@ev-ai/agent-hook 1.0.6 → 1.0.7

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.
package/COLLECTED-DATA.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Collected data
2
2
 
3
- What `@evalon-ai/agent-hook` POSTs to the Evalon collector (`POST /{orgToken}/hook`, default `https://hooks.evalon.ai/{orgToken}/hook`). Auth is the org path id in the URL — no Bearer header and not in the JSON body. See [README.md](./README.md) for install and privacy defaults.
3
+ What `@ev-ai/agent-hook` POSTs to the ev-ai collector (`POST /{orgToken}/hook`, default `https://hooks.ev-ai.ai/{orgToken}/hook`). Auth is the org path id in the URL — no Bearer header and not in the JSON body. See [README.md](./README.md) for install and privacy defaults.
4
4
 
5
5
  ## Tracked events
6
6
 
@@ -10,17 +10,20 @@ What `@evalon-ai/agent-hook` POSTs to the Evalon collector (`POST /{orgToken}/ho
10
10
  | `session_end` | Session stops |
11
11
  | `tool_invoked` | Tool, skill, MCP, shell, or file-edit hook fires |
12
12
 
13
- Every event also carries: UTC timestamp, `installation_id`, runner `platform` (`claude` / `cursor` / `codex`), `platform_agent_id` (Layer-1 inventory join key: `{owner}/{repo}:{scopePath/}{markerDir}`, e.g. `acme/my-app:.claude` or `acme/my-app:apps/web/.cursor`), `session_id`, `turn_id`, raw `runner_event` name, `agent_hook_version`, `host_arch`, and `node_version`.
13
+ Every event also carries: UTC timestamp, `installation_id` (per-machine under `~/.ev-ai/agent-hook/installation.json`; on ephemeral CI/cloud homes derived from platform seeds such as `GITHUB_REPOSITORY_ID`+`GITHUB_ACTOR` / `CODESPACE_NAME`, or pinned via `EV_AI_HOOK_INSTALLATION_ID`), runner `platform` (`claude` / `cursor` / `codex`), `platform_agent_id` (Layer-1 inventory join key: `{owner}/{repo}:{scopePath/}{markerDir}`, e.g. `acme/my-app:.claude` or `acme/my-app:apps/web/.cursor`), `session_id`, `turn_id`, raw `runner_event` name, `agent_hook_version`, `host_arch`, `node_version`, and `build_ms` (wall-clock milliseconds to assemble the envelope before the collector POST; not tool/session duration).
14
14
 
15
15
  ## Tracked data points
16
16
 
17
17
  ### On `session_start`
18
18
 
19
- - **Host** — hostname, OS / version, username, shell, TTY, runtime context (interactive / CI / container / cron), optional virt and cloud provider / region / instance id. Cloud metadata is probed only for non-interactive contexts (CI, container, cron, GitHub Actions); interactive laptop sessions skip IMDS entirely. Non-interactive probes are cached locally for 24h per context.
19
+ - **Host** — hostname, OS / version, username, shell, TTY, runtime context (`interactive` / `github_actions` / `claude_remote` / `cursor_cloud` / `codespaces` / `managed` / `container` / `cron`). `managed` covers generic `CI=true` plus named platforms that often omit it (`TF_BUILD`, `JENKINS_URL`, `BUILDKITE`, `CIRCLECI`, `GITLAB_CI`, `CODEBUILD_BUILD_ID`, `DRONE`, …). `container` covers `/.dockerenv`, k8s (`KUBERNETES_SERVICE_HOST`), and VS Code / Codespaces-style remote containers (`REMOTE_CONTAINERS` / `DEVCONTAINER`). Optional virt and cloud provider / region / instance id. Cloud metadata is probed only for non-interactive contexts; interactive laptop sessions skip IMDS entirely. Non-interactive probes are cached locally for 24h per context.
20
20
  - **Git** — origin remote (credentials stripped), branch, HEAD SHA, dirty flag
21
- - **Env (allowlist only)** — CI markers (`CI`, `GITHUB_*`, `GITLAB_CI`, …), `NODE_ENV`, `TERM_PROGRAM`, vendor base-URL overrides (`ANTHROPIC_BASE_URL`, `OPENAI_BASE_URL`, …), Claude Bedrock/Vertex flags. API keys and proxy vars are never read. Gateway URLs have embedded credentials and credential-shaped query params (`key`, `api-key`, `token`, `sig`, …) redacted.
21
+ - **Env (allowlist only)** — CI markers (`CI`, `GITHUB_*`, `GITLAB_CI`, `CIRCLECI`, `BUILDKITE`, `TF_BUILD`, …), actor identity markers (`GITHUB_ACTOR`, `GITLAB_USER_*`, `BUILD_REQUESTEDFOR*`, `BUILDKITE_BUILD_CREATOR*`, `BUILD_USER*`, `CHANGE_AUTHOR*`, `CIRCLE_USERNAME`, `CODEBUILD_INITIATOR`, `DRONE_COMMIT_AUTHOR*`, `EV_AI_HOOK_OPERATOR_*`, `GIT_AUTHOR_*`, `GIT_COMMITTER_*`, `EMAIL`, …), cloud session markers (`CLAUDE_CODE_REMOTE`, `CURSOR_AGENT`, `CODESPACES`), `NODE_ENV`, `TERM_PROGRAM`, vendor base-URL overrides (`ANTHROPIC_BASE_URL`, `OPENAI_BASE_URL`, …), Claude Bedrock/Vertex flags. API keys and proxy vars are never read. Gateway URLs have embedded credentials and credential-shaped query params (`key`, `api-key`, `token`, `sig`, …) redacted.
22
22
  - **MCP inventory** — declared server **names** (and discovery source), not commands/URLs/env
23
23
  - **User-scope config** — `cli_version` (claude / agent|cursor-agent / codex `--version`); model (Claude; SessionStart stdin `model` preferred over settings-file), Claude-only `claude_version` mirror; presence/size of global settings / memory / MCP files; name+size listings of global skills, commands, subagents, rules (full listing when the hash changed or every 10th session start as a repair re-send; capped at 500 entries per list with `truncated: true` when capped). File **contents** are not sent.
24
+ - **User spec (home-dir components)** — per-component delta of skills / commands / rules / memory / subagents / hooks / MCP servers / plugins from `~/.claude`, `~/.cursor`, `~/.codex`, `~/.agents`. Walked on the **first** `session_start` for a runner and again only after a **14-hour cooldown** (`user_spec_collected_at_ms` in `self-config-cache.json`); mid-cooldown session starts skip the home walk and omit `user_spec*` / `operator`. Each upsert row carries `kind`, path-derived `name`, home-relative `path`, capped file `text` (≤20_000 chars) for file-backed kinds, `content_hash`, `origin` (`user` or `plugin:<name>@<marketplace>`), `enabled`, optional `trigger` / `attributes`. Frontmatter fields (`name`, `description`, …) are not parsed on the client — the collector derives them from `text`. Only **changed or new** components are sent (`user_spec`); removals are explicit tombstones (`user_spec_removed: [{ path, name }]`). Unchanged scope after a cooldown refresh → hash/count/truncated scalars alone. First walk is a full authoritative snapshot (`user_spec_full: true`). File `text` is shipped **once per `content_hash`** (later sends omit the body when that hash was already delivered); under the ~300 KiB user-spec byte budget, overflowing bodies are deferred (`user_spec_text_deferred`) before rows are dropped. Self-config / operator caches commit only after a successful collector POST. Hook rows send `action_kind` + `action_hash` only — never the command string. MCP rows send name + transport only. Plugin rows never include `installPath` / `projectPath`. Disabled with `EV_AI_HOOK_USER_SPEC=off`.
25
+ - **Operator identity** — on the first user-spec collect for an installation (and again when the 14-hour user-spec cooldown elapses): `git_user_name` / `git_user_email` from `git config` when set (`identity_source: "git_config"`). When unset, tries `GIT_AUTHOR_NAME`/`GIT_AUTHOR_EMAIL`, then `GIT_COMMITTER_*`, then `EMAIL` (`identity_source: "git_env"`). Bot-shaped git identity (`*[bot]*`, `action@github.com`, `noreply@anthropic.com`, `cursoragent@cursor.com`, …) is skipped so CI/cloud actor env vars can win: explicit `EV_AI_HOOK_OPERATOR_NAME` / `EV_AI_HOOK_OPERATOR_EMAIL` → `identity_source: "configured"`; then `GITHUB_ACTOR` / `GITHUB_TRIGGERING_ACTOR` / `GITHUB_USER` → `"github"`; `GITLAB_USER_*` → `"gitlab"`; Azure DevOps `BUILD_REQUESTEDFOR*` → `"azure_devops"`; Buildkite `BUILDKITE_BUILD_CREATOR*` → `"buildkite"`; Jenkins `BUILD_USER*` / `CHANGE_AUTHOR*` → `"jenkins"`; CircleCI `CIRCLE_USERNAME` → `"circleci"`; CodeBuild `CODEBUILD_INITIATOR` → `"codebuild"`; Drone/Woodpecker `DRONE_COMMIT_AUTHOR*` → `"drone"`. When those are also absent, falls back to the HEAD commit author from `git log -1` (`identity_source: "git_log"`). Claude Code remote (`CLAUDE_CODE_REMOTE`) and Cursor cloud (`CURSOR_AGENT`) without a git or CI actor are tagged `identity_source: "cloud"` with null name/email (no synthetic email). CI/cloud actor sources also set `platform_login` (GitHub/GitLab/CircleCI/CodeBuild/Jenkins `BUILD_USER_ID`/Drone login) so the collector can join installations to members without inventing a noreply email. Omitted while user-spec is on cooldown and in steady state when unchanged. Never invents an OS username. Disabled with the same `EV_AI_HOOK_USER_SPEC=off` opt-out.
26
+ - **Cloud identity bootstrap** — Cursor cloud agents do not fire `sessionStart`. On the first `tool_invoked` / skill event when operator identity has never been sent (any runtime context — cloud VMs with a pseudo-TTY often look `interactive`), the hook POSTs a lightweight `session_start` (`run_meta.trigger: cloud_identity_bootstrap`) with host/context/operator — no home user-spec walk, and no `cli_version` / `model` / `user_scope` / `hook_input` (those stay unset so the collector never treats bootstrap nulls as a probed empty config). Debounced in-process and across concurrent hook processes via an exclusive claim lock beside `installation.json` (`cloud-bootstrap.lock`); skipped when `EV_AI_HOOK_USER_SPEC=off`.
24
27
  - **Permission keys (Claude)** — each rule as `{ key, mode }` where `mode` is the list it came from (`allow` / `deny` / `ask`), so a blocked rule is never mistaken for a permitted one. Absolute POSIX / Windows / `~`-anchored paths inside a rule are replaced with `<path>` (`Bash(find /Users/me/repo -name x)` → `Bash(find <path> -name x)`) — the rule shape is the posture signal, the operator's home layout is not. Capped at 200 rules, 200 characters each.
25
28
  - **Allowlisted hook metadata** — see below (includes SessionStart `model`, `permission_mode`, …)
26
29
 
@@ -46,9 +49,11 @@ Every event also carries: UTC timestamp, `installation_id`, runner `platform` (`
46
49
 
47
50
  ### Hook metadata (default)
48
51
 
49
- From runner stdin, only: session/conversation/turn ids (`prompt_id` / `prompt.id` / `generation_id` / `turn_id`), event name/source, status / `stop_reason` / SessionEnd `reason`, tool/skill name, `tool_use_id`, `permission_mode`, active `model` / Cursor `model_id`, `agent_id` / `agent_type`, Cursor `subagent_id` / `subagent_type` / `subagent_model` / `is_parallel_worker`, `effort` / `effort.level`, `duration_ms` / `duration`, failure category fields (`failure_type`, `is_interrupt` — the message fields `error`, `error_details`, `error_message` are **not** forwarded), Claude `UserPromptExpansion` metadata (`command_name`, `expansion_type`, `command_source` — never `prompt` / `command_args`), and git-root-relative `cwd_relative` (never absolute `cwd`). Session titles, tool args, prompts, shell commands, file contents, and tool result bodies are dropped unless the operator opts into full capture (`capture_hook_input: "full"` or `EVALON_HOOK_CAPTURE_FULL_INPUT=1`).
52
+ From runner stdin, only: session/conversation/turn ids (`prompt_id` / `prompt.id` / `generation_id` / `turn_id`), event name/source, status / `stop_reason` / SessionEnd `reason`, tool/skill name, `tool_use_id`, `permission_mode`, active `model` / Cursor `model_id`, `agent_id` / `agent_type`, Cursor `subagent_id` / `subagent_type` / `subagent_model` / `is_parallel_worker`, `effort` / `effort.level`, `duration_ms` / `duration`, failure category fields (`failure_type`, `is_interrupt` — the message fields `error`, `error_details`, `error_message` are **not** forwarded), Claude `UserPromptExpansion` metadata (`command_name`, `expansion_type`, `command_source` — never `prompt` / `command_args`), and git-root-relative `cwd_relative` (never absolute `cwd`). Session titles, tool args, prompts, shell commands, file contents, and tool result bodies are dropped unless the operator opts into full capture (`capture_hook_input: "full"` or `EV_AI_HOOK_CAPTURE_FULL_INPUT=1`).
50
53
 
51
- Install wires Claude `SessionStart` / `UserPromptExpansion` / `PreToolUse` (all tools) / `PostToolUse` / `PostToolUseFailure` / `PermissionDenied` / `Stop` / `StopFailure` / `SessionEnd` / `SubagentStart` / `SubagentStop`; Cursor `sessionStart` / `beforeSubmitPrompt` / `preToolUse` / `postToolUse` / `postToolUseFailure` / `subagentStart` / `subagentStop` / `stop`; Codex `SessionStart` / `UserPromptSubmit` / `PreToolUse` (all tools) / `PostToolUse` / `Stop`. Re-run `install` to upgrade existing repos (Cursor upgrades strip retired `beforeShellExecution` / `afterFileEdit` / `beforeMCPExecution` Evalon hooks).
54
+ Install wires Claude `SessionStart` / `UserPromptExpansion` / `PreToolUse` (all tools) / `PostToolUse` / `PostToolUseFailure` / `PermissionDenied` / `Stop` / `StopFailure` / `SessionEnd` / `SubagentStart` / `SubagentStop`; Cursor `sessionStart` / `beforeSubmitPrompt` / `preToolUse` / `postToolUse` / `postToolUseFailure` / `subagentStart` / `subagentStop` / `stop`; Codex `SessionStart` / `UserPromptSubmit` / `PreToolUse` (all tools) / `PostToolUse` / `Stop`. Re-run `install` to upgrade existing repos (Cursor upgrades strip retired `beforeShellExecution` / `afterFileEdit` / `beforeMCPExecution` ev-ai hooks).
55
+
56
+ When Cursor loads Claude (or Codex) file hooks as third-party configs alongside `.cursor/hooks.json`, the binary drops the foreign `--runner` twin so `platform` stays `cursor` and events are not duplicated. Claude Code and Codex hosts are unaffected.
52
57
 
53
58
  ## PII we do not send
54
59
 
@@ -57,11 +62,13 @@ Username and hostname *are* sent (per-member usage for the installing org). The
57
62
  - Prompts, chat transcripts, session titles, and keystrokes
58
63
  - Tool arguments, shell commands, and file / code contents
59
64
  - Tool error messages, stderr, and result bodies (a failure **class** is sent, never the message)
60
- - Contents of skills, rules, commands, memory, or settings files (names and sizes only)
65
+ - Contents of skills, rules, commands, memory, or settings files **outside** the user-spec path (user-scope name+size listings still omit bodies). User-spec file-backed components **do** send capped `text` (once per content hash; may be deferred under the byte budget); `description` is derived server-side
66
+ - Hook command / prompt strings from the home directory (only `action_kind` + `action_hash`)
61
67
  - API keys, tokens, and other secret env vars
62
68
  - HTTP(S) proxy credentials and proxy env vars
63
69
  - Embedded credentials in git remotes and gateway URLs (`user:pass@` stripped; credential-shaped query params redacted)
64
- - MCP server commands, args, env blocks, and URLs (name/type only)
65
- - Email addresses, full names, or employee IDs beyond what appears in OS username / hostname
66
- - Home-directory paths (including inside Claude permission rules), local IP addresses, and listening ports
70
+ - MCP server commands, args, env blocks, and URLs (name/transport only)
71
+ - Plugin `installPath` / `projectPath` (absolute / home paths)
72
+ - OS username as an identity substitute (git `user.name` / `user.email`, CI actor logins via `platform_login`, or CI emails are sent when available; OS username is still only present via the existing host username field)
73
+ - Home-directory absolute paths (rewritten to home-relative before send), local IP addresses, and listening ports
67
74
  - Data to any endpoint other than the org-configured collector
package/README.md CHANGED
@@ -1,30 +1,19 @@
1
- # @evalon-ai/agent-hook
1
+ # @ev-ai/agent-hook
2
2
 
3
- Cross-runner runtime telemetry hook for **Claude Code**, **Cursor**, and **OpenAI Codex**. Each session (and selected tool/MCP events) POSTs a runtime envelope to your Evalon collector at `POST /{orgToken}/hook`.
3
+ Cross-runner runtime telemetry hook for **Claude Code**, **Cursor**, and **OpenAI Codex**. Each session (and selected tool/MCP events) POSTs a runtime envelope to your ev-ai collector at `POST /{orgToken}/hook`.
4
4
 
5
5
  ## What this is (and isn't)
6
6
 
7
- This is an **opt-in, first-party observability agent** that an Evalon AI customer installs on their own developers' machines / CI to get an inventory and runtime view of **their own org's AI coding-agent usage**. It is the AI-coding-agent equivalent of an EDR/telemetry sensor or an APM agent: the org deploys it, on its own hosts, to send data **to its own collector**.
7
+ This is an **opt-in, first-party observability agent** that an ev-ai customer installs on their own developers' machines / CI to get an inventory and runtime view of **their own org's AI coding-agent usage**. It is the AI-coding-agent equivalent of an EDR/telemetry sensor or an APM agent: the org deploys it, on its own hosts, to send data **to its own collector**.
8
8
 
9
- - **Data goes to the customer's own collector.** The destination is the org's Evalon endpoint (default `https://hooks.evalon.ai/{orgToken}/hook`, or a self-hosted collector via `--url`). It is not a third party from the org's perspective — the customer is the data controller.
10
- - **It is consent-based and removable.** Nothing installs silently: the operator enables the Evalon plugins (or runs file-wiring `install`), and uninstall / plugin disable removes Evalon wiring. Non-managed hooks can be removed locally by the developer at any time.
9
+ - **Data goes to the customer's own collector.** The destination is the org's ev-ai endpoint (default `https://hooks.ev-ai.ai/{orgToken}/hook`, or a self-hosted collector via `--url`). It is not a third party from the org's perspective — the customer is the data controller.
10
+ - **It is consent-based and removable.** Nothing installs silently: the operator enables the ev-ai plugins (or runs file-wiring `install`), and uninstall / plugin disable removes ev-ai wiring. Non-managed hooks can be removed locally by the developer at any time.
11
11
  - **Collection is deliberately minimized.** `hook_input` defaults to an allowlist of safe metadata (session/tool ids, status) — tool arguments, prompts, file contents, and shell commands are dropped unless the operator explicitly opts into full capture. `env_vars` is a fixed allowlist of non-secret CI/runtime markers; API keys and proxy vars are never read. See [Privacy defaults](#privacy-defaults).
12
12
  - **What it is not:** it is not spyware, not a keylogger, and not a data broker. It does not collect keystrokes, file contents, or credentials, and it does not exfiltrate to any endpoint the operator did not configure.
13
13
 
14
- ## Registry access
15
-
16
- The package is distributed on **GitHub Packages**, so every machine that installs it needs these two lines in `~/.npmrc` with a token that can read packages from the `evalon-ai` org:
17
-
18
- ```
19
- @evalon-ai:registry=https://npm.pkg.github.com
20
- //npm.pkg.github.com/:_authToken=<TOKEN>
21
- ```
22
-
23
- Put the token only on the `_authToken` line — never inside the registry URL.
24
-
25
14
  ## Install
26
15
 
27
- **Primary path:** enable the Evalon **runner plugins** (Claude / Cursor / Codex) from the hosted marketplace [`evalon-ai/marketplace`](https://github.com/evalon-ai/marketplace). Their hooks pin `npx -y @evalon-ai/agent-hook@<ver> --runner …`. Your repo commits only a shared `collector_url` manifest plus plugin enablement — not per-event blocks in `.claude/settings.json` / `.cursor/hooks.json` / `.codex/hooks.json`.
16
+ **Primary path:** enable the ev-ai **runner plugins** (Claude / Cursor / Codex) from the hosted marketplace. Their hooks pin `npx -y @ev-ai/agent-hook@<ver> --runner …`. Your repo commits only a shared `collector_url` manifest plus plugin enablement — not per-event blocks in `.claude/settings.json` / `.cursor/hooks.json` / `.codex/hooks.json`.
28
17
 
29
18
  **Fallback:** the `install` CLI merges hooks into those three config files directly.
30
19
 
@@ -33,21 +22,21 @@ Put the token only on the `_authToken` line — never inside the registry URL.
33
22
  1. Write the org destination (manifest only):
34
23
 
35
24
  ```bash
36
- npx @evalon-ai/agent-hook@X.Y.Z configure \
37
- --url https://hooks.evalon.ai/<your-org-path-id>/hook
25
+ npx @ev-ai/agent-hook@X.Y.Z configure \
26
+ --url https://hooks.ev-ai.ai/<your-org-path-id>/hook
38
27
  ```
39
28
 
40
29
  `--url` must be the full ingest URL ending in `/{orgToken}/hook`. Prefer a long opaque hex org path id (64 lowercase hex chars). Safe to commit in private repos — auth is in the URL path, not a Bearer header.
41
30
 
42
- 2. Enable the Claude / Cursor / Codex plugins per [`evalon-ai/marketplace`](https://github.com/evalon-ai/marketplace).
43
- 3. Commit the shared manifest (`.claude/evalon-runtime-report.json`) plus plugin enablement **or** the file-wired hook configs (not both for the same events). Restart runners.
31
+ 2. Enable the Claude / Cursor / Codex plugins from the hosted marketplace.
32
+ 3. Commit the shared manifest (`.claude/ev-ai-runtime-report.json`) plus plugin enablement **or** the file-wired hook configs (not both for the same events). Restart runners.
44
33
 
45
34
  Plugins pin an exact package version, never `@latest`.
46
35
 
47
- **Migrating from file-wiring:** strip Evalon per-event blocks while keeping the manifest:
36
+ **Migrating from file-wiring:** strip ev-ai per-event blocks while keeping the manifest:
48
37
 
49
38
  ```bash
50
- npx @evalon-ai/agent-hook@X.Y.Z migrate-to-plugin
39
+ npx @ev-ai/agent-hook@X.Y.Z migrate-to-plugin
51
40
  ```
52
41
 
53
42
  Then enable plugins. Do not leave both plugin and file hooks active — that double-POSTs.
@@ -61,93 +50,95 @@ Then enable plugins. Do not leave both plugin and file hooks active — that dou
61
50
  One-time wiring by the repo owner. Teammates pull committed hook configs and need **Node only**.
62
51
 
63
52
  ```bash
64
- npx @evalon-ai/agent-hook@latest install \
65
- --url https://hooks.evalon.ai/<your-org-path-id>/hook
53
+ npx @ev-ai/agent-hook@latest install \
54
+ --url https://hooks.ev-ai.ai/<your-org-path-id>/hook
66
55
  ```
67
56
 
68
57
  When Claude Code already has native OTEL enabled (managed/user/project settings), install **skips** the Claude hook to avoid duplicate events. Cursor and Codex are still wired. Override with `--force`:
69
58
 
70
59
  ```bash
71
- npx @evalon-ai/agent-hook@latest install \
72
- --url https://hooks.evalon.ai/<token>/hook \
60
+ npx @ev-ai/agent-hook@latest install \
61
+ --url https://hooks.ev-ai.ai/<token>/hook \
73
62
  --force
74
63
  ```
75
64
 
76
65
  Skip a vendor entirely with `--no-claude`, `--no-cursor`, or `--no-codex`:
77
66
 
78
67
  ```bash
79
- npx @evalon-ai/agent-hook@latest install \
80
- --url https://hooks.evalon.ai/<token>/hook \
68
+ npx @ev-ai/agent-hook@latest install \
69
+ --url https://hooks.ev-ai.ai/<token>/hook \
81
70
  --no-cursor --no-codex
82
71
  ```
83
72
 
73
+ Keep Claude and Cursor both wired. Cursor also loads `.claude/settings.json` as third-party hooks; the binary suppresses those Claude/Codex-tagged twin invocations when it detects a Cursor host, so each event posts once as `platform: cursor`. Real Claude Code sessions still use the Claude hooks unchanged.
74
+
84
75
  Wired command shape (auth is in the committed `collector_url`). The per-event command is **pinned to the installer's version** (not `@latest`):
85
76
 
86
77
  ```bash
87
- npx -y @evalon-ai/agent-hook@1.0.6 --runner cursor
78
+ npx -y @ev-ai/agent-hook@1.0.6 --runner cursor
88
79
  ```
89
80
 
90
- You can optionally put the collector URL on the hook command itself — `--url` (or `--token` + optional `--base-url`) overrides any shared manifest, so `.claude/evalon-runtime-report.json` is not required:
81
+ You can optionally put the collector URL on the hook command itself — `--url` (or `--token` + optional `--base-url`) overrides any shared manifest, so `.claude/ev-ai-runtime-report.json` is not required:
91
82
 
92
83
  ```json
93
84
  {
94
- "command": "npx -y @evalon-ai/agent-hook@1.0.6 --runner claude --url 'https://hooks.evalon.ai/<orgToken>/hook'"
85
+ "command": "npx -y @ev-ai/agent-hook@1.0.6 --runner claude --url 'https://hooks.ev-ai.ai/<orgToken>/hook'"
95
86
  }
96
87
  ```
97
88
 
98
- **Commit** `.claude/evalon-runtime-report.json` (contains `collector_url`) plus `.claude/settings.json`, `.cursor/hooks.json`, and `.codex/hooks.json` when using this path (or omit the manifest if every wired command already has `--url`). Do **not** also enable the Evalon plugins for the same events — that double-posts.
89
+ **Commit** `.claude/ev-ai-runtime-report.json` (contains `collector_url`) plus `.claude/settings.json`, `.cursor/hooks.json`, and `.codex/hooks.json` when using this path (or omit the manifest if every wired command already has `--url`). Do **not** also enable the ev-ai plugins for the same events — that double-posts.
99
90
 
100
- Install is **additive**: existing non-Evalon hooks are kept; re-install replaces only Evalon-owned entries. Uninstall removes only Evalon entries (and the Evalon manifest).
91
+ Install is **additive**: existing non-ev-ai hooks are kept; re-install replaces only ev-ai-owned entries. Uninstall removes only ev-ai entries (and the ev-ai manifest).
101
92
 
102
93
  ### Alternative — CDN binary (no Node at hook time)
103
94
 
104
95
  For environments where Node is not on PATH when runners fire hooks (typically with file-wiring or a future plugin that bundles a binary):
105
96
 
106
97
  ```bash
107
- curl -fsSL https://cdn.evalon.ai/agent-hook/install.sh | sh -s -- -- \
108
- --url https://hooks.evalon.ai/<token>/hook
98
+ curl -fsSL https://cdn.ev-ai.ai/agent-hook/install.sh | sh -s -- -- \
99
+ --url https://hooks.ev-ai.ai/<token>/hook
109
100
  ```
110
101
 
111
102
  Pin a specific release:
112
103
 
113
104
  ```bash
114
- AGENT_HOOK_VERSION=1.0.6 curl -fsSL https://cdn.evalon.ai/agent-hook/install.sh | sh -s -- -- \
115
- --url https://hooks.evalon.ai/<token>/hook
105
+ AGENT_HOOK_VERSION=1.0.6 curl -fsSL https://cdn.ev-ai.ai/agent-hook/install.sh | sh -s -- -- \
106
+ --url https://hooks.ev-ai.ai/<token>/hook
116
107
  ```
117
108
 
118
- The installer downloads a **standalone binary** (~50–100MB) for your OS/arch, verifies SHA256, caches it under `~/.evalon/agent-hook/<version>/`, copies it into the git repo at `.evalon/agent-hook/evalon-agent-hook`, and wires all three runners with `--delivery binary` (default for the compiled installer).
109
+ The installer downloads a **standalone binary** (~50–100MB) for your OS/arch, verifies SHA256, caches it under `~/.ev-ai/agent-hook/<version>/`, copies it into the git repo at `.ev-ai/agent-hook/ev-ai-agent-hook`, and wires all three runners with `--delivery binary` (default for the compiled installer).
119
110
 
120
111
  Wired command shape (git-root-relative path + `--runner`):
121
112
 
122
113
  ```bash
123
- "$(git rev-parse --show-toplevel)/.evalon/agent-hook/evalon-agent-hook" --runner cursor
114
+ "$(git rev-parse --show-toplevel)/.ev-ai/agent-hook/ev-ai-agent-hook" --runner cursor
124
115
  ```
125
116
 
126
- **Install per machine** for the binary path: each collaborator runs install once to download their platform binary into `.evalon/agent-hook/` (gitignored).
117
+ **Install per machine** for the binary path: each collaborator runs install once to download their platform binary into `.ev-ai/agent-hook/` (gitignored).
127
118
 
128
119
  Force npx delivery from Node even when a global binary pin exists:
129
120
 
130
121
  ```bash
131
- npx @evalon-ai/agent-hook@latest install \
132
- --url https://hooks.evalon.ai/<token>/hook \
122
+ npx @ev-ai/agent-hook@latest install \
123
+ --url https://hooks.ev-ai.ai/<token>/hook \
133
124
  --delivery npx
134
125
  ```
135
126
 
136
127
  ### Identity and runtime notes
137
128
 
138
- Each developer's `installation_id` is created on first hook fire and stored under `~/.evalon/agent-hook/installations/<repo-key>.json`.
129
+ Each developer's `installation_id` is created on first hook fire and stored once per machine under `~/.ev-ai/agent-hook/installation.json` (shared across all repos on that machine). Ephemeral CI/cloud homes (no durable `~/.ev-ai`) derive a stable id from platform seeds (e.g. GitHub Actions `GITHUB_REPOSITORY_ID` + `GITHUB_ACTOR`, Codespaces `CODESPACE_NAME`) so collector rows do not churn every run. Pin explicitly with `EV_AI_HOOK_INSTALLATION_ID` (8–64 chars `[A-Za-z0-9._-]`) when the environment has no actor seed (Claude Code remote / Cursor cloud).
139
130
 
140
- Per-event execution uses `npx` (primary) or the pinned binary (CDN path). The runner-facing process **acks immediately** (`{"continue":true}` + exit 0) after draining stdin and spawning a detached `__work` child that collects + POSTs — **except teardown events**, which stay in-process and await the HTTP POST so a runner that tears down the process tree on exit cannot kill the worker mid-flight. Teardown = Claude `SessionEnd` / `StopFailure`, Codex `Stop` (its only end signal), and `SubagentStop`. Per-turn Claude `Stop` / Cursor `stop` fire at the end of **every turn** (not teardown), so they detach like tool events and never block the runner between turns. Set `EVALON_HOOK_SYNC=1` to keep all events in-process for debugging.
131
+ Per-event execution uses `npx` (primary) or the pinned binary (CDN path). The runner-facing process **acks immediately** (`{"continue":true}` + exit 0) after draining stdin and spawning a detached `__work` child that collects + POSTs — **except teardown events**, which stay in-process and await the HTTP POST so a runner that tears down the process tree on exit cannot kill the worker mid-flight. Teardown = Claude `SessionEnd` / `StopFailure`, Codex `Stop` (its only end signal), and `SubagentStop`. Per-turn Claude `Stop` / Cursor `stop` fire at the end of **every turn** (not teardown), so they detach like tool events and never block the runner between turns. Set `EV_AI_HOOK_SYNC=1` to keep all events in-process for debugging.
141
132
 
142
133
  ### Gitignore (recommended)
143
134
 
144
135
  ```gitignore
145
- /.evalon/
136
+ /.ev-ai/
146
137
  ```
147
138
 
148
- Do **not** gitignore `.claude/evalon-runtime-report.json` when using a committed org path id — teammates need it to post without env vars. Keep the repo private; rotate the path id via your org settings if it leaks.
139
+ Do **not** gitignore `.claude/ev-ai-runtime-report.json` when using a committed org path id — teammates need it to post without env vars. Keep the repo private; rotate the path id via your org settings if it leaks.
149
140
 
150
- For the **plugin** path, do not add Evalon per-event hooks to `.claude/settings.json` / `.cursor/hooks.json` / `.codex/hooks.json`. For the **file-wiring** fallback, add those files only if your repo does not already track other hook settings you need to share.
141
+ For the **plugin** path, do not add ev-ai per-event hooks to `.claude/settings.json` / `.cursor/hooks.json` / `.codex/hooks.json`. For the **file-wiring** fallback, add those files only if your repo does not already track other hook settings you need to share.
151
142
 
152
143
  ## Fail-open contract
153
144
 
@@ -156,42 +147,42 @@ For the **plugin** path, do not add Evalon per-event hooks to `.claude/settings.
156
147
  - Teardown events stay in-process (sync POST) — Claude `SessionEnd` / `StopFailure`, Codex `Stop`, and `SubagentStop`, because the runner may kill detached children when the session/worker tree is torn down
157
148
  - POST / spawn failures log to stderr only
158
149
 
159
- Debug envelope logging: `EVALON_HOOK_DEBUG=1` (redacted summary). Full envelope: `EVALON_HOOK_DEBUG=full`. Force all events in-process: `EVALON_HOOK_SYNC=1`.
150
+ Debug envelope logging: `EV_AI_HOOK_DEBUG=1` (redacted summary). Full envelope: `EV_AI_HOOK_DEBUG=full`. Force all events in-process: `EV_AI_HOOK_SYNC=1`.
160
151
 
161
152
  ## Privacy defaults
162
153
 
163
154
  Full field-by-field inventory of what is POSTed: [COLLECTED-DATA.md](./COLLECTED-DATA.md).
164
155
 
165
- - **`hook_input`**: allowlisted metadata only (`session_id`, `tool_name`, `status`, …). Tool args / prompts / session titles are dropped. Opt-in full stdin: untracked operator manifest `capture_hook_input: "full"` or `EVALON_HOOK_CAPTURE_FULL_INPUT=1` (still size-capped). A **git-tracked** (committed) manifest cannot set `full` — use the env var or an untracked operator manifest instead.
156
+ - **`hook_input`**: allowlisted metadata only (`session_id`, `tool_name`, `status`, …). Tool args / prompts / session titles are dropped. Opt-in full stdin: untracked operator manifest `capture_hook_input: "full"` or `EV_AI_HOOK_CAPTURE_FULL_INPUT=1` (still size-capped). A **git-tracked** (committed) manifest cannot set `full` — use the env var or an untracked operator manifest instead.
166
157
  - **`env_vars`**: fixed allowlist only (CI markers, `GITHUB_*` context, vendor base-URL overrides). Gateway URL values (`*_BASE_URL`, etc.) are sent with host/path and non-sensitive query keys for proxy-substitution detection; embedded URL credentials (`user:pass@`) and credential-shaped query params (`key`, `api-key`, `token`, `sig`, …) are redacted. API keys and HTTP proxy vars are never read.
167
158
  - **Transport**: collector URL must be `https` (or `http://localhost` / `127.0.0.1`, which is allowed only so a collector can be exercised on the same machine). Cleartext remote URLs are blocked (fail-open, no POST).
168
159
 
169
160
  ## Uninstall
170
161
 
171
- **Plugin path:** disable / uninstall the Evalon marketplace plugins, then remove or rotate the shared manifest.
162
+ **Plugin path:** disable / uninstall the ev-ai marketplace plugins, then remove or rotate the shared manifest.
172
163
 
173
- **File-wiring → plugin:** keep the manifest, strip only Evalon file hooks:
164
+ **File-wiring → plugin:** keep the manifest, strip only ev-ai file hooks:
174
165
 
175
166
  ```bash
176
- npx @evalon-ai/agent-hook migrate-to-plugin
167
+ npx @ev-ai/agent-hook migrate-to-plugin
177
168
  ```
178
169
 
179
170
  **File-wiring full uninstall** (also deletes the shared manifest):
180
171
 
181
172
  ```bash
182
- npx @evalon-ai/agent-hook uninstall
173
+ npx @ev-ai/agent-hook uninstall
183
174
  ```
184
175
 
185
176
  Or via the CDN-installed binary:
186
177
 
187
178
  ```bash
188
- "$HOME/.evalon/agent-hook/current/evalon-agent-hook" uninstall
179
+ "$HOME/.ev-ai/agent-hook/current/ev-ai-agent-hook" uninstall
189
180
  ```
190
181
 
191
182
  Or:
192
183
 
193
184
  ```bash
194
- curl -fsSL https://cdn.evalon.ai/agent-hook/install.sh | sh -s -- uninstall
185
+ curl -fsSL https://cdn.ev-ai.ai/agent-hook/install.sh | sh -s -- uninstall
195
186
  ```
196
187
 
197
- `uninstall` removes Evalon-owned hook entries from Claude/Cursor/Codex config files (leaves other hooks intact) and deletes `evalon-runtime-report.json` manifest(s) in the current git repo. Does not remove `~/.evalon/agent-hook/` (pinned binary and per-machine identity).
188
+ `uninstall` removes ev-ai-owned hook entries from Claude/Cursor/Codex config files (leaves other hooks intact) and deletes `ev-ai-runtime-report.json` manifest(s) in the current git repo. Does not remove `~/.ev-ai/agent-hook/` (pinned binary) or `~/.ev-ai/agent-hook/` (per-machine identity).
package/dist/cli.mjs CHANGED
@@ -1,19 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import{realpathSync as $s}from"node:fs";import{resolve as Bs}from"node:path";import{fileURLToPath as Ks,pathToFileURL as Gs}from"node:url";var Ln="https://hooks.evalon.ai";function Z(e,t=Ln){let n=t.replace(/\/+$/,""),o=e.trim();return`${n}/${o}/hook`}var D=".claude/evalon-runtime-report.json",Ye="node_modules/@evalon/agent-hook/dist/hook.mjs",P="evalon-agent-hook",Xe="https://cdn.evalon.ai/agent-hook",ye=`current/${P}`,Se=`.evalon/agent-hook/${P}`,qe=5e3,Ze=5e3,Ee=3e3;var ve=3e3,Qe=1500,et=4*1024,tt=32*1024,Un=4*1024,b="1.0.6",Q=`@evalon-ai/agent-hook@${b}`,nt="Evalon runtime report",ot=["claude","cursor","codex"];import{chmodSync as xt,cpSync as bt,existsSync as C,mkdirSync as Pe,readdirSync as go,readFileSync as ho,rmSync as ae,symlinkSync as _o,writeFileSync as ko}from"node:fs";import{homedir as A}from"node:os";import{basename as yo,dirname as Te,isAbsolute as So,join as f,relative as Rt,resolve as It,sep as Eo}from"node:path";import{fileURLToPath as vo}from"node:url";var jn=new Set(["localhost","127.0.0.1","[::1]","::1"]),rt=/^[A-Za-z0-9._~-]+$/;function st(e){for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n<=32||n===127||n===39)return!0}return!1}function ee(e){try{let t=new URL(e);return t.protocol==="https:"?!0:t.protocol==="http:"?jn.has(t.hostname):!1}catch{return!1}}function $(e){let t;try{t=new URL(e)}catch{return`invalid URL (got: ${e})`}if(!ee(e))return`must be https (or http on localhost / 127.0.0.1 / ::1) (got: ${e})`;let n=Fn(e);if(!n)return`must end with /{orgToken}/hook (got: ${e})`;if(!rt.test(n))return`org token must match ${rt.source} (got: ${n})`;if(st(e))return`must not contain whitespace, control characters, or single quotes (got: ${e})`;if(st(t.pathname))return`pathname must not contain whitespace, control characters, or single quotes (got: ${e})`}function B(e){return new URL(e).toString()}function Fn(e){try{let n=new URL(e).pathname.split("/").filter(o=>o.length>0);if(n.length>=2&&n[n.length-1]==="hook"){let o=n[n.length-2];return o.length>0?o:void 0}return}catch{return}}function we(e){try{let t=new URL(e),n=t.pathname.split("/").filter(o=>o.length>0);return n.length>=2&&n[n.length-1]==="hook"&&(n[n.length-2]="***",t.pathname=`/${n.join("/")}`),t.toString()}catch{return"<invalid-url>"}}function it(e){if(e.collector_url)return e.collector_url;let t=e.repo_ingest_token?.trim();return t?Z(t):""}import{createHash as Wn,randomBytes as Vn}from"node:crypto";import{existsSync as zn,mkdirSync as Yn,readFileSync as Xn,writeFileSync as qn}from"node:fs";import{homedir as oe}from"node:os";import{dirname as Zn,join as xe,resolve as Qn}from"node:path";import{randomBytes as Dn}from"node:crypto";import{existsSync as ut,mkdirSync as $n,readdirSync as Bn,renameSync as at,statSync as dt,unlinkSync as ct,writeFileSync as Kn}from"node:fs";import{basename as Gn,dirname as lt,join as ft,relative as Jn}from"node:path";function l(e){process.stderr.write(`[evalon-agent-hook] ${e}
4
- `)}function L(e,t){$n(lt(e),{recursive:!0});let n=ft(lt(e),`.${Gn(e)}.${process.pid}.${Dn(4).toString("hex")}.tmp`);try{Kn(n,t,"utf8");try{at(n,e)}catch(o){let r=o instanceof Error&&"code"in o?o.code:void 0;if(r==="EEXIST"||r==="EPERM"||r==="EACCES"){ct(e),at(n,e);return}throw o}}catch(o){try{ct(n)}catch{}throw o}}function pt(){return new Date().toISOString().replace(/\.\d{3}Z$/,"Z")}function mt(){process.stdout.write('{"continue":true}')}function g(e){let t=process.env[e];return t===void 0||t===""?void 0:t}async function te(){return new Promise(e=>{let t="";if(process.stdin.isTTY){e("");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{t+=n}),process.stdin.on("end",()=>{e(t)}),process.stdin.on("error",()=>{e(t)}),process.stdin.resume()})}async function Ie(e){return new Promise(t=>{let n="",o=!1,r=a=>{o||(o=!0,clearTimeout(s),t(a||"{}"))},s=setTimeout(()=>{r(n)},e);if(process.stdin.isTTY){r("{}");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",a=>{n+=a}),process.stdin.on("end",()=>{r(n)}),process.stdin.on("error",()=>{r(n)}),process.stdin.resume()})}async function R(e,t,n=3e3,o={}){let{execFile:r}=await import("node:child_process"),{promisify:s}=await import("node:util"),a=s(r);try{let{stdout:i}=await a(e,t,{timeout:n,windowsHide:!0,maxBuffer:1048576,cwd:o.cwd});return{ok:!0,stdout:i.trim()}}catch(i){let c=i,u=typeof c.code=="number"?c.code:typeof c.status=="number"?c.status:void 0;return{ok:!1,code:u,spawnFailed:u===void 0}}}async function h(e,t,n=3e3,o={}){let r=await R(e,t,n,o);return r.ok?r.stdout:""}async function w(e=process.cwd()){return await h("git",["rev-parse","--show-toplevel"],2e3,{cwd:e})||e}function _(e,t){try{return JSON.parse(e)}catch{return t}}function K(e){return typeof e=="string"?e:""}function N(e,t){let n=e[t];if(typeof n=="string"||typeof n=="number"||typeof n=="boolean")return n;if(!t.includes("."))return;let o=t.split("."),r=e;for(let s of o){if(r===null||typeof r!="object"||Array.isArray(r))return;r=r[s]}if(typeof r=="string"||typeof r=="number"||typeof r=="boolean")return r}function d(e,t){let n=N(e,t);return typeof n=="string"?n:""}var ne=500;function G(e,t=2){if(!ut(e))return{entries:[],truncated:!1};let n=[],o=!1,r=(s,a)=>{if(a>t||o)return;let i;try{i=Bn(s,{withFileTypes:!0})}catch{return}for(let c of i){if(o)return;let u=ft(s,c.name);if(c.isDirectory()){r(u,a+1);continue}if(c.isFile()){try{n.push({name:Jn(e,u),size:dt(u).size})}catch{continue}if(n.length>=ne){o=!0;return}}}};return r(e,1),{entries:n,truncated:o}}function J(e){return ut(e)?{present:!0,size:dt(e).size}:{present:!1,size:0}}function _t(e,t){return`${e}:${t??""}`}function be(e=oe()){return xe(e,".evalon","agent-hook")}function eo(e=oe()){return xe(be(e),"installations")}function to(e,t=oe()){return xe(eo(t),`${e}.json`)}function gt(){return Vn(8).toString("hex")}async function no(e){let n=await h("git",["config","--get","remote.origin.url"],2e3,{cwd:e})||Qn(e);return Wn("sha256").update(n).digest("hex").slice(0,16)}function oo(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[n,o]of Object.entries(e))typeof o=="string"&&o.length>0&&(t[n]=o);return Object.keys(t).length>0?t:void 0}function re(e){if(zn(e))try{let t=JSON.parse(Xn(e,"utf8"));if(typeof t.installation_id=="string"&&t.installation_id.length>0){let n=oo(t.platform_agent_ids);return{installation_id:t.installation_id,...n?{platform_agent_ids:n}:{}}}}catch{}}function kt(e,t){let o=re(e)?.platform_agent_ids?.[t];return typeof o=="string"&&o.length>0?o:void 0}function yt(e,t,n){if(!n)return;let o=re(e);if(!o||o.platform_agent_ids?.[t]===n)return;let r={installation_id:o.installation_id,platform_agent_ids:{...o.platform_agent_ids,[t]:n}};try{L(e,`${JSON.stringify(r,null,2)}
5
- `)}catch(s){let a=s instanceof Error?s.message:String(s);l(`WARN: platform_agent_id cache write failed open: ${a}`)}}function ro(e){return e instanceof Error&&"code"in e&&e.code==="EEXIST"}function so(e,t){Yn(Zn(e),{recursive:!0}),qn(e,`${JSON.stringify({installation_id:t},null,2)}
6
- `,{encoding:"utf8",flag:"wx"})}function ht(e,t){try{return so(e,t),{installation_id:t}}catch(n){if(!ro(n))throw n;return re(e)}}async function se(e,t={}){let n=t.home??oe(),o=await no(e),r=to(o,n),s=re(r);if(s)return{installationId:s.installation_id,storePath:r,repoKey:o};let a=t.overrideId??t.migrateFromManifestId??gt(),i=ht(r,a);if(i)return{installationId:i.installation_id,storePath:r,repoKey:o};let c=ht(r,gt());if(c)return{installationId:c.installation_id,storePath:r,repoKey:o};throw new Error(`Failed to create installation record at ${r}`)}import{existsSync as Re,readFileSync as io}from"node:fs";import{dirname as ao,join as St,relative as co}from"node:path";var ie=[D,".cursor/evalon-runtime-report.json",".codex/evalon-runtime-report.json"];async function lo(e=process.cwd(),t){let n=g("EVALON_HOOK_MANIFEST");if(n&&Re(n))return n;let o=t??await w(e);for(let r of ie){let s=St(o,r);if(Re(s))return s}for(let r of ie){let s=St(e,r);if(Re(s))return s}}async function uo(e,t){let n=t??await w(ao(e)),o=co(n,e),r=await R("git",["ls-files","--error-unmatch",o],2e3,{cwd:n});return r.ok?!0:r.code===1?!1:(l(`WARN: git ls-files failed for manifest ${e} (code=${String(r.code)}); treating as tracked`),!0)}function fo(e){let t=io(e,"utf8");return _(t,{})}function po(){return{schema_version:2,mcp_servers:[]}}async function Et(e=process.cwd()){let t=await w(e),n=await lo(e,t),o=n?fo(n):po(),r,s=n?await uo(n,t):!1;s&&o.installation_id?(l(`WARN: ignoring installation_id in git-tracked manifest ${n}; identity is per-machine under ~/.evalon/agent-hook/installations/`),delete o.installation_id):!s&&o.installation_id&&(r=o.installation_id,delete o.installation_id),o.capture_hook_input==="full"&&n&&s&&(l(`WARN: ignoring capture_hook_input=full in git-tracked manifest ${n}; use EVALON_HOOK_CAPTURE_FULL_INPUT=1 or an untracked operator manifest`),delete o.capture_hook_input);let{installationId:a,storePath:i}=await se(t,{migrateFromManifestId:r});return o.installation_id=a,{manifestPath:n??i,manifest:o,installationId:a,installationStorePath:i,collectorUrl:it(o),platformAgentId:o.platform_agent_id??"",gitRoot:t}}function vt(e){return{schema_version:2,...e?{collector_url:e}:{},mcp_servers:[]}}var mo=["darwin-arm64","darwin-x64","linux-arm64","linux-x64"];function Ce(e=process.platform,t=process.arch){if(e==="darwin")return t==="arm64"?"darwin-arm64":t==="x64"?"darwin-x64":void 0;if(e==="linux")return t==="arm64"?"linux-arm64":t==="x64"?"linux-x64":void 0}function wt(e=process.platform,t=process.arch){let n=Ce(e,t);if(!n)throw new Error(`Unsupported platform ${e}-${t}. Supported: ${mo.join(", ")}.`);return n}function Ae(e){return`compile-out/bin/${e}/evalon-agent-hook`}function wo(e,t){let n=e.collectorUrl?.trim();if(!n)throw new Error(`${t} requires --url <https://hooks.evalon.ai/{orgToken}/hook>`);let o=$(n);if(o)throw new Error(`collector URL rejected: ${o}`);return B(n)}function Io(e){let t=e.collectorUrl?.trim();if(!t)return;let n=$(t);if(n)throw new Error(`collector URL rejected: ${n}`);return B(t)}function xo(e){return wo(e,"install")}function Ct(e){let t={};for(let n=0;n<e.length;n++){let o=e[n];if(o==="--url"){let r=e[n+1];r&&!r.startsWith("--")&&(t.collectorUrl=r,n+=1);continue}if(o==="--collector-url")throw new Error("--collector-url was renamed to --url")}return t}function At(e){let t={};for(let n=0;n<e.length;n++){let o=e[n];if(o==="--url"){let r=e[n+1];r&&!r.startsWith("--")&&(t.collectorUrl=r,n+=1);continue}if(o==="--collector-url")throw new Error("--collector-url was renamed to --url");if(o==="--update")throw new Error("--update was removed; use the `update` command instead of `install --update`");if(o==="--delivery"){let r=e[n+1];(r==="npx"||r==="binary")&&(t.delivery=r,n+=1);continue}if(o==="--force"){t.force=!0;continue}if(o==="--no-claude"){t.skipClaude=!0;continue}if(o==="--no-cursor"){t.skipCursor=!0;continue}if(o==="--no-codex"){t.skipCodex=!0;continue}}return t}function Ot(e=process.execPath){return Pt(e)?"binary":"npx"}function bo(){return f(A(),".evalon","agent-hook")}function Ro(e=A()){return f(e,".evalon","agent-hook",ye)}function Co(){let e=Te(vo(import.meta.url)),t=f(e,"hook.mjs");return C(t)?t:f(e,"..","dist","hook.mjs")}function Pt(e=process.execPath){return yo(e)===P}function Tt(e,t){let n=Rt(It(e),It(t));return!n.startsWith("..")&&!So(n)}function ce(e){return e.split(Eo).join("/")}function Ao(e){return`node "$(git rev-parse --show-toplevel)/${ce(e)}"`}function Oo(e){return`"$(git rev-parse --show-toplevel)/${ce(e)}"`}function Po(e){return f(e,Se)}function Nt(e,t){let n=Po(e);Pe(Te(n),{recursive:!0}),bt(t,n,{force:!0});try{xt(n,493)}catch{}return n}function To(e){let t=f(bo(),"current");try{ae(t,{recursive:!0,force:!0})}catch{}_o(e,t,process.platform==="win32"?"junction":"dir")}function Ht(e,t=b,n=A()){let o=f(n,".evalon","agent-hook",t),r=f(o,P);Pe(o,{recursive:!0}),bt(e,r,{force:!0});try{xt(r,493)}catch{}return To(o),f(n,".evalon","agent-hook",ye)}function Mt(e){let t=Ce();if(!t)return;let n=[f(e,Ae(t)),f(e,"packages","agent-hook",Ae(t))];for(let o of n)if(C(o)&&Tt(e,o))return o}function No(e=A()){let t=Ro(e);return C(t)?t:void 0}function Ho(e,t=A()){let n=No(t);return n||(Pt()?Ht(process.execPath,b,t):Mt(e))}function Mo(e,t=A()){let n=Mt(e);if(!n)throw new Error(`update requires a locally compiled binary \u2014 run this package\u2019s build:hook-binary script first.
7
- To install a released binary instead: curl -fsSL https://cdn.evalon.ai/agent-hook/install.sh | sh`);let o=Ht(n,b,t),r=Nt(e,n);return{sourcePath:n,projectPath:r,globalPath:o}}function Lo(e){let t=[f(e,"packages","agent-hook","dist","hook.mjs"),f(e,Ye)],n=Co();C(n)&&Tt(e,n)&&t.unshift(n);for(let o of t){if(!C(o))continue;let r=ce(Rt(e,o));return{command:Ao(r),hookPath:r,strategy:"dev_mjs"}}}function Uo(e=Q){return`npx -y ${e}`}function jo(e,t=A(),n=Ot()){if(n==="npx")return{command:Uo(),hookPath:Q,strategy:"npx"};let o=Ho(e,t);if(o){Nt(e,o);let s=ce(Se);return{command:Oo(s),hookPath:s,strategy:"project_binary"}}let r=Lo(e);if(r)return r;throw new Error(`evalon-agent-hook binary not found. Install from CDN:
8
- curl -fsSL ${Xe}/install.sh | sh
3
+ import{realpathSync as Xa}from"node:fs";import{resolve as qa}from"node:path";import{fileURLToPath as Za,pathToFileURL as Qa}from"node:url";var io="https://hooks.ev-ai.ai";function Ie(e,t=io){let n=t.replace(/\/+$/,""),r=e.trim();return`${n}/${r}/hook`}var Re=".claude/ev-ai-runtime-report.json",Xt="node_modules/@ev-ai/agent-hook/dist/hook.mjs",J="ev-ai-agent-hook",qt="https://cdn.ev-ai.ai/agent-hook",ze=`current/${J}`,Ye=`.ev-ai/agent-hook/${J}`,Zt=5e3,Qt=5e3,Xe=3e3;var qe=3e3,en=1500,tn=4*1024,nn=32*1024,ao=4*1024,H="1.0.7",Ce=`@ev-ai/agent-hook@${H}`,rn="ev-ai runtime report",on=["claude","cursor","codex"];import{chmodSync as jn,cpSync as Bn,existsSync as F,mkdirSync as ut,readdirSync as Do,readFileSync as Fo,rmSync as be,symlinkSync as jo,writeFileSync as Bo}from"node:fs";import{homedir as j}from"node:os";import{basename as $o,dirname as dt,isAbsolute as Go,join as h,relative as $n,resolve as Dn,sep as Ko}from"node:path";import{fileURLToPath as Jo}from"node:url";var co=new Set(["localhost","127.0.0.1","[::1]","::1"]),sn=/^[A-Za-z0-9._~-]+$/;function an(e){for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n<=32||n===127||n===39)return!0}return!1}function xe(e){try{let t=new URL(e);return t.protocol==="https:"?!0:t.protocol==="http:"?co.has(t.hostname):!1}catch{return!1}}function ae(e){let t;try{t=new URL(e)}catch{return`invalid URL (got: ${e})`}if(!xe(e))return`must be https (or http on localhost / 127.0.0.1 / ::1) (got: ${e})`;let n=lo(e);if(!n)return`must end with /{orgToken}/hook (got: ${e})`;if(!sn.test(n))return`org token must match ${sn.source} (got: ${n})`;if(an(e))return`must not contain whitespace, control characters, or single quotes (got: ${e})`;if(an(t.pathname))return`pathname must not contain whitespace, control characters, or single quotes (got: ${e})`}function ce(e){return new URL(e).toString()}function lo(e){try{let n=new URL(e).pathname.split("/").filter(r=>r.length>0);if(n.length>=2&&n[n.length-1]==="hook"){let r=n[n.length-2];return r.length>0?r:void 0}return}catch{return}}function Ze(e){try{let t=new URL(e),n=t.pathname.split("/").filter(r=>r.length>0);return n.length>=2&&n[n.length-1]==="hook"&&(n[n.length-2]="***",t.pathname=`/${n.join("/")}`),t.toString()}catch{return"<invalid-url>"}}function cn(e){if(e.collector_url)return e.collector_url;let t=e.repo_ingest_token?.trim();return t?Ie(t):""}import{createHash as Sn,randomBytes as So}from"node:crypto";import{existsSync as En,mkdirSync as yn,readFileSync as kn,unlinkSync as In,writeFileSync as Rn}from"node:fs";import{homedir as tt}from"node:os";import{dirname as nt,join as rt,resolve as Eo}from"node:path";import{randomBytes as uo}from"node:crypto";import{existsSync as fn,mkdirSync as fo,readdirSync as po,readFileSync as mo,renameSync as ln,statSync as pn,unlinkSync as un,writeFileSync as go}from"node:fs";import{basename as ho,dirname as dn,join as mn,relative as _o}from"node:path";function d(e){process.stderr.write(`[ev-ai-agent-hook] ${e}
4
+ `)}function z(e,t){fo(dn(e),{recursive:!0});let n=mn(dn(e),`.${ho(e)}.${process.pid}.${uo(4).toString("hex")}.tmp`);try{go(n,t,"utf8");try{ln(n,e)}catch(r){let o=r instanceof Error&&"code"in r?r.code:void 0;if(o==="EEXIST"||o==="EPERM"||o==="EACCES"){un(e),ln(n,e);return}throw r}}catch(r){try{un(n)}catch{}throw r}}function Ae(){return new Date().toISOString().replace(/\.\d{3}Z$/,"Z")}function gn(){process.stdout.write('{"continue":true}')}function E(e){let t=process.env[e];return t===void 0||t===""?void 0:t}async function le(){return new Promise(e=>{let t="";if(process.stdin.isTTY){e("");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{t+=n}),process.stdin.on("end",()=>{e(t)}),process.stdin.on("error",()=>{e(t)}),process.stdin.resume()})}async function et(e){return new Promise(t=>{let n="",r=!1,o=i=>{r||(r=!0,clearTimeout(s),t(i||"{}"))},s=setTimeout(()=>{o(n)},e);if(process.stdin.isTTY){o("{}");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",i=>{n+=i}),process.stdin.on("end",()=>{o(n)}),process.stdin.on("error",()=>{o(n)}),process.stdin.resume()})}async function D(e,t,n=3e3,r={}){let{execFile:o}=await import("node:child_process"),{promisify:s}=await import("node:util"),i=s(o);try{let{stdout:a}=await i(e,t,{timeout:n,windowsHide:!0,maxBuffer:1048576,cwd:r.cwd});return{ok:!0,stdout:a.trim()}}catch(a){let c=a,u=typeof c.code=="number"?c.code:typeof c.status=="number"?c.status:void 0;return{ok:!1,code:u,spawnFailed:u===void 0}}}async function C(e,t,n=3e3,r={}){let o=await D(e,t,n,r);return o.ok?o.stdout:""}async function M(e=process.cwd()){return await C("git",["rev-parse","--show-toplevel"],2e3,{cwd:e})||e}function v(e,t){try{return JSON.parse(e)}catch{return t}}var Qe=new Map;function ne(e,t){let n=Qe.get(e);if(n!==void 0)return n;try{let r=v(mo(e,"utf8"),t);return Qe.set(e,r),r}catch{return Qe.set(e,t),t}}function ue(e){return typeof e=="string"?e:""}function Y(e,t){let n=e[t];if(typeof n=="string"||typeof n=="number"||typeof n=="boolean")return n;if(!t.includes("."))return;let r=t.split("."),o=e;for(let s of r){if(o===null||typeof o!="object"||Array.isArray(o))return;o=o[s]}if(typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o}function m(e,t){let n=Y(e,t);return typeof n=="string"?n:""}var X=500;function de(e,t=2){if(!fn(e))return{entries:[],truncated:!1};let n=[],r=!1,o=(s,i)=>{if(i>t||r)return;let a;try{a=po(s,{withFileTypes:!0})}catch{return}for(let c of a){if(r)return;let u=mn(s,c.name);if(c.isDirectory()){o(u,i+1);continue}if(c.isFile()){try{n.push({name:_o(e,u),size:pn(u).size})}catch{continue}if(n.length>=X){r=!0;return}}}};return o(e,1),{entries:n,truncated:r}}function fe(e){return fn(e)?{present:!0,size:pn(e).size}:{present:!1,size:0}}var yo="installation.json",ko="cloud-bootstrap.lock",Io=6e4;function Cn(e,t,n){let r=`${e}:${t??""}`;return n?`${n}:${r}`:r}function ot(e=tt()){return rt(e,".ev-ai","agent-hook")}function Ro(e=tt()){return rt(ot(e),yo)}function xn(e){return rt(nt(e),ko)}function An(){return So(8).toString("hex")}function Te(e){return Sn("sha256").update(e).digest("hex").slice(0,16)}function k(e){if(e===void 0)return null;let t=e.trim();return t.length>0?t:null}function Tn(e){return/^[A-Za-z0-9._-]{8,64}$/.test(e)}function Co(e=process.env){let t=k(e.EV_AI_HOOK_INSTALLATION_ID);if(t){if(!Tn(t)){d(`WARN: ignoring EV_AI_HOOK_INSTALLATION_ID (expected 8\u201364 chars [A-Za-z0-9._-], got length ${t.length})`);return}return t}}function xo(e=process.env){if(k(e.GITHUB_ACTIONS)){let t=k(e.GITHUB_REPOSITORY_ID)??k(e.GITHUB_REPOSITORY),n=k(e.GITHUB_ACTOR)??k(e.GITHUB_TRIGGERING_ACTOR)??k(e.GITHUB_USER);if(t&&n)return Te(`github_actions|${t}|${n}`)}if(k(e.CODESPACES)||k(e.CODESPACE_NAME)){let t=k(e.CODESPACE_NAME);if(t)return Te(`codespaces|${t}`);let n=k(e.GITHUB_REPOSITORY_ID)??k(e.GITHUB_REPOSITORY),r=k(e.GITHUB_USER)??k(e.GITHUB_ACTOR);if(n&&r)return Te(`codespaces|${n}|${r}`)}if(k(e.GITLAB_CI)){let t=k(e.CI_PROJECT_ID)??k(e.CI_PROJECT_PATH),n=k(e.GITLAB_USER_LOGIN)??k(e.GITLAB_USER_EMAIL)??k(e.GITLAB_USER_NAME);if(t&&n)return Te(`gitlab|${t}|${n}`)}return null}function hn(e,t){if(e&&Tn(e))return e;e&&d(`WARN: ignoring installation id override (expected 8\u201364 chars [A-Za-z0-9._-], got length ${e.length})`);let n=Co(t);if(n)return n;let r=xo(t);return r||An()}async function Ao(e){let n=await C("git",["config","--get","remote.origin.url"],2e3,{cwd:e})||Eo(e);return Sn("sha256").update(n).digest("hex").slice(0,16)}function To(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r=="string"&&r.length>0&&(t[n]=r);return Object.keys(t).length>0?t:void 0}function Oo(e){try{let t=JSON.parse(e);if(typeof t.installation_id!="string"||t.installation_id.length===0)return;let n=To(t.platform_agent_ids);return{installation_id:t.installation_id,...n?{platform_agent_ids:n}:{},...typeof t.operator_identity_hash=="string"?{operator_identity_hash:t.operator_identity_hash}:{},...typeof t.operator_identity_sent_at=="string"?{operator_identity_sent_at:t.operator_identity_sent_at}:{}}}catch{return}}function q(e){if(En(e))try{return Oo(kn(e,"utf8"))}catch{}}function st(e){return q(e)}function On(e,t,n){let r=q(e);if(!r||r.operator_identity_hash===t&&r.operator_identity_sent_at===n)return;let o={...r,operator_identity_hash:t,operator_identity_sent_at:n};try{z(e,`${JSON.stringify(o,null,2)}
5
+ `)}catch(s){let i=s instanceof Error?s.message:String(s);d(`WARN: operator identity cache write failed open: ${i}`)}}function vn(e,t=Date.now()){if(!e)return!0;if(q(e)?.operator_identity_hash)return!1;let n=xn(e);try{if(En(n)){let r=Number.NaN;try{r=Number(kn(n,"utf8").trim())}catch{}let o=t-r;if(Number.isFinite(o)&&o>=0&&o<Io)return!1;try{In(n)}catch{}}}catch{}try{return yn(nt(n),{recursive:!0}),Rn(n,`${t}
6
+ `,{encoding:"utf8",flag:"wx"}),!0}catch(r){if(Pn(r))return!1;let o=r instanceof Error?r.message:String(r);return d(`WARN: cloud bootstrap claim failed open: ${o}`),!0}}function bn(e){if(e)try{In(xn(e))}catch{}}function wn(e,t){let r=q(e)?.platform_agent_ids?.[t];return typeof r=="string"&&r.length>0?r:void 0}function Un(e,t,n){if(!n)return;let r=q(e);if(!r||r.platform_agent_ids?.[t]===n)return;let o={installation_id:r.installation_id,platform_agent_ids:{...r.platform_agent_ids,[t]:n},...r.operator_identity_hash?{operator_identity_hash:r.operator_identity_hash}:{},...r.operator_identity_sent_at?{operator_identity_sent_at:r.operator_identity_sent_at}:{}};try{z(e,`${JSON.stringify(o,null,2)}
7
+ `)}catch(s){let i=s instanceof Error?s.message:String(s);d(`WARN: platform_agent_id cache write failed open: ${i}`)}}function Pn(e){return e instanceof Error&&"code"in e&&e.code==="EEXIST"}function vo(e,t){yn(nt(e),{recursive:!0}),Rn(e,`${JSON.stringify(t,null,2)}
8
+ `,{encoding:"utf8",flag:"wx"})}function _n(e,t){try{return vo(e,t),t}catch(n){if(!Pn(n))throw n;return q(e)}}async function Oe(e,t={}){let n=t.home??tt(),r=t.env??process.env,o=await Ao(e),s=Ro(n),i=q(s);if(i)return{installationId:i.installation_id,storePath:s,repoKey:o};let a=hn(t.overrideId,r),c=_n(s,{installation_id:a});if(c)return{installationId:c.installation_id,storePath:s,repoKey:o};let u=hn(void 0,r),l=_n(s,{installation_id:u===a?An():u});if(l)return{installationId:l.installation_id,storePath:s,repoKey:o};throw new Error(`Failed to create installation record at ${s}`)}import{existsSync as it,readFileSync as bo}from"node:fs";import{dirname as wo,join as Nn,relative as Uo}from"node:path";var ve=[Re,".cursor/ev-ai-runtime-report.json",".codex/ev-ai-runtime-report.json"];async function Po(e=process.cwd(),t){let n=E("EV_AI_HOOK_MANIFEST");if(n&&it(n))return n;let r=t??await M(e);for(let o of ve){let s=Nn(r,o);if(it(s))return s}for(let o of ve){let s=Nn(e,o);if(it(s))return s}}async function No(e,t){let n=t??await M(wo(e)),r=Uo(n,e),o=await D("git",["ls-files","--error-unmatch",r],2e3,{cwd:n});return o.ok?!0:o.code===1?!1:(d(`WARN: git ls-files failed for manifest ${e} (code=${String(o.code)}); treating as tracked`),!0)}function Mo(e){let t=bo(e,"utf8");return v(t,{})}function Lo(){return{schema_version:2,mcp_servers:[]}}async function Mn(e=process.cwd()){let t=await M(e),n=await Po(e,t),r=n?Mo(n):Lo();delete r.installation_id;let o=n?await No(n,t):!1;r.capture_hook_input==="full"&&n&&o&&(d(`WARN: ignoring capture_hook_input=full in git-tracked manifest ${n}; use EV_AI_HOOK_CAPTURE_FULL_INPUT=1 or an untracked operator manifest`),delete r.capture_hook_input);let{installationId:s,storePath:i,repoKey:a}=await Oe(t);return{manifestPath:n??i,manifest:r,installationId:s,installationStorePath:i,repoKey:a,collectorUrl:cn(r),platformAgentId:r.platform_agent_id??"",gitRoot:t}}function Ln(e){return{schema_version:2,...e?{collector_url:e}:{},mcp_servers:[]}}var Ho=["darwin-arm64","darwin-x64","linux-arm64","linux-x64"];function at(e=process.platform,t=process.arch){if(e==="darwin")return t==="arm64"?"darwin-arm64":t==="x64"?"darwin-x64":void 0;if(e==="linux")return t==="arm64"?"linux-arm64":t==="x64"?"linux-x64":void 0}function Hn(e=process.platform,t=process.arch){let n=at(e,t);if(!n)throw new Error(`Unsupported platform ${e}-${t}. Supported: ${Ho.join(", ")}.`);return n}function ct(e){return`compile-out/bin/${e}/ev-ai-agent-hook`}function Vo(e,t){let n=e.collectorUrl?.trim();if(!n)throw new Error(`${t} requires --url <https://hooks.ev-ai.ai/{orgToken}/hook>`);let r=ae(n);if(r)throw new Error(`collector URL rejected: ${r}`);return ce(n)}function Wo(e){let t=e.collectorUrl?.trim();if(!t)return;let n=ae(t);if(n)throw new Error(`collector URL rejected: ${n}`);return ce(t)}function zo(e){return Vo(e,"install")}function Gn(e){let t={};for(let n=0;n<e.length;n++){let r=e[n];if(r==="--url"){let o=e[n+1];o&&!o.startsWith("--")&&(t.collectorUrl=o,n+=1);continue}if(r==="--collector-url")throw new Error("--collector-url was renamed to --url")}return t}function Kn(e){let t={};for(let n=0;n<e.length;n++){let r=e[n];if(r==="--url"){let o=e[n+1];o&&!o.startsWith("--")&&(t.collectorUrl=o,n+=1);continue}if(r==="--collector-url")throw new Error("--collector-url was renamed to --url");if(r==="--update")throw new Error("--update was removed; use the `update` command instead of `install --update`");if(r==="--delivery"){let o=e[n+1];(o==="npx"||o==="binary"||o==="local")&&(t.delivery=o,n+=1);continue}if(r==="--force"){t.force=!0;continue}if(r==="--no-claude"){t.skipClaude=!0;continue}if(r==="--no-cursor"){t.skipCursor=!0;continue}if(r==="--no-codex"){t.skipCodex=!0;continue}}return t}function Jn(e=process.execPath){return Vn(e)?"binary":"npx"}function Yo(){return h(j(),".ev-ai","agent-hook")}function Xo(e=j()){return h(e,".ev-ai","agent-hook",ze)}function qo(){let e=dt(Jo(import.meta.url)),t=h(e,"hook.mjs");return F(t)?t:h(e,"..","dist","hook.mjs")}function Vn(e=process.execPath){return $o(e)===J}function Wn(e,t){let n=$n(Dn(e),Dn(t));return!n.startsWith("..")&&!Go(n)}function we(e){return e.split(Ko).join("/")}function Zo(e){return`node "$(git rev-parse --show-toplevel)/${we(e)}"`}function Qo(e){return`"$(git rev-parse --show-toplevel)/${we(e)}"`}function es(e){return h(e,Ye)}function zn(e,t){let n=es(e);ut(dt(n),{recursive:!0}),Bn(t,n,{force:!0});try{jn(n,493)}catch{}return n}function ts(e){let t=h(Yo(),"current");try{be(t,{recursive:!0,force:!0})}catch{}jo(e,t,process.platform==="win32"?"junction":"dir")}function Yn(e,t=H,n=j()){let r=h(n,".ev-ai","agent-hook",t),o=h(r,J);ut(r,{recursive:!0}),Bn(e,o,{force:!0});try{jn(o,493)}catch{}return ts(r),h(n,".ev-ai","agent-hook",ze)}function Xn(e){let t=at();if(!t)return;let n=[h(e,ct(t)),h(e,"packages","agent-hook",ct(t))];for(let r of n)if(F(r)&&Wn(e,r))return r}function ns(e=j()){let t=Xo(e);return F(t)?t:void 0}function rs(e,t=j()){let n=ns(t);return n||(Vn()?Yn(process.execPath,H,t):Xn(e))}function os(e,t=j()){let n=Xn(e);if(!n)throw new Error(`update requires a locally compiled binary \u2014 run this package\u2019s build:hook-binary script first.
9
+ To install a released binary instead: curl -fsSL https://cdn.ev-ai.ai/agent-hook/install.sh | sh`);let r=Yn(n,H,t),o=zn(e,n);return{sourcePath:n,projectPath:o,globalPath:r}}function Fn(e){let t=[h(e,"packages","agent-hook","dist","hook.mjs"),h(e,Xt)],n=qo();F(n)&&Wn(e,n)&&t.unshift(n);for(let r of t){if(!F(r))continue;let o=we($n(e,r));return{command:Zo(o),hookPath:o,strategy:"dev_mjs"}}}function ss(e=Ce){return`npx -y ${e}`}function is(e,t=j(),n=Jn()){if(n==="npx")return{command:ss(),hookPath:Ce,strategy:"npx"};if(n==="local"){let s=Fn(e);if(s)return s;throw new Error("local delivery requires packages/agent-hook/dist/hook.mjs (or node_modules/@ev-ai/agent-hook/dist/hook.mjs) under the git root \u2014 run yarn workspace @ev-ai/agent-hook build first")}let r=rs(e,t);if(r){zn(e,r);let s=we(Ye);return{command:Qo(s),hookPath:s,strategy:"project_binary"}}let o=Fn(e);if(o)return o;throw new Error(`ev-ai-agent-hook binary not found. Install from CDN:
10
+ curl -fsSL ${qt}/install.sh | sh
9
11
  Or use npx delivery:
10
- npx ${Q} install`)}function Lt(e){return typeof e!="string"?!1:e.includes("@evalon-ai/agent-hook")||e.includes("@evalon/agent-hook")||e.includes("agent-hook/dist/hook")||e.includes(".evalon/agent-hook")||e.includes(P)||/(?:^|[\s/"'])evalon-agent-hook(?:$|[\s"'])/.test(e)}function Ne(e,t){return`${e.replace(/\s+--runner(?:=|\s+)\S+/g,"").trimEnd()} --runner ${t}`}function T(e,t){Pe(Te(e),{recursive:!0}),ko(e,`${JSON.stringify(t,null,2)}
11
- `,"utf8")}function I(e){if(C(e))try{return JSON.parse(ho(e,"utf8"))}catch(t){throw t instanceof SyntaxError?new Error(`Invalid JSON in ${e} \u2014 fix or remove the file`,{cause:t}):t}}function Fo(e,t){let n=vt(t.collectorUrl),o={...e,schema_version:e?.schema_version??n.schema_version};return t.collectorUrl!==void 0?o.collector_url=t.collectorUrl:o.collector_url=e?.collector_url??n.collector_url,delete o.repo_ingest_token,delete o.installation_id,o.mcp_servers??=n.mcp_servers,o}function Do(e){return(e.schema_version??2)===2&&e.collector_url===void 0&&(e.mcp_servers?.length??0)===0&&e.platform_agent_id===void 0&&e.capture_hook_input===void 0&&e.repo_ingest_token===void 0}function Ut(e,t){let n=f(e,D),o=I(n),r=Fo(o,t);return t.collectorUrl!==void 0||C(n)||!Do(r)?(T(n,r),{manifestPath:n,wrote:!0}):{manifestPath:void 0,wrote:!1}}function Oe(e){if(e===null||typeof e!="object")return!1;let t=e,n=String(t.CLAUDE_CODE_ENABLE_TELEMETRY??"").toLowerCase();return n==="1"||n==="true"?!0:Object.keys(t).some(o=>o.startsWith("OTEL_"))}function $o(e=process.platform){switch(e){case"darwin":return"/Library/Application Support/ClaudeCode";case"win32":return f(process.env.ProgramFiles??"C:\\Program Files","ClaudeCode");default:return"/etc/claude-code"}}function Bo(e=process.platform){let t=$o(e),n=[f(t,"managed-settings.json")],o=f(t,"managed-settings.d");try{if(!C(o))return n;let r=go(o).filter(s=>s.endsWith(".json")&&!s.startsWith(".")).sort().map(s=>f(o,s));n.push(...r)}catch{}return n}function Ko(e){if(Oe(process.env))return!0;let t=A();return[...Bo(),f(t,".claude","settings.json"),f(t,".claude","remote-settings.json"),f(e,".claude","settings.json"),f(e,".claude","settings.local.json")].some(o=>{try{let r=I(o);return r?Oe(r.env):!1}catch{return!1}})}function Go(e){try{let t=I(f(e,".claude","settings.json"));return t?Oe(t.env):!1}catch{return!1}}function jt(e){return Array.isArray(e)?e:[]}function le(e){let t=[],n=o=>!!o&&typeof o=="object"&&Lt(o.command);for(let o of jt(e)){if(!o||typeof o!="object"){t.push(o);continue}let r=Array.isArray(o.hooks)?o.hooks:[],s=r.filter(a=>!n(a));if(!(s.length===0&&r.some(n))){if(s.length!==r.length){t.push({...o,hooks:s});continue}t.push(o)}}return t}function Ft(e,t){return[...le(e),...t]}function He(e){return Array.isArray(e)?e.filter(t=>!t||typeof t!="object"?!0:!Lt(t.command)):[]}function Jo(e,t){return[...He(e),{command:t}]}function Wo(e){let t=()=>({hooks:[{type:"command",command:e}]});return{SessionStart:[t()],UserPromptExpansion:[t()],PreToolUse:[t()],PostToolUse:[t()],PostToolUseFailure:[t()],PermissionDenied:[t()],Stop:[t()],StopFailure:[t()],SessionEnd:[t()],SubagentStart:[t()],SubagentStop:[t()]}}function Vo(e){let t={type:"command",command:e,statusMessage:nt},n=()=>({hooks:[t]});return{SessionStart:[n()],UserPromptSubmit:[n()],PreToolUse:[n()],PostToolUse:[n()],Stop:[n()]}}var zo=["sessionStart","beforeSubmitPrompt","preToolUse","postToolUse","postToolUseFailure","subagentStart","subagentStop","stop"],Yo=["beforeMCPExecution","beforeShellExecution","afterFileEdit"];function Xo(e){let t={...e};for(let n of Yo){if(!(n in t))continue;let o=He(t[n]);o.length===0?delete t[n]:t[n]=o}return t}function qo(e,t,n={}){let o=f(e,".claude/settings.json"),r=Ne(t,"claude"),s=I(o)??{};if(Ko(e)&&!n.force){if(s.hooks&&typeof s.hooks=="object"){let p={...s.hooks};for(let m of Object.keys(p))p[m]=le(p[m]),jt(p[m]).length===0&&delete p[m];Object.keys(p).length===0?delete s.hooks:s.hooks=p,T(o,s)}return!1}let i=s.hooks&&typeof s.hooks=="object"?s.hooks:{},c=Wo(r),u={...i};for(let[p,m]of Object.entries(c))u[p]=Ft(i[p],m);return s.hooks=u,T(o,s),!0}function Zo(e,t){let n=f(e,".cursor/hooks.json"),o=Ne(t,"cursor"),r=I(n)??{},s=r.hooks&&typeof r.hooks=="object"?r.hooks:{},a=Xo({...s});for(let i of zo)a[i]=Jo(a[i],o);T(n,{...r,version:typeof r.version=="number"?r.version:1,hooks:a})}function Qo(e,t){let n=f(e,".codex/hooks.json"),o=Ne(t,"codex"),r=I(n)??{},s=r.hooks&&typeof r.hooks=="object"?r.hooks:{},a=Vo(o),i={...s};for(let[c,u]of Object.entries(a))i[c]=Ft(s[c],u);T(n,{...r,hooks:i})}function er(e){let t=f(e,".claude/settings.json"),n=I(t);if(!n?.hooks||typeof n.hooks!="object")return;let o={...n.hooks},r=!1;for(let s of Object.keys(o)){let a=o[s],i=le(a);JSON.stringify(a)!==JSON.stringify(i)&&(r=!0),i.length===0?delete o[s]:o[s]=i}r&&(Object.keys(o).length===0?delete n.hooks:n.hooks=o,T(t,n),l(`Removed Evalon hooks from ${t}`))}function tr(e){let t=f(e,".cursor/hooks.json"),n=I(t);if(!n?.hooks||typeof n.hooks!="object")return;let o={...n.hooks},r=!1,s=0;for(let a of Object.keys(o)){let i=o[a],c=He(i);JSON.stringify(i)!==JSON.stringify(c)&&(r=!0),c.length===0?delete o[a]:(o[a]=c,s+=c.length)}if(r){if(s===0&&Object.keys(o).length===0&&Object.keys(n).filter(i=>i!=="hooks"&&i!=="version").length===0){ae(t,{force:!0}),l(`Removed ${t}`);return}T(t,{...n,hooks:o}),l(`Removed Evalon hooks from ${t}`)}}function nr(e){let t=f(e,".codex/hooks.json"),n=I(t);if(!n?.hooks||typeof n.hooks!="object")return;let o={...n.hooks},r=!1,s=0;for(let a of Object.keys(o)){let i=o[a],c=le(i);JSON.stringify(i)!==JSON.stringify(c)&&(r=!0),c.length===0?delete o[a]:(o[a]=c,s+=c.length)}if(r){if(s===0&&Object.keys(o).length===0&&Object.keys(n).filter(i=>i!=="hooks").length===0){ae(t,{force:!0}),l(`Removed ${t}`);return}T(t,{...n,hooks:o}),l(`Removed Evalon hooks from ${t}`)}}function Me(e=process.platform,t=process.arch,n={}){if(e==="win32")throw new Error("Windows install is not supported yet. Use macOS/Linux, or wait for phase-2 native commands.");(n.requireBinaryArch??!0)&&wt(e,t)}async function Dt(e={}){let t=xo(e);e.collectorUrl=t;let n=e.skipClaude===!0,o=e.skipCursor===!0,r=e.skipCodex===!0;if(n&&o&&r)throw new Error("at least one runner must be wired; refuse --no-claude --no-cursor --no-codex together");let s=e.delivery??Ot();Me(process.platform,process.arch,{requireBinaryArch:s==="binary"});let a=e.cwd??process.cwd(),i=await w(a),{command:c,hookPath:u,strategy:p}=jo(i,A(),s),m=I(f(i,D)),{installationId:E,storePath:k}=await se(i,{overrideId:e.installationId,migrateFromManifestId:m?.installation_id}),{manifestPath:O,wrote:v}=Ut(i,e),y=[];return n?l("Skipped Claude hook \u2014 --no-claude"):qo(i,c,{force:e.force})?(y.push("Claude"),e.force&&Go(i)&&l("Forced Claude hook despite project native OTEL \u2014 expect duplicate session/tool events")):l("Skipped Claude hook \u2014 native OTEL telemetry already enabled (avoids duplicate events); pass --force to wire anyway"),o?l("Skipped Cursor hook \u2014 --no-cursor"):(Zo(i,c),y.push("Cursor")),r?l("Skipped Codex hook \u2014 --no-codex"):(Qo(i,c),y.push("Codex")),l(`Installed hook (${p}) at ${u}`),l(`Installation identity ${E} at ${k}`),v&&O?l(`Shared manifest written to ${O}`):l("Using package default collector config (no shared manifest file needed)"),l(y.length>0?`Wired ${y.join(", ")} hooks in ${i} (commands include --runner)`:`No runner hooks wired in ${i} (Claude skipped by OTEL; Cursor/Codex excluded via flags)`),p==="npx"?l("Hook commands use npx and may be committed; teammates need Node on PATH only (no install step, no env vars when collector_url is in the shared manifest)."):p==="project_binary"&&l("Hook commands are git-root-relative and may be committed; each collaborator runs install once to populate .evalon/agent-hook/ (gitignored)."),v&&O&&e.collectorUrl&&l("Shared manifest includes collector_url \u2014 commit it with hook configs so teammates post without env vars."),{gitRoot:i,hookPath:u,manifestPath:O,installationStorePath:k,strategy:p}}async function $t(e=process.cwd()){Me(process.platform,process.arch,{requireBinaryArch:!0});let t=await w(e),{projectPath:n,globalPath:o}=Mo(t);l(`Refreshed ${o}`),l(`Refreshed ${n}`),l("Hook configs and shared manifest left unchanged")}async function Bt(e={}){let t=Io(e);e.collectorUrl=t,Me(process.platform,process.arch,{requireBinaryArch:!1});let n=e.cwd??process.cwd(),o=await w(n),{manifestPath:r,wrote:s}=Ut(o,e);if(t!==void 0&&(!r||!s))throw new Error("configure failed to write shared collector manifest");return s&&r?l(`Wrote ${r}`):t===void 0&&l("No --url given and no shared manifest yet \u2014 pass --url <\u2026/{orgToken}/hook> to write collector destination."),l("Manifest only \u2014 enable Evalon marketplace plugins (https://github.com/evalon-ai/marketplace). Do not also run file-wiring install for the same events."),{gitRoot:o,manifestPath:r}}function Kt(e){for(let t of[()=>er(e),()=>tr(e),()=>nr(e)])try{t()}catch(n){let o=n instanceof Error?n.message:String(n);l(`WARN: strip skipped a hook file: ${o}`)}}async function Gt(e=process.cwd()){let t=await w(e);return Kt(t),l("Stripped Evalon file-wired hooks; shared collector manifest left in place."),l("Next: enable Evalon marketplace plugins (https://github.com/evalon-ai/marketplace), then restart runners."),{gitRoot:t}}async function Jt(e=process.cwd()){let t=await w(e);Kt(t);for(let n of ie){let o=f(t,n);if(C(o))try{ae(o,{force:!0}),l(`Removed ${o}`)}catch(r){let s=r instanceof Error?r.message:String(r);l(`WARN: uninstall could not remove ${o}: ${s}`)}}}var or={claude:".claude",cursor:".cursor",codex:".codex"};function ue(e){let n=e.replace(/^\/+|\/+$/g,"").toLowerCase().split("/").filter(Boolean);return n.length<2?"":n.join("/")}function rr(e){if(!e)return"";let t=e.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1");t=t.replace(/\.git$/i,"");let n=t.match(/^git@[^:]+:(.+)$/);if(n?.[1])return ue(n[1]);let o=t.match(/^ssh:\/\/[^/]+\/(.+)$/i);if(o?.[1])return ue(o[1]);t=t.replace(/^https:\/\//i,""),t=t.replace(/^http:\/\//i,""),t=t.replace(/^ssh:\/\//i,"");let r=t.match(/^[^/]+\/(.+)$/);return r?.[1]?ue(r[1]):ue(t)}async function Le(e=process.cwd()){let t=await R("git",["rev-parse","--is-inside-work-tree"],2e3,{cwd:e});if(!t.ok||t.stdout!=="true")return null;let[n,o,r,s]=await Promise.all([R("git",["remote","get-url","origin"],2e3,{cwd:e}),R("git",["branch","--show-current"],2e3,{cwd:e}),R("git",["rev-parse","HEAD"],2e3,{cwd:e}),R("git",["status","--porcelain"],2e3,{cwd:e})]),a=n.ok?n.stdout:null;return{remote:a===null?null:a.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1"),branch:o.ok?o.stdout:null,head:r.ok?r.stdout:null,dirty:s.ok?s.stdout.length>0:null}}async function Wt(e,t,n,o=process.cwd(),r,s){if(t)return t;let a=or[n];if(!a)return"";let i=_t(n,e.scope_path);if(s){let k=kt(s,i);if(k)return k}let c=r??await Le(o),u=c?.remote?rr(c.remote):"";if(u||(u=process.env.GITHUB_REPOSITORY??""),!u)return"";let p=e.scope_path??"",m=p?`${p}/`:"",E=`${u}:${m}${a}`;return s&&yt(s,i,E),E}import{existsSync as sr,readFileSync as ir}from"node:fs";import{hostname as ar,userInfo as cr}from"node:os";function Vt(){if(g("GITHUB_ACTIONS"))return"github_actions";let e=g("CI");if(e&&e!=="false"&&e!=="0")return"managed";try{if(sr("/.dockerenv")||ir("/proc/1/environ","utf8").includes("container="))return"container"}catch{}return process.stdin.isTTY||process.stdout.isTTY||g("TERM")?"interactive":"cron"}async function zt(){return await h("systemd-detect-virt",[],1e3)}async function Yt(){let e=process.platform==="darwin"?"Darwin":process.platform==="win32"?"Windows_NT":"Linux",t="";if(process.platform==="darwin")t=await h("sw_vers",["-productVersion"],1e3);else if(process.platform==="linux"){try{let{readFileSync:s}=await import("node:fs"),a=s("/etc/os-release","utf8"),i=a.match(/^PRETTY_NAME="?([^"\n]+)"?/m)?.[1],c=a.match(/^VERSION_ID="?([^"\n]+)"?/m)?.[1];t=i??c??""}catch{t=await h("lsb_release",["-sd"],1e3).then(s=>s.replace(/^"|"$/g,""))}t||(t=await h("uname",["-r"],1e3))}else t=await h("ver",[],1e3);let n=process.env.USER??cr().username??"",o=(process.env.SHELL??"").split(/[/\\]/).pop()??"",r="";try{r=await h("tty",[],500),r.includes("not a tty")&&(r="")}catch{r=""}return{os:e,os_version:t||null,user:n||null,shell:o||null,tty:r||null}}function Xt(){return ar()}import{existsSync as lr,readFileSync as ur}from"node:fs";import{homedir as qt}from"node:os";import{join as dr}from"node:path";var fr="cloud-cache.json",pr=1440*60*1e3,mr=900*1e3;function gr(e=qt()){return dr(be(e),fr)}function hr(e){if(!lr(e))return;let t=_(ur(e,"utf8"),{});if(!(typeof t.context!="string"||typeof t.probed_at!="number"||t.result!==null&&t.result!==void 0&&typeof t.result!="object"))return{context:t.context,probed_at:t.probed_at,result:t.result??null}}function _r(e,t){try{L(e,`${JSON.stringify(t)}
12
- `)}catch(n){let o=n instanceof Error?n.message:String(n);l(`WARN: cloud cache write failed open: ${o}`)}}function kr(e,t,n){if(!e||e.context!==t)return!1;let o=e.result===null?mr:pr;return n-e.probed_at<o}async function yr(e){let t=await fetch("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"60"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=(await t.text()).trim();if(!n)return;let o={"X-aws-ec2-metadata-token":n},[r,s]=await Promise.all([fetch("http://169.254.169.254/latest/meta-data/placement/region",{headers:o,signal:AbortSignal.timeout(e)}).catch(()=>{}),fetch("http://169.254.169.254/latest/meta-data/instance-id",{headers:o,signal:AbortSignal.timeout(e)}).catch(()=>{})]);if(!r?.ok&&!s?.ok)return;let a=r?.ok?(await r.text()).trim():"",i=s?.ok?(await s.text()).trim():"";if(!(!a&&!i))return{provider:"aws",region:a,instance_id:i}}async function Sr(e){let t=await fetch("http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true",{headers:{"Metadata-Flavor":"Google"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=await t.json(),o=typeof n.zone=="string"?n.zone.split("/").pop()??"":"",r=n.id===void 0?"":String(n.id);if(!(!o&&!r))return{provider:"gcp",region:o,instance_id:r}}async function Er(e){let t=await fetch("http://169.254.169.254/metadata/instance?api-version=2021-02-01",{headers:{Metadata:"true"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=await t.json(),o=n.compute?.location??"",r=n.compute?.vmId??"";if(!(!o&&!r))return{provider:"azure",region:o,instance_id:r}}async function vr(e){let t=await Promise.allSettled([yr(e),Sr(e),Er(e)]);for(let n of t)if(n.status==="fulfilled"&&n.value)return n.value;return null}async function Zt(e,t){if(e==="interactive")return null;let n=t?.home??qt(),o=t?.timeoutMs??1e3,r=t?.nowMs??Date.now(),s=gr(n),a=hr(s);if(kr(a,e,r))return a.result;let i=await vr(o);return _r(s,{context:e,probed_at:r,result:i}),i}import{existsSync as wr,readFileSync as Ir}from"node:fs";import{homedir as xr}from"node:os";import{join as Ue}from"node:path";function je(e,t,n){if(!wr(e))return;let o=_(Ir(e,"utf8"),{});for(let r of Object.keys(o.mcpServers??{}))n.set(r,{name:r,source:t})}async function Qt(e,t=process.cwd(),n="claude",o=xr()){let r=new Map;for(let s of e.mcp_servers??[])s.name&&r.set(s.name,{name:s.name,source:"manifest"});return n==="claude"&&je(Ue(o,".claude.json"),"claude_json_user",r),je(Ue(t,".mcp.json"),"mcp_json",r),je(Ue(t,".cursor/mcp.json"),"cursor_mcp",r),[...r.values()]}var br=["CI","GITHUB_ACTIONS","GITLAB_CI","CIRCLECI","BUILDKITE","TF_BUILD","GITHUB_REPOSITORY","GITHUB_REF","GITHUB_SHA","GITHUB_RUN_ID","GITHUB_WORKFLOW","RUNNER_OS","RUNNER_ARCH","NODE_ENV","TERM_PROGRAM","ANTHROPIC_BASE_URL","OPENAI_BASE_URL","OPENAI_API_BASE","AZURE_OPENAI_ENDPOINT","GOOGLE_GEMINI_BASE_URL","GEMINI_API_BASE","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX"],Rr=new Set(["key","api-key","api_key","apikey","token","sig","signature","access_token","password","pwd","secret","client_secret"]);function Cr(e){try{let t=new URL(e);(t.username||t.password)&&(t.username="",t.password="");for(let[n]of t.searchParams)Rr.has(n.toLowerCase())&&t.searchParams.set(n,"[redacted]");return t.toString()}catch{return e}}function en(e=process.env){return br.map(t=>Object.prototype.hasOwnProperty.call(e,t)?{name:t,present:!0,value:Cr(e[t]??"")}:{name:t,present:!1})}import{createHash as Ar}from"node:crypto";import{existsSync as on,readFileSync as rn}from"node:fs";import{homedir as sn}from"node:os";import{join as S}from"node:path";var Or={claude:{skills:".claude/skills",subagents:".claude/agents",commands:".claude/commands",memory:".claude/CLAUDE.md",settings:".claude/settings.json"},cursor:{skills:[".cursor/skills",".cursor/skills-cursor"],commands:".cursor/commands",rules:".cursor/rules",mcp:".cursor/mcp.json"},codex:{skills:".agents/skills",commands:".codex/prompts",memory:".codex/AGENTS.md",settings:".codex/config.toml"}},Pr=200,tn=200,Tr=["allow","deny","ask"],Nr=/(?<=^|[\s(,=:])(?:~|[A-Za-z]:)?[\\/][^\s,)]+/g,Fe="<path>",Hr=new RegExp(`${Fe}(?:\\s+[A-Za-z.][^\\s,)]*[\\\\/][^\\s,)]*)+`,"g");function Mr(e){let t=e.replace(Nr,Fe).replace(Hr,Fe);return t.length>tn?`${t.slice(0,tn)}...`:t}function nn(e){if(!on(e))return{model:"",permissionKeys:[]};let t=_(rn(e,"utf8"),{}),n=[];for(let o of Tr)for(let r of t.permissions?.[o]??[])typeof r=="string"&&r.length>0&&n.push({key:Mr(r),mode:o});return{model:t.model??"",permissionKeys:n}}var Lr=10,Ur="self-config-cache.json",jr={claude:["claude"],cursor:["agent","cursor-agent"],codex:["codex"]};async function Fr(e,t=h){let n=jr[e];if(!n||n.length===0)return null;let o=async r=>{let s=n[r];if(s===void 0)return null;let i=((await t(s,["--version"],2e3)).split(`
13
- `)[0]??"").trim();return i||o(r+1)};return o(0)}function Dr(e=sn()){return S(e,".evalon","agent-hook",Ur)}function $r(e){let n=[...e].sort((o,r)=>o.name.localeCompare(r.name)).map(o=>`${o.name}:${o.size}`).join(`
14
- `);return Ar("sha256").update(n).digest("hex").slice(0,16)}function de(e,t,n=!1){let o=$r(e),r=e.length;return t===o?n?{hash:o,count:r,truncated:n}:{hash:o,count:r}:n?{hash:o,count:r,entries:e,truncated:n}:{hash:o,count:r,entries:e}}function Br(e){return on(e)?_(rn(e,"utf8"),{}):{}}function Kr(e,t){try{L(e,`${JSON.stringify(t)}
15
- `)}catch(n){let o=n instanceof Error?n.message:String(n);l(`WARN: self-config cache write failed open: ${o}`)}}function Gr(e,t,n){let o={...e,send_count:n};for(let r of Object.keys(t)){let s=t[r];s.entries!==void 0&&(o[r]=s.hash)}return o}async function an(e,t=process.cwd(),n=sn()){let o=e==="claude",r=await Fr(e),s="",a=[];if(o){let x=nn(S(n,".claude/settings.json")),X=nn(S(t,".claude/settings.local.json"));s=X.model||x.model,a=[...x.permissionKeys,...X.permissionKeys].slice(0,Pr)}let i=Or[e]??{},c={present:!1,size:0},u=x=>{let X=Array.isArray(x)?x:x?[x]:[],M=[],q=!1;for(let Mn of X){let ze=G(S(n,Mn));if(M=M.concat(ze.entries),q=q||ze.truncated,M.length>=ne){M=M.slice(0,ne),q=!0;break}}return{entries:M,truncated:q}},p=Dr(n),m=Br(p),E=m[e]??{},k=(E.send_count??0)+1,O=k>0&&k%Lr===0,v=x=>O?void 0:E[x],y=u(i.skills),j=i.subagents?G(S(n,i.subagents)):{entries:[],truncated:!1},We=i.commands?G(S(n,i.commands)):{entries:[],truncated:!1},Ve=i.rules?G(S(n,i.rules)):{entries:[],truncated:!1},F={skills:de(y.entries,v("skills"),y.truncated),subagents:de(j.entries,v("subagents"),j.truncated),commands:de(We.entries,v("commands"),We.truncated),rules:de(Ve.entries,v("rules"),Ve.truncated)};return m[e]=Gr(E,F,k),Kr(p,m),{runner_platform:e,config_scope:"user",cli_version:r,claude_version:o?r:null,model:o&&s||null,permission_keys:a,user_scope:{skills:F.skills,subagents:F.subagents,commands:F.commands,rules:F.rules,memory:i.memory?J(S(n,i.memory)):c,settings:i.settings?J(S(n,i.settings)):c,mcp:i.mcp?J(S(n,i.mcp)):c},local_settings:o?J(S(t,".claude/settings.local.json")):c}}function W(e,t,n){let o={installation_id:n.installationId};return n.platformAgentId&&(o.platform_agent_id=n.platformAgentId),n.sessionId&&(o.session_id=n.sessionId),n.turnId&&(o.turn_id=n.turnId),{schema_version:2,event:e,timestamp:pt(),session_id:n.sessionId||null,turn_id:n.turnId||null,installation_id:n.installationId,platform:n.runnerPlatform,platform_agent_id:n.platformAgentId||null,runner_event:n.runnerEvent||null,agent_hook_version:b,host_arch:process.arch,node_version:process.version,correlation:o,payload:t}}import{existsSync as En}from"node:fs";import{spawn as vn}from"node:child_process";import{basename as ms}from"node:path";import{fileURLToPath as gs}from"node:url";var cn=/(?:^|\/|[\s"'=(])(?:\.cursor\/|\.claude\/|\.agents\/)skills(?:-cursor)?\/([^/]+)\/SKILL\.md/i,ln=/(?:^|\/|[\s"'=(])\.codex\/commands\/([^/]+)\.md\b/i,Jr=/(?:^|\s)\/([a-z][a-z0-9-]{1,63})\b/gi,Wr=new Set(["applications","app","bin","boot","data","dev","etc","home","lib","media","mnt","node_modules","opt","pkg","private","proc","projects","repos","run","sbin","src","srv","sys","tmp","usr","users","var","volumes","workspace","workspaces"]),Vr=new Set(["read","read_file","view"]),zr=new Set(["bash","shell","zsh"]);function Yr(e){let t=e.replace(/\\/g,"/");return cn.exec(t)?.[1]??null}function Xr(e){let t=e.replace(/\\/g,"/"),o=ln.exec(t)?.[1];return o?o.toLowerCase():null}function qr(e){return Yr(e)??Xr(e)}function Zr(e){for(let t of["path","file_path","target_file"]){let n=e[t];if(typeof n=="string"&&n.length>0)return n}return null}function un(e){if(typeof e=="string")try{let t=JSON.parse(e);return un(t)}catch{return null}return!e||typeof e!="object"?null:Zr(e)}function Qr(e){if(!e||typeof e!="object")return null;let t=e.command;return typeof t=="string"&&t.length>0?t:null}function es(e){let t=e.replace(/\\/g,"/"),n=cn.exec(t);if(n?.[1])return n[1];let r=ln.exec(t)?.[1];return r?r.toLowerCase():null}function ts(e){return typeof e.tool_name=="string"?e.tool_name:typeof e.tool=="string"?e.tool:""}function dn(e){let t=ts(e).toLowerCase();if(Vr.has(t)){let n=un(e.tool_input);return n?qr(n):null}if(zr.has(t)){let n=Qr(e.tool_input);return n?es(n):null}return null}function ns(e){let t=new Set,n=[];for(let o of e.matchAll(Jr)){let r=o[1]?.toLowerCase();!r||t.has(r)||Wr.has(r)||(t.add(r),n.push(r))}return n}function os(e){return K(e.prompt)}function fn(e){let t=d(e,"command_name");if(t){let o=d(e,"expansion_type");if(o&&o!=="slash_command")return[];let r=t.replace(/^\//,"").toLowerCase();return r?[r]:[]}let n=os(e);return n?ns(n):[]}function De(e){return e!==void 0&&ot.includes(e)}function fe(e,t){let n=e[t+1];return n&&!n.startsWith("--")?{value:n,next:t+1}:{next:t}}function pe(e){let t,n,o,r,s;for(let a=0;a<e.length;a++){let i=e[a];if(i!==void 0){if(i==="--runner"){let c=fe(e,a);t=c.value,a=c.next;continue}if(i.startsWith("--runner=")){t=i.slice(9);continue}if(i==="--url"){let c=fe(e,a);c.value&&(o=c.value),a=c.next;continue}if(i.startsWith("--url=")){o=i.slice(6);continue}if(i==="--token"){let c=fe(e,a);c.value&&(r=c.value),a=c.next;continue}if(i.startsWith("--token=")){r=i.slice(8);continue}if(i==="--base-url"){let c=fe(e,a);c.value&&(s=c.value),a=c.next;continue}if(i.startsWith("--base-url=")){s=i.slice(11);continue}!i.startsWith("-")&&n===void 0&&(n=i)}}return{runner:De(t)?t:void 0,event:n,collectorUrl:o,orgToken:r,baseUrl:s}}function $e(e){let t=e.collectorUrl?.trim(),n;if(t)n=t;else{let r=e.orgToken?.trim();r&&(n=Z(r,e.baseUrl?.trim()??void 0))}if(!n)return;let o=$(n);if(o){l(`WARN: ignoring --url/--token collector override: ${o}`);return}return B(n)}function rs(e,t){return d(e,"conversation_id")?!0:t!==""&&t===t.toLowerCase()}function Be(e,t,n,o){if(rs(e,t))return"cursor";if(De(o))return o;let r=d(e,"conversation_id"),s=d(e,"turn_id"),a=d(e,"session_id"),i=t.toLowerCase(),c="unknown";return r||t===i&&t!==""?c="cursor":s?c="codex":(a||i==="sessionstart"||i==="sessionend"||i==="stop"||i==="stopfailure"||i==="pretooluse"||i==="posttooluse"||i==="posttoolusefailure"||i==="permissiondenied"||i==="subagentstart"||i==="subagentstop"||i==="userpromptexpansion")&&(c="claude"),De(n)&&(c=n),c}function me(e,t){let n=e.toLowerCase();return n==="sessionend"||n==="stopfailure"||n==="subagentstop"?!0:n==="stop"&&t==="codex"}function ss(e){switch(e){case"sessionstart":return"session_start";case"stop":case"sessionend":case"stopfailure":return"session_end";case"pretooluse":case"posttooluse":case"posttoolusefailure":case"permissiondenied":case"beforemcpexecution":case"beforeshellexecution":case"afterfileedit":case"subagentstart":case"subagentstop":return"tool_invoked";case"beforesubmitprompt":case"userpromptexpansion":case"userpromptsubmit":return"skill_invoked";default:return""}}function pn(e){let t=e.toLowerCase();return t==="posttooluse"?!0:t==="posttoolusefailure"||t==="permissiondenied"?!1:null}function mn(e,t,n){let o=d(e,"session_id")||d(e,"conversation_id"),r=d(e,"prompt.id")||d(e,"prompt_id")||d(e,"generation_id")||d(e,"turn_id"),s=d(e,"hook_event_name")||d(e,"event"),a=d(e,"source"),i=Be(e,s,t,n);return{sessionId:o,turnId:r,runnerEvent:s,hookSource:a,runnerPlatform:i}}var is=["session_start","session_end","tool_invoked","skill_invoked"];function as(e){return is.includes(e)}function gn(e,t){return e&&as(e)?e:ss(t.toLowerCase())}function hn(e){let t=d(e,"tool_name")||d(e,"tool")||null,n=e.tool_input,r=(n&&typeof n=="object"?K(n.skill)||K(n.skill_name):"")||d(e,"skill_name")||null;return r??=dn(e),{toolName:t,skillName:r}}var cs=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;function _n(e){for(let t of["subagent_type","agent_type"]){let n=d(e,t);if(n&&cs.test(n))return n}return null}function kn(e){let t=N(e,"duration_ms");if(typeof t=="number")return t;let n=N(e,"duration");return typeof n=="number"?n:null}var ls="error",us="interrupted",ds="permission_denied",fs=/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/;function Ke(e){return fs.test(e)?e:null}function ps(e){for(let t of["failure_type","error_type"]){let n=Ke(d(e,t));if(n)return n}return null}function yn(e,t){return N(e,"is_interrupt")===!0?us:t.toLowerCase()==="permissiondenied"?ds:ps(e)??ls}function Sn(e){if(!e)return{mcpServer:null,mcpTool:null};let t=/^mcp__(.+?)__(.+)$/i.exec(e);if(t?.[1]&&t[2])return{mcpServer:t[1],mcpTool:t[2]};if(/^MCP:/i.test(e)){let n=e.slice(4);if(!n)return{mcpServer:null,mcpTool:null};let o=n.indexOf(":");return o>0?{mcpServer:n.slice(0,o),mcpTool:n.slice(o+1)||null}:{mcpServer:null,mcpTool:n}}return{mcpServer:null,mcpTool:null}}var V="__post",Ge="__work";function hs(e,t){let n=e.payload,o=n&&typeof n=="object"&&!Array.isArray(n)?Object.keys(n):[],r=e.correlation&&typeof e.correlation=="object"?Object.keys(e.correlation):[];return JSON.stringify({event:e.event,schema_version:e.schema_version,agent_hook_version:e.agent_hook_version,host_arch:e.host_arch,node_version:e.node_version,body_bytes:t,correlation_keys:r,payload_keys:o})}function wn(e){switch(e){case"session_start":return qe;case"session_end":return Ze;case"tool_invoked":case"skill_invoked":return Ee;default:return Ee}}function _s(e,t,n){return`${JSON.stringify({url:e,timeoutMs:t})}
16
- ${n}`}function In(e,t=[],n=process.execPath,o=import.meta.url,r=En){if(ms(n)===P)return{command:n,args:[e,...t]};let s=gs(o);return r(s)?{command:n,args:[s,e,...t]}:{command:n,args:[e,...t]}}function ks(e=process.execPath,t=import.meta.url,n=En){return In(V,[],e,t,n)}function ys(e){let t=e.indexOf(`
17
- `);if(t<0)return null;let n;try{n=JSON.parse(e.slice(0,t))}catch{return null}return{meta:n,body:e.slice(t+1)}}async function ge(e,t=fetch){let n=await e(),o=ys(n);if(!o)return;let{meta:r,body:s}=o,a={"Content-Type":"application/json"};try{await t(r.url,{method:"POST",headers:a,body:s,signal:AbortSignal.timeout(Number(r.timeoutMs))})}catch{}}async function Ss(e,t,n){let o=wn(e);l(`POST event=${e} url=${we(n)} size=${t.length} platform=${process.platform}`);let r={"Content-Type":"application/json"},s=Date.now();try{let a=await fetch(n,{method:"POST",headers:r,body:t,signal:AbortSignal.timeout(o)}),i=Date.now()-s;if(a.ok)return l(`POST outcome=ok elapsed_ms=${i} http=${a.status}`),!0;let c=(await a.text()).slice(0,200).replace(/[\n\r]/g,"");return l(`POST outcome=fail elapsed_ms=${i} http=${a.status} body=${c}`),!1}catch(a){let i=Date.now()-s,c=a instanceof Error?a.message:String(a);return l(`POST outcome=fail elapsed_ms=${i} http=000 body=${c}`),!1}}async function xn(e,t,n,o,r){try{let s=o(e,t,{detached:!0,stdio:["pipe","ignore","ignore"],windowsHide:!0});s.on("error",()=>{}),s.stdin.on("error",()=>{});let a=!1;return await new Promise(i=>{let c=setTimeout(()=>{if(!a){l(`WARN: ${r} stdin handoff timed out \u2014 continuing fail-open`);try{s.stdin.destroy()}catch{}}i()},Qe),u=()=>{a=!0,clearTimeout(c),i()};s.stdin.end(n,()=>u()),s.stdin.once("error",()=>u())}),s.unref(),s}catch(s){let a=s instanceof Error?s.message:String(s);return l(`WARN: ${r} spawn failed open: ${a}`),null}}async function Es(e,t,n,o=vn,r=ks){let s=wn(e),a=_s(n,s,t),{command:i,args:c}=r();return xn(i,c,a,o,"detached post")}async function bn(e,t,n=vn,o=In){let{command:r,args:s}=o(Ge,t);return xn(r,s,e,n,"detached work")}async function z(e,t,n,o,r){if(!r){l("WARN: collector URL missing \u2014 pass --url on the hook command or set collector_url in manifest");return}if(!ee(r)){l(`WARN: collector URL blocked (https required): ${we(r)}`);return}let s=o(e,t,n),a=`${JSON.stringify(s)}
18
- `,i=g("EVALON_HOOK_DEBUG");if(i==="full"?l(`DEBUG envelope=${JSON.stringify(s)}`):i==="1"&&l(`DEBUG summary=${hs(s,Buffer.byteLength(a,"utf8"))}`),!me(n.runnerEvent,n.runnerPlatform)){await Es(e,a,r);return}await Ss(e,a,r)}import{relative as vs,resolve as Je,sep as Rn}from"node:path";var ws=["session_id","conversation_id","turn_id","generation_id","prompt.id","prompt_id","hook_event_name","event","source","status","stop_reason","reason","tool_name","tool","tool_use_id","skill_name","command_name","expansion_type","command_source","permission_mode","model","model_id","agent_id","agent_type","subagent_id","subagent_type","subagent_model","is_parallel_worker","effort","effort.level","duration_ms","duration","failure_type","is_interrupt"];function Is(e){return e.capture_hook_input==="full"?!0:e.capture_hook_input==="allowlist"?!1:g("EVALON_HOOK_CAPTURE_FULL_INPUT")==="1"}function xs(e){let t={};for(let n of ws){let o=N(e,n);o!==void 0&&(t[n]=o)}return t}function bs(e,t){if(typeof e!="string"||e.length===0||!t)return null;let n=Je(e),o=Je(t),r=vs(o,n);return!r||r==="."?".":r.startsWith(`..${Rn}`)||r===".."||Je(o,r)!==n?null:r.split(Rn).join("/")}function Cn(e,t){let n=JSON.stringify(e),o=Buffer.byteLength(n,"utf8");if(o<=t)return e;let r=Object.entries(e).filter(([a,i])=>!a.startsWith("_")&&(typeof i=="string"||typeof i=="number"||typeof i=="boolean")).sort((a,i)=>Buffer.byteLength(JSON.stringify(a[1]),"utf8")-Buffer.byteLength(JSON.stringify(i[1]),"utf8")),s={_truncated:!0,_original_bytes:o};for(let[a,i]of r){let c={...s,[a]:i};if(Buffer.byteLength(JSON.stringify(c),"utf8")>t)break;s[a]=i}return s}function Y(e,t,n={}){let o=n.gitRoot!==void 0?bs(e.cwd,n.gitRoot):null;if(Is(t)){let s={...e};return delete s.cwd,delete s.transcript_path,o!==null&&(s.cwd_relative=o),Cn(s,tt)}let r=xs(e);return o!==null&&(r.cwd_relative=o),Cn(r,et)}import{createReadStream as Rs}from"node:fs";import{stat as Cs}from"node:fs/promises";import{basename as As,resolve as Os}from"node:path";import{createInterface as Ps}from"node:readline";var Ts=1024*1024;function Ns(e){let t=e.replace(/\\/g,"/");return t.includes("/.claude/projects/")&&As(t).endsWith(".jsonl")}async function An(e){if(!e||!Ns(e))return null;try{let t=Os(e),n=await Cs(t);if(!n.isFile())return null;let o=Math.max(0,n.size-Ts),r=[],s=Ps({input:Rs(t,{encoding:"utf8",start:o}),crlfDelay:1/0});for await(let a of s)a.length!==0&&r.push(a);o>0&&r.length>0&&r.shift();for(let a=r.length-1;a>=0;a--){let i=r[a];if(i)try{let c=JSON.parse(i);if(c.type!=="assistant")continue;let u=c.message;if(!u||typeof u!="object")continue;let p=u.model;if(typeof p=="string"&&p.length>0)return p}catch{continue}}return null}catch{return null}}function he(e){return{sessionId:e.sessionId,turnId:e.turnId,installationId:e.manifest.installationId,runnerPlatform:e.runnerPlatform,platformAgentId:e.platformAgentId,runnerEvent:e.runnerEvent}}function Hs(...e){for(let t of e)if(t)return t;return null}function U(e,t,n){if(e.status==="fulfilled")return e.value;let o=e.reason instanceof Error?e.reason.message:String(e.reason);return l(`WARN: ${n} failed open: ${o}`),t}function Ms(e){let t={present:!1,size:0},n={hash:"",count:0};return{runner_platform:e,config_scope:"user",cli_version:null,claude_version:null,model:null,permission_keys:[],user_scope:{skills:n,subagents:n,commands:n,rules:n,memory:t,settings:t,mcp:t},local_settings:t}}async function _e(e,t,n){try{e.platformAgentId=await Wt(e.manifest.manifest,e.platformAgentId,String(e.runnerPlatform),t,n,e.manifest.installationStorePath)}catch(o){let r=o instanceof Error?o.message:String(o);l(`WARN: derivePlatformAgentId failed open: ${r}`)}}async function Ls(e){let{gitRoot:t}=e.manifest,n=Vt(),o=String(e.runnerPlatform),[r,s,a,i,c,u]=await Promise.allSettled([Le(t),zt(),Zt(n),Yt(),Qt(e.manifest.manifest,t,o),an(o,t)]),p=U(r,null,"gitSnapshot"),m=U(s,"","detectVirt"),E=U(a,null,"probeCloud"),k=U(i,{},"hostEnv"),O=U(c,[],"mcpDeclared"),v=U(u,Ms(o),"selfConfig");await _e(e,t,p);let y=d(e.hookInput,"model");y&&(v.model=y);let j={identity:{host:Xt(),context:n,virt:m||null,cloud:E,git:p},host_env:k,env_vars:en(),mcp:{declared:O},self_config:v,run_meta:{trigger:e.hookSource||"startup"},hook_input:Y(e.hookInput,e.manifest.manifest,{gitRoot:t})};await z("session_start",j,he(e),W,e.manifest.collectorUrl)}async function Us(e){let{gitRoot:t}=e.manifest;await _e(e,t);let n=Hs(d(e.hookInput,"status"),d(e.hookInput,"stop_reason"),d(e.hookInput,"reason"),Ke(d(e.hookInput,"error"))),o=e.runnerPlatform==="claude"?await An(d(e.hookInput,"transcript_path")):null,r=Y(e.hookInput,e.manifest.manifest,{gitRoot:t});o&&(r.model=o),await z("session_end",{status:n,...o?{model:o}:{},hook_input:r},he(e),W,e.manifest.collectorUrl)}async function js(e){let t=fn(e.hookInput);if(t.length===0)return;let{gitRoot:n}=e.manifest;await _e(e,n);let o=Y(e.hookInput,e.manifest.manifest,{gitRoot:n}),r=he(e);await Promise.all(t.map(s=>z("tool_invoked",{tool_name:"Skill",skill_name:s,success:null,duration_ms:null,hook_input:o},r,W,e.manifest.collectorUrl)))}async function Fs(e){let{gitRoot:t}=e.manifest;await _e(e,t);let{toolName:n,skillName:o}=hn(e.hookInput),r=kn(e.hookInput),s=pn(e.runnerEvent),a=s===!1?yn(e.hookInput,e.runnerEvent):null,{mcpServer:i,mcpTool:c}=Sn(n),u=_n(e.hookInput);await z("tool_invoked",{tool_name:n,skill_name:o,success:s,duration_ms:r,...a?{failure_reason:a}:{},...i?{mcp_server:i}:{},...c?{mcp_tool:c}:{},...u?{subagent_type:u}:{},hook_input:Y(e.hookInput,e.manifest.manifest,{gitRoot:t})},he(e),W,e.manifest.collectorUrl)}async function On(e){switch(e.internalEvent){case"session_start":await Ls(e);return;case"session_end":await Us(e);return;case"skill_invoked":await js(e);return;case"tool_invoked":await Fs(e);return;default:return}}function Pn(e){return e!=="session_start"&&e!=="session_end"&&e!=="tool_invoked"&&e!=="skill_invoked"&&e!==""}async function Tn(e,t,n,o){let r=t??await Ie(ve),s=_(r,{}),a=await Et();if(!a)return;o&&(a.collectorUrl=o);let i=mn(s,a.manifest.platform,n),c=gn(e,i.runnerEvent);if(!c){l(`WARN: unknown hook event '${i.runnerEvent}'; skipping telemetry`);return}let u={hookInput:s,sessionId:i.sessionId,turnId:i.turnId,runnerEvent:i.runnerEvent,runnerPlatform:i.runnerPlatform,hookSource:i.hookSource,internalEvent:c,manifest:a,platformAgentId:a.platformAgentId};if(Pn(c)){l(`WARN: unsupported internal event '${c}'`);return}await On(u)}function Ds(e,t){if(g("EVALON_HOOK_SYNC")==="1")return!0;let n=pe(e),o=_(t,{}),r=n.event??(d(o,"hook_event_name")||d(o,"event")),s=Be(o,r,void 0,n.runner);return me(r,s)}async function Nn(e=process.argv.slice(2)){if(e[0]===V){try{await ge(te)}catch{}return 0}if(e[0]===Ge){try{let t=pe(e.slice(1));await Tn(t.event,void 0,t.runner,$e(t))}catch(t){let n=t instanceof Error?t.message:String(t);l(`WARN: detached work failed open: ${n}`)}return 0}try{let t=await Ie(ve),n=pe(e),o=$e(n);Ds(e,t)?await Tn(n.event,t,n.runner,o):await bn(t,e)}catch(t){let n=t instanceof Error?t.message:String(t);l(`WARN: hook failed open: ${n}`)}finally{mt()}return 0}function ke(){l("Usage: evalon-agent-hook <configure|install|migrate-to-plugin|update|uninstall|--version>"),l(" configure [--url <\u2026/{orgToken}/hook>]"),l(" (manifest only \u2014 pair with marketplace plugins)"),l(" install --url <\u2026/{orgToken}/hook>"),l(" [--delivery npx|binary] [--force]"),l(" [--no-claude] [--no-cursor] [--no-codex]"),l(" (fallback: merge hooks into .claude / .cursor / .codex configs)"),l(" (writes collector_url to shared manifest; hook commands use --runner only)"),l(" migrate-to-plugin"),l(" (strip Evalon file hooks; keep collector manifest)"),l(" update (refresh binary pins from a local build; leaves hook configs alone)"),l(" uninstall"),l("Hook mode: --runner <platform> [--url <\u2026/hook>|--token <orgToken>] [event]"),l(" (--url/--token optional overrides; else collector_url from manifest)")}function Hn(e){return e.includes("--help")||e.includes("-h")}async function Js(e=process.argv.slice(2)){let[t,...n]=e;if(t===V){try{await ge(te)}catch{}return 0}return t==="--version"||t==="-V"?(process.stdout.write(`${b}
19
- `),0):t==="configure"?Hn(n)?(ke(),0):(await Bt(Ct(n)),0):t==="install"?Hn(n)?(ke(),0):(await Dt(At(n)),0):t==="migrate-to-plugin"?(await Gt(),0):t==="update"?(await $t(),0):t==="uninstall"?(await Jt(),0):t==="help"||t==="--help"||t==="-h"?(ke(),0):t===void 0?(ke(),1):Nn(e)}function Ws(e,t,n=$s){if(!t)return!1;try{return e===Gs(Bs(t)).href?!0:n(Ks(e))===n(t)}catch{return!1}}Ws(import.meta.url,process.argv[1])&&process.env.VITEST===void 0&&Js().then(e=>{process.exit(e)}).catch(e=>{let t=e instanceof Error?e.message:String(e);l(t),process.exit(1)});export{Ws as isCliEntrypoint,Js as main};
12
+ npx ${Ce} install`)}function qn(e){return typeof e!="string"?!1:e.includes("@ev-ai/agent-hook")||e.includes("agent-hook/dist/hook")||e.includes(".ev-ai/agent-hook")||e.includes(J)||/(?:^|[\s/"'])ev-ai-agent-hook(?:$|[\s"'])/.test(e)}function ft(e,t){return`${e.replace(/\s+--runner(?:=|\s+)\S+/g,"").trimEnd()} --runner ${t}`}function V(e,t){ut(dt(e),{recursive:!0}),Bo(e,`${JSON.stringify(t,null,2)}
13
+ `,"utf8")}function B(e){if(F(e))try{return JSON.parse(Fo(e,"utf8"))}catch(t){throw t instanceof SyntaxError?new Error(`Invalid JSON in ${e} \u2014 fix or remove the file`,{cause:t}):t}}function as(e,t){let n=Ln(t.collectorUrl),r={...e,schema_version:e?.schema_version??n.schema_version};return t.collectorUrl!==void 0?r.collector_url=t.collectorUrl:r.collector_url=e?.collector_url??n.collector_url,delete r.repo_ingest_token,delete r.installation_id,r.mcp_servers??=n.mcp_servers,r}function cs(e){return(e.schema_version??2)===2&&e.collector_url===void 0&&(e.mcp_servers?.length??0)===0&&e.platform_agent_id===void 0&&e.capture_hook_input===void 0&&e.repo_ingest_token===void 0}function Zn(e,t){let n=h(e,Re),r=B(n),o=as(r,t);return t.collectorUrl!==void 0||F(n)||!cs(o)?(V(n,o),{manifestPath:n,wrote:!0}):{manifestPath:void 0,wrote:!1}}function lt(e){if(e===null||typeof e!="object")return!1;let t=e,n=String(t.CLAUDE_CODE_ENABLE_TELEMETRY??"").toLowerCase();return n==="1"||n==="true"?!0:Object.keys(t).some(r=>r.startsWith("OTEL_"))}function ls(e=process.platform){switch(e){case"darwin":return"/Library/Application Support/ClaudeCode";case"win32":return h(process.env.ProgramFiles??"C:\\Program Files","ClaudeCode");default:return"/etc/claude-code"}}function us(e=process.platform){let t=ls(e),n=[h(t,"managed-settings.json")],r=h(t,"managed-settings.d");try{if(!F(r))return n;let o=Do(r).filter(s=>s.endsWith(".json")&&!s.startsWith(".")).sort().map(s=>h(r,s));n.push(...o)}catch{}return n}function ds(e){if(lt(process.env))return!0;let t=j();return[...us(),h(t,".claude","settings.json"),h(t,".claude","remote-settings.json"),h(e,".claude","settings.json"),h(e,".claude","settings.local.json")].some(r=>{try{let o=B(r);return o?lt(o.env):!1}catch{return!1}})}function fs(e){try{let t=B(h(e,".claude","settings.json"));return t?lt(t.env):!1}catch{return!1}}function Qn(e){return Array.isArray(e)?e:[]}function Ue(e){let t=[],n=r=>!!r&&typeof r=="object"&&qn(r.command);for(let r of Qn(e)){if(!r||typeof r!="object"){t.push(r);continue}let o=Array.isArray(r.hooks)?r.hooks:[],s=o.filter(i=>!n(i));if(!(s.length===0&&o.some(n))){if(s.length!==o.length){t.push({...r,hooks:s});continue}t.push(r)}}return t}function er(e,t){return[...Ue(e),...t]}function pt(e){return Array.isArray(e)?e.filter(t=>!t||typeof t!="object"?!0:!qn(t.command)):[]}function ps(e,t){return[...pt(e),{command:t}]}function ms(e){let t=()=>({hooks:[{type:"command",command:e}]});return{SessionStart:[t()],UserPromptExpansion:[t()],PreToolUse:[t()],PostToolUse:[t()],PostToolUseFailure:[t()],PermissionDenied:[t()],Stop:[t()],StopFailure:[t()],SessionEnd:[t()],SubagentStart:[t()],SubagentStop:[t()]}}function gs(e){let t={type:"command",command:e,statusMessage:rn},n=()=>({hooks:[t]});return{SessionStart:[n()],UserPromptSubmit:[n()],PreToolUse:[n()],PostToolUse:[n()],Stop:[n()]}}var hs=["sessionStart","beforeSubmitPrompt","preToolUse","postToolUse","postToolUseFailure","subagentStart","subagentStop","stop"],_s=["beforeMCPExecution","beforeShellExecution","afterFileEdit"];function Ss(e){let t={...e};for(let n of _s){if(!(n in t))continue;let r=pt(t[n]);r.length===0?delete t[n]:t[n]=r}return t}function Es(e,t,n={}){let r=h(e,".claude/settings.json"),o=ft(t,"claude"),s=B(r)??{};if(ds(e)&&!n.force){if(s.hooks&&typeof s.hooks=="object"){let l={...s.hooks};for(let f of Object.keys(l))l[f]=Ue(l[f]),Qn(l[f]).length===0&&delete l[f];Object.keys(l).length===0?delete s.hooks:s.hooks=l,V(r,s)}return!1}let a=s.hooks&&typeof s.hooks=="object"?s.hooks:{},c=ms(o),u={...a};for(let[l,f]of Object.entries(c))u[l]=er(a[l],f);return s.hooks=u,V(r,s),!0}function ys(e,t){let n=h(e,".cursor/hooks.json"),r=ft(t,"cursor"),o=B(n)??{},s=o.hooks&&typeof o.hooks=="object"?o.hooks:{},i=Ss({...s});for(let a of hs)i[a]=ps(i[a],r);V(n,{...o,version:typeof o.version=="number"?o.version:1,hooks:i})}function ks(e,t){let n=h(e,".codex/hooks.json"),r=ft(t,"codex"),o=B(n)??{},s=o.hooks&&typeof o.hooks=="object"?o.hooks:{},i=gs(r),a={...s};for(let[c,u]of Object.entries(i))a[c]=er(s[c],u);V(n,{...o,hooks:a})}function Is(e){let t=h(e,".claude/settings.json"),n=B(t);if(!n?.hooks||typeof n.hooks!="object")return;let r={...n.hooks},o=!1;for(let s of Object.keys(r)){let i=r[s],a=Ue(i);JSON.stringify(i)!==JSON.stringify(a)&&(o=!0),a.length===0?delete r[s]:r[s]=a}o&&(Object.keys(r).length===0?delete n.hooks:n.hooks=r,V(t,n),d(`Removed ev-ai hooks from ${t}`))}function Rs(e){let t=h(e,".cursor/hooks.json"),n=B(t);if(!n?.hooks||typeof n.hooks!="object")return;let r={...n.hooks},o=!1,s=0;for(let i of Object.keys(r)){let a=r[i],c=pt(a);JSON.stringify(a)!==JSON.stringify(c)&&(o=!0),c.length===0?delete r[i]:(r[i]=c,s+=c.length)}if(o){if(s===0&&Object.keys(r).length===0&&Object.keys(n).filter(a=>a!=="hooks"&&a!=="version").length===0){be(t,{force:!0}),d(`Removed ${t}`);return}V(t,{...n,hooks:r}),d(`Removed ev-ai hooks from ${t}`)}}function Cs(e){let t=h(e,".codex/hooks.json"),n=B(t);if(!n?.hooks||typeof n.hooks!="object")return;let r={...n.hooks},o=!1,s=0;for(let i of Object.keys(r)){let a=r[i],c=Ue(a);JSON.stringify(a)!==JSON.stringify(c)&&(o=!0),c.length===0?delete r[i]:(r[i]=c,s+=c.length)}if(o){if(s===0&&Object.keys(r).length===0&&Object.keys(n).filter(a=>a!=="hooks").length===0){be(t,{force:!0}),d(`Removed ${t}`);return}V(t,{...n,hooks:r}),d(`Removed ev-ai hooks from ${t}`)}}function mt(e=process.platform,t=process.arch,n={}){if(e==="win32")throw new Error("Windows install is not supported yet. Use macOS/Linux, or wait for phase-2 native commands.");(n.requireBinaryArch??!0)&&Hn(e,t)}async function tr(e={}){let t=zo(e);e.collectorUrl=t;let n=e.skipClaude===!0,r=e.skipCursor===!0,o=e.skipCodex===!0;if(n&&r&&o)throw new Error("at least one runner must be wired; refuse --no-claude --no-cursor --no-codex together");let s=e.delivery??Jn();mt(process.platform,process.arch,{requireBinaryArch:s==="binary"});let i=e.cwd??process.cwd(),a=await M(i),{command:c,hookPath:u,strategy:l}=is(a,j(),s),{installationId:f,storePath:g}=await Oe(a,{overrideId:e.installationId}),{manifestPath:p,wrote:_}=Zn(a,e),R=[];return n?d("Skipped Claude hook \u2014 --no-claude"):Es(a,c,{force:e.force})?(R.push("Claude"),e.force&&fs(a)&&d("Forced Claude hook despite project native OTEL \u2014 expect duplicate session/tool events")):d("Skipped Claude hook \u2014 native OTEL telemetry already enabled (avoids duplicate events); pass --force to wire anyway"),r?d("Skipped Cursor hook \u2014 --no-cursor"):(ys(a,c),R.push("Cursor")),o?d("Skipped Codex hook \u2014 --no-codex"):(ks(a,c),R.push("Codex")),d(`Installed hook (${l}) at ${u}`),d(`Installation identity ${f} at ${g}`),_&&p?d(`Shared manifest written to ${p}`):d("Using package default collector config (no shared manifest file needed)"),d(R.length>0?`Wired ${R.join(", ")} hooks in ${a} (commands include --runner)`:`No runner hooks wired in ${a} (Claude skipped by OTEL; Cursor/Codex excluded via flags)`),l==="npx"?d("Hook commands use npx and may be committed; teammates need Node on PATH only (no install step, no env vars when collector_url is in the shared manifest)."):l==="project_binary"?d("Hook commands are git-root-relative and may be committed; each collaborator runs install once to populate .ev-ai/agent-hook/ (gitignored)."):l==="dev_mjs"&&d("Hook commands use node + monorepo packages/agent-hook/dist/hook.mjs (local delivery; rebuild with yarn workspace @ev-ai/agent-hook build)."),_&&p&&e.collectorUrl&&d("Shared manifest includes collector_url \u2014 commit it with hook configs so teammates post without env vars."),{gitRoot:a,hookPath:u,manifestPath:p,installationStorePath:g,strategy:l}}async function nr(e=process.cwd()){mt(process.platform,process.arch,{requireBinaryArch:!0});let t=await M(e),{projectPath:n,globalPath:r}=os(t);d(`Refreshed ${r}`),d(`Refreshed ${n}`),d("Hook configs and shared manifest left unchanged")}async function rr(e={}){let t=Wo(e);e.collectorUrl=t,mt(process.platform,process.arch,{requireBinaryArch:!1});let n=e.cwd??process.cwd(),r=await M(n),{manifestPath:o,wrote:s}=Zn(r,e);if(t!==void 0&&(!o||!s))throw new Error("configure failed to write shared collector manifest");return s&&o?d(`Wrote ${o}`):t===void 0&&d("No --url given and no shared manifest yet \u2014 pass --url <\u2026/{orgToken}/hook> to write collector destination."),d("Manifest only \u2014 enable ev-ai marketplace plugins. Do not also run file-wiring install for the same events."),{gitRoot:r,manifestPath:o}}function or(e){for(let t of[()=>Is(e),()=>Rs(e),()=>Cs(e)])try{t()}catch(n){let r=n instanceof Error?n.message:String(n);d(`WARN: strip skipped a hook file: ${r}`)}}async function sr(e=process.cwd()){let t=await M(e);return or(t),d("Stripped ev-ai file-wired hooks; shared collector manifest left in place."),d("Next: enable ev-ai marketplace plugins, then restart runners."),{gitRoot:t}}async function ir(e=process.cwd()){let t=await M(e);or(t);for(let n of ve){let r=h(t,n);if(F(r))try{be(r,{force:!0}),d(`Removed ${r}`)}catch(o){let s=o instanceof Error?o.message:String(o);d(`WARN: uninstall could not remove ${r}: ${s}`)}}}var xs={claude:".claude",cursor:".cursor",codex:".codex"};function pe(e){let n=e.replace(/^\/+|\/+$/g,"").toLowerCase().split("/").filter(Boolean);return n.length<2?"":n.join("/")}function As(e){if(!e)return"";let t=e.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1");t=t.replace(/\.git$/i,"");let n=t.match(/^git@[^:]+:(.+)$/);if(n?.[1])return pe(n[1]);let r=t.match(/^ssh:\/\/[^/]+\/(.+)$/i);if(r?.[1])return pe(r[1]);t=t.replace(/^https:\/\//i,""),t=t.replace(/^http:\/\//i,""),t=t.replace(/^ssh:\/\//i,"");let o=t.match(/^[^/]+\/(.+)$/);return o?.[1]?pe(o[1]):pe(t)}async function me(e=process.cwd()){let t=await D("git",["rev-parse","--is-inside-work-tree"],2e3,{cwd:e});if(!t.ok||t.stdout!=="true")return null;let[n,r,o,s]=await Promise.all([D("git",["remote","get-url","origin"],2e3,{cwd:e}),D("git",["branch","--show-current"],2e3,{cwd:e}),D("git",["rev-parse","HEAD"],2e3,{cwd:e}),D("git",["status","--porcelain"],2e3,{cwd:e})]),i=n.ok?n.stdout:null;return{remote:i===null?null:i.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1"),branch:r.ok?r.stdout:null,head:o.ok?o.stdout:null,dirty:s.ok?s.stdout.length>0:null}}async function ar(e,t,n,r=process.cwd(),o,s,i){if(t)return t;let a=xs[n];if(!a)return"";let c=Cn(n,e.scope_path,i);if(s){let _=wn(s,c);if(_)return _}let u=o??await me(r),l=u?.remote?As(u.remote):"";if(l||(l=pe(process.env.GITHUB_REPOSITORY??"")),!l)return"";let f=e.scope_path??"",g=f?`${f}/`:"",p=`${l}:${g}${a}`;return s&&Un(s,c,p),p}import{existsSync as Ts,readFileSync as Os}from"node:fs";import{hostname as vs,userInfo as bs}from"node:os";function Pe(e){if(e===void 0||e==="")return!1;let t=e.trim().toLowerCase();return t!=="0"&&t!=="false"&&t!=="no"}var ws=["GITLAB_CI","CIRCLECI","BUILDKITE","TF_BUILD","JENKINS_URL","JENKINS_HOME","CODEBUILD_BUILD_ID","DRONE","DRONE_BUILD_NUMBER","TEAMCITY_VERSION","TRAVIS","APPVEYOR","BITBUCKET_BUILD_NUMBER"];function Us(){return ws.some(e=>!!E(e))}function Ps(){if(E("KUBERNETES_SERVICE_HOST")||Pe(E("REMOTE_CONTAINERS"))||Pe(E("DEVCONTAINER")))return!0;try{if(Ts("/.dockerenv")||Os("/proc/1/environ","utf8").includes("container="))return!0}catch{}return!1}function gt(){if(E("GITHUB_ACTIONS"))return"github_actions";if(Pe(E("CLAUDE_CODE_REMOTE")))return"claude_remote";if(Pe(E("CURSOR_AGENT")))return"cursor_cloud";if(E("CODESPACES")||E("CODESPACE_NAME"))return"codespaces";if(Us())return"managed";let e=E("CI");return e&&e!=="false"&&e!=="0"?"managed":Ps()?"container":process.stdin.isTTY||process.stdout.isTTY||E("TERM")?"interactive":"cron"}async function ht(){return await C("systemd-detect-virt",[],1e3)}function Ns(e=process.env,t=bs){for(let n of["USER","LOGNAME","USERNAME"]){let r=e[n];if(typeof r=="string"){let o=r.trim();if(o.length>0)return o}}try{return t().username??""}catch{return""}}async function _t(){let e=process.platform==="darwin"?"Darwin":process.platform==="win32"?"Windows_NT":"Linux",t="";if(process.platform==="darwin")t=await C("sw_vers",["-productVersion"],1e3);else if(process.platform==="linux"){try{let{readFileSync:s}=await import("node:fs"),i=s("/etc/os-release","utf8"),a=i.match(/^PRETTY_NAME="?([^"\n]+)"?/m)?.[1],c=i.match(/^VERSION_ID="?([^"\n]+)"?/m)?.[1];t=a??c??""}catch{t=await C("lsb_release",["-sd"],1e3).then(s=>s.replace(/^"|"$/g,""))}t||(t=await C("uname",["-r"],1e3))}else t=await C("ver",[],1e3);let n=Ns(),r=(process.env.SHELL??"").split(/[/\\]/).pop()??"",o="";try{o=await C("tty",[],500),o.includes("not a tty")&&(o="")}catch{o=""}return{os:e,os_version:t||null,user:n||null,shell:r||null,tty:o||null}}function St(){return vs()}import{existsSync as Ms,readFileSync as Ls}from"node:fs";import{homedir as cr}from"node:os";import{join as Hs}from"node:path";var Ds="cloud-cache.json",Fs=1440*60*1e3,js=900*1e3;function Bs(e=cr()){return Hs(ot(e),Ds)}function $s(e){if(!Ms(e))return;let t=v(Ls(e,"utf8"),{});if(!(typeof t.context!="string"||typeof t.probed_at!="number"||t.result!==null&&t.result!==void 0&&typeof t.result!="object"))return{context:t.context,probed_at:t.probed_at,result:t.result??null}}function Gs(e,t){try{z(e,`${JSON.stringify(t)}
14
+ `)}catch(n){let r=n instanceof Error?n.message:String(n);d(`WARN: cloud cache write failed open: ${r}`)}}function Ks(e,t,n){if(!e||e.context!==t)return!1;let r=e.result===null?js:Fs;return n-e.probed_at<r}async function Js(e){let t=await fetch("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"60"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=(await t.text()).trim();if(!n)return;let r={"X-aws-ec2-metadata-token":n},[o,s]=await Promise.all([fetch("http://169.254.169.254/latest/meta-data/placement/region",{headers:r,signal:AbortSignal.timeout(e)}).catch(()=>{}),fetch("http://169.254.169.254/latest/meta-data/instance-id",{headers:r,signal:AbortSignal.timeout(e)}).catch(()=>{})]);if(!o?.ok&&!s?.ok)return;let i=o?.ok?(await o.text()).trim():"",a=s?.ok?(await s.text()).trim():"";if(!(!i&&!a))return{provider:"aws",region:i,instance_id:a}}async function Vs(e){let t=await fetch("http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true",{headers:{"Metadata-Flavor":"Google"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=await t.json(),r=typeof n.zone=="string"?n.zone.split("/").pop()??"":"",o=n.id===void 0?"":String(n.id);if(!(!r&&!o))return{provider:"gcp",region:r,instance_id:o}}async function Ws(e){let t=await fetch("http://169.254.169.254/metadata/instance?api-version=2021-02-01",{headers:{Metadata:"true"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=await t.json(),r=n.compute?.location??"",o=n.compute?.vmId??"";if(!(!r&&!o))return{provider:"azure",region:r,instance_id:o}}async function zs(e){let t=await Promise.allSettled([Js(e),Vs(e),Ws(e)]);for(let n of t)if(n.status==="fulfilled"&&n.value)return n.value;return null}async function Et(e,t){if(e==="interactive")return null;let n=t?.home??cr(),r=t?.timeoutMs??1e3,o=t?.nowMs??Date.now(),s=Bs(n),i=$s(s);if(Ks(i,e,o))return i.result;let a=await zs(r);return Gs(s,{context:e,probed_at:o,result:a}),a}import{existsSync as Ys}from"node:fs";import{homedir as Xs}from"node:os";import{join as yt}from"node:path";function kt(e,t,n){if(!Ys(e))return;let r=ne(e,{});for(let o of Object.keys(r.mcpServers??{}))n.set(o,{name:o,source:t})}async function It(e,t=process.cwd(),n="claude",r=Xs()){let o=new Map;for(let s of e.mcp_servers??[])s.name&&o.set(s.name,{name:s.name,source:"manifest"});return n==="claude"&&kt(yt(r,".claude.json"),"claude_json_user",o),kt(yt(t,".mcp.json"),"mcp_json",o),kt(yt(t,".cursor/mcp.json"),"cursor_mcp",o),[...o.values()]}var qs=["CI","GITHUB_ACTIONS","GITLAB_CI","CIRCLECI","BUILDKITE","TF_BUILD","JENKINS_URL","JENKINS_HOME","CODEBUILD_BUILD_ID","DRONE","DRONE_BUILD_NUMBER","TEAMCITY_VERSION","TRAVIS","APPVEYOR","BITBUCKET_BUILD_NUMBER","KUBERNETES_SERVICE_HOST","REMOTE_CONTAINERS","DEVCONTAINER","GITHUB_REPOSITORY","GITHUB_REPOSITORY_ID","GITHUB_REF","GITHUB_SHA","GITHUB_RUN_ID","GITHUB_WORKFLOW","GITHUB_ACTOR","GITHUB_TRIGGERING_ACTOR","GITHUB_ACTOR_ID","GITHUB_USER","GITLAB_USER_LOGIN","GITLAB_USER_NAME","GITLAB_USER_EMAIL","BUILD_REQUESTEDFOR","BUILD_REQUESTEDFOREMAIL","BUILDKITE_BUILD_CREATOR","BUILDKITE_BUILD_CREATOR_EMAIL","BUILD_USER","BUILD_USER_ID","BUILD_USER_EMAIL","CHANGE_AUTHOR","CHANGE_AUTHOR_EMAIL","CIRCLE_USERNAME","CODEBUILD_INITIATOR","DRONE_COMMIT_AUTHOR","DRONE_COMMIT_AUTHOR_NAME","DRONE_COMMIT_AUTHOR_EMAIL","EV_AI_HOOK_OPERATOR_NAME","EV_AI_HOOK_OPERATOR_EMAIL","GIT_AUTHOR_NAME","GIT_AUTHOR_EMAIL","GIT_COMMITTER_NAME","GIT_COMMITTER_EMAIL","EMAIL","RUNNER_OS","RUNNER_ARCH","NODE_ENV","TERM_PROGRAM","CLAUDE_CODE_REMOTE","CLAUDE_CODE_REMOTE_SESSION_ID","CURSOR_AGENT","CODESPACES","CODESPACE_NAME","ANTHROPIC_BASE_URL","OPENAI_BASE_URL","OPENAI_API_BASE","AZURE_OPENAI_ENDPOINT","GOOGLE_GEMINI_BASE_URL","GEMINI_API_BASE","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX"],Zs=new Set(["key","api-key","api_key","apikey","token","sig","signature","access_token","password","pwd","secret","client_secret"]);function Qs(e){try{let t=new URL(e);(t.username||t.password)&&(t.username="",t.password="");for(let[n]of t.searchParams)Zs.has(n.toLowerCase())&&t.searchParams.set(n,"[redacted]");return t.toString()}catch{return e}}function Rt(e=process.env){return qs.map(t=>Object.prototype.hasOwnProperty.call(e,t)?{name:t,present:!0,value:Qs(e[t]??"")}:{name:t,present:!1})}import{createHash as ei}from"node:crypto";function I(e){return ei("sha256").update(e).digest("hex").slice(0,16)}function $(e,t){return`${e}\0${t}`}function lr(e){let t=e.indexOf("\0");return t<=0?null:{path:e.slice(0,t),name:e.slice(t+1)}}function Ct(e){let n=[...e].sort((r,o)=>{let s=r.path.localeCompare(o.path);return s!==0?s:r.name.localeCompare(o.name)}).map(r=>`${r.path}|${r.name}|${r.content_hash}`).join(`
15
+ `);return I(n)}function ti(e,t,n="git_config",r=null){return I(`${e??""}|${t??""}|${r??""}|${n}`)}function ni(e){let t=null,n=null;for(let r of e.split(`
16
+ `)){let o=r.trim();if(!o)continue;let s=o.indexOf(" ");if(s<=0)continue;let i=o.slice(0,s).toLowerCase(),a=o.slice(s+1).trim();a&&(i==="user.name"?t=a:i==="user.email"&&(n=a))}return{git_user_name:t,git_user_email:n,platform_login:null}}async function ri(e,t=C){let n=await t("git",["config","--get-regexp","^user\\.(name|email)$"],2e3,{cwd:e});return ni(n)}function oi(e=process.env){let t=S(e.GIT_AUTHOR_NAME),n=S(e.GIT_AUTHOR_EMAIL);if(t||n)return{git_user_name:t,git_user_email:n,platform_login:null,identity_source:"git_env"};let r=S(e.GIT_COMMITTER_NAME),o=S(e.GIT_COMMITTER_EMAIL);if(r||o)return{git_user_name:r,git_user_email:o,platform_login:null,identity_source:"git_env"};let s=S(e.EMAIL);return s?{git_user_name:null,git_user_email:s,platform_login:null,identity_source:"git_env"}:null}async function si(e,t=C){let n=await t("git",["log","-1","--format=%an%x00%ae"],2e3,{cwd:e});if(!n)return null;let r=n.indexOf("\0"),o=(r>=0?n.slice(0,r):n).trim(),s=(r>=0?n.slice(r+1):"").trim();return!o&&!s?null:{git_user_name:o||null,git_user_email:s||null,platform_login:null,identity_source:"git_log"}}function G(e,t,n,r=null){return!e&&!t&&!r?null:{git_user_name:e,git_user_email:t,platform_login:r,identity_source:n}}function ii(e=process.env){let t=G(S(e.EV_AI_HOOK_OPERATOR_NAME),S(e.EV_AI_HOOK_OPERATOR_EMAIL),"configured");if(t)return t;let n=S(e.GITHUB_ACTOR)??S(e.GITHUB_TRIGGERING_ACTOR)??S(e.GITHUB_USER),r=G(n,null,"github",n);if(r)return r;let o=S(e.GITLAB_USER_LOGIN),s=G(S(e.GITLAB_USER_NAME)??o,S(e.GITLAB_USER_EMAIL),"gitlab",o);if(s)return s;let i=G(S(e.BUILD_REQUESTEDFOR),S(e.BUILD_REQUESTEDFOREMAIL),"azure_devops");if(i)return i;let a=G(S(e.BUILDKITE_BUILD_CREATOR),S(e.BUILDKITE_BUILD_CREATOR_EMAIL),"buildkite");if(a)return a;let c=G(S(e.BUILD_USER)??S(e.CHANGE_AUTHOR),S(e.BUILD_USER_EMAIL)??S(e.CHANGE_AUTHOR_EMAIL),"jenkins",S(e.BUILD_USER_ID));if(c)return c;let u=S(e.CIRCLE_USERNAME),l=G(u,null,"circleci",u);if(l)return l;let f=S(e.CODEBUILD_INITIATOR),g=G(f,null,"codebuild",f);if(g)return g;let p=G(S(e.DRONE_COMMIT_AUTHOR)??S(e.DRONE_COMMIT_AUTHOR_NAME),S(e.DRONE_COMMIT_AUTHOR_EMAIL),"drone",S(e.DRONE_COMMIT_AUTHOR));return p||(ur(e.CLAUDE_CODE_REMOTE)||ur(e.CURSOR_AGENT)?{git_user_name:null,git_user_email:null,platform_login:null,identity_source:"cloud"}:null)}function xt(e){return!!((e.git_user_name??e.git_user_email)&&!li(e.git_user_name,e.git_user_email))}function S(e){if(e===void 0)return null;let t=e.trim();return t.length>0?t:null}function ur(e){if(e===void 0||e==="")return!1;let t=e.trim().toLowerCase();return t!=="0"&&t!=="false"&&t!=="no"}var ai=new Set(["action@github.com","noreply@github.com","noreply@anthropic.com","cursoragent@cursor.com"]),ci=new Set(["github-actions","github actions","dependabot","renovate","cursoragent","cursor agent"]);function li(e,t){let n=(e??"").trim().toLowerCase(),r=(t??"").trim().toLowerCase();if(!n&&!r)return!1;if(n.includes("[bot]")||ci.has(n)||r.includes("[bot]")||ai.has(r))return!0;if(r.endsWith("@users.noreply.github.com")){let o=r.slice(0,r.indexOf("@")),s=o.includes("+")?o.slice(o.indexOf("+")+1):o;if(s.endsWith("bot")||s.includes("[bot]"))return!0}return!1}async function ui(e,t=C,n=process.env){let r=await ri(e,t);if(xt(r))return{...r,identity_source:"git_config"};let o=oi(n);if(o&&xt(o))return o;let s=ii(n);if(s&&(s.git_user_name||s.git_user_email||s.platform_login))return s;let i=await si(e,t);return i&&xt(i)?i:s||(r.git_user_name||r.git_user_email?{...r,identity_source:"git_config"}:o||i||{git_user_name:null,git_user_email:null,platform_login:null,identity_source:"git_config"})}async function Ne(e){let{gitRoot:t,installationStorePath:n,forceResend:r}=e,o=e.exec??C,s=e.env??process.env,i=await ui(t,o,s),a=ti(i.git_user_name,i.git_user_email,i.identity_source,i.platform_login),u=(n?st(n):void 0)?.operator_identity_hash;if(!(r||u!==void 0&&u!==a||!u))return{commit:()=>{}};let p=n;return{operator:i,commit:()=>{p&&On(p,a,Ae())}}}function At(e){return e?!st(e)?.operator_identity_hash:!0}function dr(e){return!0}import{existsSync as Pi,readFileSync as Ni}from"node:fs";import{homedir as Or}from"node:os";import{join as P}from"node:path";import{basename as wi,join as re}from"node:path";import{existsSync as fr,readdirSync as di}from"node:fs";import{basename as fi,dirname as pi,relative as mi}from"node:path";var Me=class{constructor(t){this.home=t}components=[];truncated=!1;pluginExpandRemaining;homeRel(t){let n=mi(this.home,t).replace(/\\/g,"/");if(!n||n.startsWith("..")){let r=pi(t);return`external/${I(r)}/${fi(t)}`}return n}get atGlobalCap(){return this.truncated||this.components.length>=X}get pluginBudgetSpent(){return this.pluginExpandRemaining!==void 0&&this.pluginExpandRemaining<=0}readEntries(t){if(!fr(t))return[];try{return di(t,{withFileTypes:!0})}catch{return[]}}readJson(t,n){if(fr(t))return ne(t,n)}push(t){return this.components.length>=X?(this.truncated=!0,!1):this.pluginExpandRemaining!==void 0&&this.pluginExpandRemaining<=0?!1:(this.pluginExpandRemaining!==void 0&&(this.pluginExpandRemaining-=1),this.components.push(t),!0)}withPluginExpandCap(t,n){let r=this.pluginExpandRemaining;this.pluginExpandRemaining=t;try{let o=n(),s=t-(this.pluginExpandRemaining??0);return{result:o,expanded:s}}finally{this.pluginExpandRemaining=r}}};import{existsSync as Tt,readFileSync as gi,statSync as hi}from"node:fs";import{basename as mr,join as ge,relative as gr}from"node:path";var Ot=2e4,_i=4;function Si(e){return e.length<=Ot?e:`${e.slice(0,Ot-1)}\u2026`}function Ei(e){try{let t=gi(e),n=t.toString("utf8");return{hash:I(t),length:t.length,text:Si(n)}}catch{return null}}var pr={HOOK:"EVENT",COMMAND:"EXPLICIT_INVOCATION",MEMORY:void 0,MCP_SERVER:void 0,PLUGIN:void 0,SKILL:"UNSPECIFIED",RULE:"UNSPECIFIED",SUBAGENT:"UNSPECIFIED"};function yi(e){return e in pr?pr[e]:"UNSPECIFIED"}function Le(e,t){let n=Ei(t.absolutePath);if(!n)return!1;let r=t.name??mr(t.absolutePath).replace(/\.(md|mdc|toml)$/i,""),o={kind:t.kind,name:r,path:e.homeRel(t.absolutePath),text:n.text,content_hash:n.hash,content_length:n.length,origin:t.origin,enabled:t.enabled},s=yi(t.kind);return s&&(o.trigger=s),e.push(o)}function ki(e,t,n){let r=gr(e,t).replace(/\\/g,"/");return!r||r.startsWith("..")?mr(t).replace(/\.(md|mdc|toml)$/i,""):n?r.replace(/\.(md|mdc|toml)$/i,""):r}function Q(e,t){let{dir:n,kind:r,origin:o,enabled:s,nested:i,extensions:a}=t;vt(e,{walkRoot:n,currentDir:n,depth:0,kind:r,origin:o,enabled:s,nested:i,extensions:a})}function vt(e,t){let{walkRoot:n,currentDir:r,depth:o,kind:s,origin:i,enabled:a,nested:c,extensions:u}=t;if(!(o>_i))for(let l of e.readEntries(r)){if(e.atGlobalCap){e.truncated=!0;return}if(e.pluginBudgetSpent)return;if(c){if(!l.isDirectory())continue;let p=ge(r,l.name,c);if(Tt(p)){let _=gr(n,ge(r,l.name)).replace(/\\/g,"/");Le(e,{absolutePath:p,kind:s,origin:i,enabled:a,name:_||l.name});continue}vt(e,{walkRoot:n,currentDir:ge(r,l.name),depth:o+1,kind:s,origin:i,enabled:a,nested:c,extensions:u});continue}if(l.isDirectory()){vt(e,{walkRoot:n,currentDir:ge(r,l.name),depth:o+1,kind:s,origin:i,enabled:a,nested:c,extensions:u});continue}if(!l.isFile()||!u)continue;let f=l.name.toLowerCase();if(!u.some(p=>f.endsWith(p)))continue;let g=ge(r,l.name);Le(e,{absolutePath:g,kind:s,origin:i,enabled:a,name:ki(n,g,!0)})}}function hr(e){for(let t of e)if(Tt(t))try{if(hi(t).size>0)return t}catch{continue}return e.find(t=>Tt(t))}function Ii(e){if(e.prompt||e.type==="prompt")return"prompt";let t=e.command??e.bash??e.powershell??"";return/\bnpx\b/i.test(t)?"npx":/\.(sh|bash|zsh|js|mjs|cjs|ts|py)(\s|$|"|')/i.test(t)||/^(\.\/|~\/|\/|[A-Za-z]:[\\/])/.test(t.trim())?"script":"inline"}function Ri(e){return Array.isArray(e.hooks)&&e.hooks.length>0?e.hooks:[{type:e.type,command:e.command,bash:e.bash,powershell:e.powershell,prompt:e.prompt}]}function Ci(e,t,n,r){let o=e.homeRel(t);for(let[s,i]of Object.entries(n))if(!(!Array.isArray(i)||e.truncated))for(let a of i){if(!a||typeof a!="object"||e.truncated)continue;let c=a;for(let u of Ri(c)){if(e.truncated)return;let l=u.command??u.bash??u.prompt??u.powershell??c.powershell??"",f=Ii({type:u.type??c.type,command:u.command??c.command,bash:u.bash??c.bash,powershell:u.powershell??c.powershell,prompt:u.prompt??c.prompt}),g=typeof c.matcher=="string"?c.matcher:"",p=I(l),_=g?`${s}:${g}:${f}:${p}`:`${s}:${f}:${p}`,R=`${s}|${g}|${f}|${l}`;e.push({kind:"HOOK",name:_,path:o,content_hash:I(R),origin:r,enabled:!0,trigger:"EVENT",attributes:{event:s,...g?{matcher:g}:{},action_kind:f,action_hash:p}})}}}function he(e,t,n){let r=e.readJson(t,{});!r?.hooks||typeof r.hooks!="object"||Ci(e,t,r.hooks,n)}var _r={claude:{skillRoots:[".claude/skills"],dirs:[{dir:".claude/agents",kind:"SUBAGENT",extensions:[".md"]},{dir:".claude/commands",kind:"COMMAND",extensions:[".md"]}],memory:[".claude/CLAUDE.md"],hooks:[".claude/settings.json"],mcpJson:[".claude.json"],plugins:"claude"},cursor:{skillRoots:[".cursor/skills",".cursor/skills-cursor"],dirs:[{dir:".cursor/agents",kind:"SUBAGENT",extensions:[".md"]},{dir:".cursor/commands",kind:"COMMAND",extensions:[".md"]},{dir:".cursor/rules",kind:"RULE",extensions:[".mdc",".md"]}],memory:[".cursor/AGENTS.md"],hooks:[".cursor/hooks.json"],mcpJson:[".cursor/mcp.json"],plugins:"cursor"},codex:{skillRoots:[".agents/skills",".codex/skills"],dirs:[{dir:".codex/agents",kind:"SUBAGENT",extensions:[".toml",".md"]},{dir:".codex/prompts",kind:"COMMAND",extensions:[".md"]}],memory:[".codex/AGENTS.override.md",".codex/AGENTS.md"],hooks:[".codex/hooks.json"],mcpToml:[".codex/config.toml"]}};import{existsSync as xi,readFileSync as Ai}from"node:fs";function Ti(e){if(!e||typeof e!="object"||Array.isArray(e))return"unknown";let t=e;return typeof t.type=="string"&&t.type.length>0?t.type:typeof t.url=="string"?"http":typeof t.command=="string"?"stdio":"unknown"}function Sr(e,t,n){let o=e.readJson(t,{})?.mcpServers;if(!o||typeof o!="object")return;let s=e.homeRel(t);for(let[i,a]of Object.entries(o)){if(e.truncated)return;let c=Ti(a);e.push({kind:"MCP_SERVER",name:i,path:s,content_hash:I(`${i}|${c}`),origin:n,enabled:!0,attributes:{transport:c}})}}function Er(e,t,n){if(!xi(t))return;let r;try{r=Ai(t,"utf8")}catch{return}let o=e.homeRel(t),s=/^\[mcp_servers(?:\.(\w+)|\."([^"]+)"|\.'([^']+)')\]\s*$/gm,i;for(;(i=s.exec(r))!==null;){if(e.truncated)return;let a=i[1]??i[2]??i[3];if(!a)continue;let c=r.slice(i.index+i[0].length),u=c.search(/^\[/m),l=u===-1?c:c.slice(0,u),f="unknown";/^\s*url\s*=/m.test(l)?f="http":/^\s*command\s*=/m.test(l)&&(f="stdio"),e.push({kind:"MCP_SERVER",name:a,path:o,content_hash:I(`${a}|${f}`),origin:n,enabled:!0,attributes:{transport:f}})}}import{existsSync as Oi,readdirSync as vi}from"node:fs";import{join as A}from"node:path";var yr=50;function bt(e,t,n,r){if(!Oi(t))return{componentCount:0,expandTruncated:!1};let o=e.components.length,{expanded:s}=e.withPluginExpandCap(yr,()=>{Q(e,{dir:A(t,"skills"),kind:"SKILL",origin:n,enabled:r,nested:"SKILL.md"}),Q(e,{dir:A(t,"commands"),kind:"COMMAND",origin:n,enabled:r,extensions:[".md"]}),Q(e,{dir:A(t,"agents"),kind:"SUBAGENT",origin:n,enabled:r,extensions:[".md"]})});he(e,A(t,"hooks","hooks.json"),n),he(e,A(t,"hooks.json"),n);let i=e.components.length-o,a=s>=yr;return{componentCount:i,expandTruncated:a}}function wt(e,t){e.push({kind:"PLUGIN",name:t.pluginKey,path:t.rowPath,content_hash:t.contentHash,origin:"user",enabled:t.enabled,attributes:{...t.marketplace?{marketplace:t.marketplace}:{},...t.version?{version:t.version}:{},scope:t.scope,component_count:t.componentCount,...t.expandTruncated?{expand_truncated:!0}:{}}})}function kr(e){let t=A(e.home,".claude/plugins/installed_plugins.json"),n=e.readJson(t,{});if(!n)return;let r=n.plugins??{},s=e.readJson(A(e.home,".claude/settings.json"),{})?.enabledPlugins??{},i=e.homeRel(t);for(let[a,c]of Object.entries(r)){if(e.truncated)return;let u=Array.isArray(c)?c:[c],l=u[0]??{},f=s[a]===!0,g=a.includes("@")?a.split("@").slice(1).join("@"):"",p=typeof l.version=="string"?l.version:"",_=typeof l.scope=="string"?l.scope:"user",R=`plugin:${a}`,b=0,x=!1;for(let w of u)if(typeof w.installPath=="string"&&w.installPath.length>0){let W=bt(e,w.installPath,R,f);b+=W.componentCount,x=x||W.expandTruncated}wt(e,{pluginKey:a,rowPath:i,enabled:f,scope:_,version:p||void 0,marketplace:g||void 0,componentCount:b,expandTruncated:x,contentHash:I(`${a}|${p}|${_}|${f}|${b}`)})}}function bi(e){let t=e,n="";try{let r=vi(e,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);if(r.length===1&&r[0])t=A(e,r[0]),n=r[0];else if(r.length>1){let o=[...r].sort(),s=o[o.length-1];s&&(t=A(e,s),n=s)}}catch{}return{installPath:t,version:n}}function Ir(e){let t=[{base:A(e.home,".cursor/plugins/local"),scope:"local"},{base:A(e.home,".cursor/plugins/cache"),scope:"cache"}];for(let{base:n,scope:r}of t)if(!e.truncated)for(let o of e.readEntries(n)){if(!o.isDirectory()||e.truncated)continue;if(r==="local"){let i=o.name,a=A(n,o.name),c=`plugin:${i}`,{componentCount:u,expandTruncated:l}=bt(e,a,c,!0);wt(e,{pluginKey:i,rowPath:e.homeRel(a),enabled:!0,scope:"local",componentCount:u,expandTruncated:l,contentHash:I(`${i}|local|${u}`)});continue}let s=o.name;for(let i of e.readEntries(A(n,s))){if(!i.isDirectory()||e.truncated)continue;let a=A(n,s,i.name),{installPath:c,version:u}=bi(a),l=`${i.name}@${s}`,f=`plugin:${l}`,{componentCount:g,expandTruncated:p}=bt(e,c,f,!0);wt(e,{pluginKey:l,rowPath:e.homeRel(c),enabled:!0,scope:"cache",version:u||void 0,marketplace:s,componentCount:g,expandTruncated:p,contentHash:I(`${l}|${u}|${g}`)})}}}function Ut(e,t){let n=_r[e],r=new Me(t),o="user";if(!n)return{components:[],truncated:!1};for(let i of n.skillRoots)Q(r,{dir:re(t,i),kind:"SKILL",origin:o,enabled:!0,nested:"SKILL.md"});for(let i of n.dirs)Q(r,{dir:re(t,i.dir),kind:i.kind,origin:o,enabled:!0,extensions:i.extensions});let s=hr(n.memory.map(i=>re(t,i)));s&&Le(r,{absolutePath:s,kind:"MEMORY",origin:o,enabled:!0,name:wi(s)});for(let i of n.hooks)he(r,re(t,i),o);for(let i of n.mcpJson??[])Sr(r,re(t,i),o);for(let i of n.mcpToml??[])Er(r,re(t,i),o);return n.plugins==="claude"?kr(r):n.plugins==="cursor"&&Ir(r),{components:r.components,truncated:r.truncated}}function Pt(e,t,n={}){let r=n.truncated===!0,o=Ct(e),s=new Set(e.map(l=>$(l.path,l.name)));if(n.forceFull===!0||t===void 0)return{hash:o,count:e.length,truncated:r,full:!0,upserts:e,removed:[],unchanged:!1};let a=[],c=t;for(let l of e){let f=$(l.path,l.name);c[f]!==l.content_hash&&a.push(l)}let u=[];if(!r){for(let l of Object.keys(c))if(!s.has(l)){let f=lr(l);f&&u.push(f)}}return{hash:o,count:e.length,truncated:r,full:!1,upserts:a,removed:u,unchanged:a.length===0&&u.length===0}}var Cr=3e5,Ui=new Set(["HOOK","MCP_SERVER","PLUGIN"]);function Nt(e,t,n){let r=new Set(t.map(s=>$(s.path,s.name))),o=[];for(let s of e)s.text!==void 0&&(n.has(s.content_hash)||r.has($(s.path,s.name))||o.push(s));return o}function Mt(e,t,n){let r=new Set(e);for(let s of t)r.add(s);let o=new Set(n.map(s=>s.content_hash));return[...r].filter(s=>o.has(s))}function Rr(e){return Buffer.byteLength(JSON.stringify(e),"utf8")}function xr(e){if(e.text===void 0)return e;let{text:t,...n}=e;return n}function Lt(e,t=Cr){let n=[],r=[];for(let l of e)Ui.has(l.kind)?n.push(l):r.push(l);r.sort((l,f)=>(l.text?.length??0)-(f.text?.length??0));let o=[...n,...r],s=[],i=2,a=0,c=0,u=[];for(let l of o){let f=s.length>0?1:0,g=Rr(l)+f;if(i+g<=t){s.push(l),i+=g,l.text!==void 0&&u.push(l.content_hash);continue}if(l.text!==void 0){let p=xr(l),_=Rr(p)+f;if(i+_<=t){s.push(p),i+=_,a+=1;continue}}c+=1}return{components:s,textDeferredCount:a,droppedCount:c,textHashesSent:u}}function Ht(e,t){return t.size===0?e:e.map(n=>n.text===void 0||!t.has(n.content_hash)?n:xr(n))}var Mi={claude:{skills:".claude/skills",subagents:".claude/agents",commands:".claude/commands",memory:".claude/CLAUDE.md",settings:".claude/settings.json"},cursor:{skills:[".cursor/skills",".cursor/skills-cursor"],subagents:".cursor/agents",commands:".cursor/commands",rules:".cursor/rules",mcp:".cursor/mcp.json"},codex:{skills:[".agents/skills",".codex/skills"],subagents:".codex/agents",commands:".codex/prompts",memory:".codex/AGENTS.md",settings:".codex/config.toml"}},Li=200,Ar=200,Hi=["allow","deny","ask"],Di=/(?<=^|[\s(,=:])(?:~|[A-Za-z]:)?[\\/][^\s,)]+/g,Dt="<path>",Fi=new RegExp(`${Dt}(?:\\s+[A-Za-z.][^\\s,)]*[\\\\/][^\\s,)]*)+`,"g");function ji(e){let t=e.replace(Di,Dt).replace(Fi,Dt);return t.length>Ar?`${t.slice(0,Ar)}...`:t}function Tr(e){let t=ne(e,{}),n=[];for(let r of Hi)for(let o of t.permissions?.[r]??[])typeof o=="string"&&o.length>0&&n.push({key:ji(o),mode:r});return{model:t.model??"",permissionKeys:n}}var Bi=10,$i=840*60*1e3,Gi="self-config-cache.json";function Ft(){return E("EV_AI_HOOK_USER_SPEC")?.toLowerCase()==="off"}function Ki(e,t=Date.now()){return e===void 0||!Number.isFinite(e)?!0:t-e>=$i}var Ji={claude:["claude"],cursor:["agent","cursor-agent"],codex:["codex"]};async function Vi(e,t=C){let n=Ji[e];if(!n||n.length===0)return null;let r=async o=>{let s=n[o];if(s===void 0)return null;let a=((await t(s,["--version"],2e3)).split(`
17
+ `)[0]??"").trim();return a||r(o+1)};return r(0)}function Wi(e=Or()){return P(e,".ev-ai","agent-hook",Gi)}function zi(e){let n=[...e].sort((r,o)=>r.name.localeCompare(o.name)).map(r=>`${r.name}:${r.size}`).join(`
18
+ `);return I(n)}function He(e,t,n=!1){let r=zi(e),o=e.length;return t===r?n?{hash:r,count:o,truncated:n}:{hash:r,count:o}:n?{hash:r,count:o,entries:e,truncated:n}:{hash:r,count:o,entries:e}}function Yi(e){return Pi(e)?v(Ni(e,"utf8"),{}):{}}function Xi(e,t){try{z(e,`${JSON.stringify(t)}
19
+ `)}catch(n){let r=n instanceof Error?n.message:String(n);d(`WARN: self-config cache write failed open: ${r}`)}}function qi(e,t,n,r){let o={...e,send_count:n};for(let s of Object.keys(t)){let i=t[s];i.entries!==void 0&&(o[s]=i.hash)}return r&&(o.user_spec_collected_at_ms=r.collectedAtMs,r.included&&(o.user_spec=r.hash,o.user_spec_components=r.componentHashes),o.user_spec_text_hashes=r.textHashes),o}async function vr(e,t=process.cwd(),n=Or(),r={}){let o=e==="claude",s=r.gitRoot??t,i=await Vi(e),a="",c=[];if(o){let U=Tr(P(n,".claude/settings.json")),L=Tr(P(t,".claude/settings.local.json"));a=L.model||U.model,c=[...U.permissionKeys,...L.permissionKeys].slice(0,Li)}let u=Mi[e]??{},l={present:!1,size:0},f=U=>{let L=Array.isArray(U)?U:U?[U]:[],y=[],K=!1;for(let Je of L){let O=de(P(n,Je));if(y=y.concat(O.entries),K=K||O.truncated,y.length>=X){y=y.slice(0,X),K=!0;break}}return{entries:y,truncated:K}},g=Wi(n),p=Yi(g),_=p[e]??{},R=(_.send_count??0)+1,b=R>0&&R%Bi===0,x=U=>b?void 0:_[U],w=f(u.skills),W=u.subagents?de(P(n,u.subagents)):{entries:[],truncated:!1},Ke=u.commands?de(P(n,u.commands)):{entries:[],truncated:!1},Vt=u.rules?de(P(n,u.rules)):{entries:[],truncated:!1},ie={skills:He(w.entries,x("skills"),w.truncated),subagents:He(W.entries,x("subagents"),W.truncated),commands:He(Ke.entries,x("commands"),Ke.truncated),rules:He(Vt.entries,x("rules"),Vt.truncated)},T={runner_platform:e,config_scope:"user",cli_version:i,claude_version:o?i:null,model:o&&a||null,permission_keys:c,user_scope:{skills:ie.skills,subagents:ie.subagents,commands:ie.commands,rules:ie.rules,memory:u.memory?fe(P(n,u.memory)):l,settings:u.settings?fe(P(n,u.settings)):l,mcp:u.mcp?fe(P(n,u.mcp)):l},local_settings:o?fe(P(t,".claude/settings.local.json")):l},Wt=null,zt=()=>{},Yt=r.nowMs??Date.now();if(!Ft()&&Ki(_.user_spec_collected_at_ms,Yt)){let U=_.user_spec_collected_at_ms!==void 0,L=Ut(e,n),y=Pt(L.components,_.user_spec_components,{forceFull:!_.user_spec_components,truncated:L.truncated}),K=new Set(_.user_spec_text_hashes??[]),Je=Nt(L.components,y.upserts,K),O=Lt(Ht([...y.upserts,...Je],K));T.user_spec_hash=y.hash,T.user_spec_count=y.count,T.user_spec_truncated=y.truncated||O.droppedCount>0,(O.components.length>0||y.removed.length>0||y.full)&&(y.full&&(T.user_spec_full=!0),O.components.length>0&&(T.user_spec=O.components),y.removed.length>0&&!T.user_spec_truncated&&(T.user_spec_removed=y.removed),O.textDeferredCount>0&&(T.user_spec_text_deferred=O.textDeferredCount));let Ve=y.full?{}:{..._.user_spec_components??{}};if(!T.user_spec_truncated)for(let te of y.removed)delete Ve[$(te.path,te.name)];for(let te of O.components)Ve[$(te.path,te.name)]=te.content_hash;Wt={hash:y.hash,componentHashes:Ve,textHashes:Mt(K,O.textHashesSent,L.components),included:O.components.length>0||y.removed.length>0&&!T.user_spec_truncated||y.full,collectedAtMs:Yt};let We=await Ne({gitRoot:s,installationStorePath:r.installationStorePath,forceResend:U});We.operator&&(T.operator=We.operator),zt=We.commit}let so=qi(_,ie,R,Wt);return{config:T,commit:()=>{p[e]=so,Xi(g,p),zt()}}}function oe(e,t,n){let r={installation_id:n.installationId};return n.platformAgentId&&(r.platform_agent_id=n.platformAgentId),n.sessionId&&(r.session_id=n.sessionId),n.turnId&&(r.turn_id=n.turnId),{schema_version:2,event:e,timestamp:Ae(),session_id:n.sessionId||null,turn_id:n.turnId||null,installation_id:n.installationId,platform:n.runnerPlatform,platform_agent_id:n.platformAgentId||null,runner_event:n.runnerEvent||null,agent_hook_version:H,host_arch:process.arch,node_version:process.version,correlation:r,payload:t}}import{existsSync as Kr}from"node:fs";import{spawn as Jr}from"node:child_process";import{basename as Ia}from"node:path";import{fileURLToPath as Ra}from"node:url";var br=/(?:^|\/|[\s"'=(])(?:\.cursor\/|\.claude\/|\.agents\/)skills(?:-cursor)?\/([^/]+)\/SKILL\.md/i,wr=/(?:^|\/|[\s"'=(])\.codex\/commands\/([^/]+)\.md\b/i,Zi=/(?:^|\s)\/([a-z][a-z0-9-]{1,63})\b/gi,Qi=new Set(["applications","app","bin","boot","data","dev","etc","home","lib","media","mnt","node_modules","opt","pkg","private","proc","projects","repos","run","sbin","src","srv","sys","tmp","usr","users","var","volumes","workspace","workspaces"]),ea=new Set(["read","read_file","view"]),ta=new Set(["bash","shell","zsh"]);function na(e){let t=e.replace(/\\/g,"/");return br.exec(t)?.[1]??null}function ra(e){let t=e.replace(/\\/g,"/"),r=wr.exec(t)?.[1];return r?r.toLowerCase():null}function oa(e){return na(e)??ra(e)}function sa(e){for(let t of["path","file_path","target_file"]){let n=e[t];if(typeof n=="string"&&n.length>0)return n}return null}function Ur(e){if(typeof e=="string")try{let t=JSON.parse(e);return Ur(t)}catch{return null}return!e||typeof e!="object"?null:sa(e)}function ia(e){if(!e||typeof e!="object")return null;let t=e.command;return typeof t=="string"&&t.length>0?t:null}function aa(e){let t=e.replace(/\\/g,"/"),n=br.exec(t);if(n?.[1])return n[1];let o=wr.exec(t)?.[1];return o?o.toLowerCase():null}function ca(e){return typeof e.tool_name=="string"?e.tool_name:typeof e.tool=="string"?e.tool:""}function Pr(e){let t=ca(e).toLowerCase();if(ea.has(t)){let n=Ur(e.tool_input);return n?oa(n):null}if(ta.has(t)){let n=ia(e.tool_input);return n?aa(n):null}return null}function la(e){let t=new Set,n=[];for(let r of e.matchAll(Zi)){let o=r[1]?.toLowerCase();!o||t.has(o)||Qi.has(o)||(t.add(o),n.push(o))}return n}function ua(e){return ue(e.prompt)}function Nr(e){let t=m(e,"command_name");if(t){let r=m(e,"expansion_type");if(r&&r!=="slash_command")return[];let o=t.replace(/^\//,"").toLowerCase();return o?[o]:[]}let n=ua(e);return n?la(n):[]}function jt(e){return e!==void 0&&on.includes(e)}function De(e,t){let n=e[t+1];return n&&!n.startsWith("--")?{value:n,next:t+1}:{next:t}}function Fe(e){let t,n,r,o,s;for(let i=0;i<e.length;i++){let a=e[i];if(a!==void 0){if(a==="--runner"){let c=De(e,i);t=c.value,i=c.next;continue}if(a.startsWith("--runner=")){t=a.slice(9);continue}if(a==="--url"){let c=De(e,i);c.value&&(r=c.value),i=c.next;continue}if(a.startsWith("--url=")){r=a.slice(6);continue}if(a==="--token"){let c=De(e,i);c.value&&(o=c.value),i=c.next;continue}if(a.startsWith("--token=")){o=a.slice(8);continue}if(a==="--base-url"){let c=De(e,i);c.value&&(s=c.value),i=c.next;continue}if(a.startsWith("--base-url=")){s=a.slice(11);continue}!a.startsWith("-")&&n===void 0&&(n=a)}}return{runner:jt(t)?t:void 0,event:n,collectorUrl:r,orgToken:o,baseUrl:s}}function Bt(e){let t=e.collectorUrl?.trim(),n;if(t)n=t;else{let o=e.orgToken?.trim();o&&(n=Ie(o,e.baseUrl?.trim()??void 0))}if(!n)return;let r=ae(n);if(r){d(`WARN: ignoring --url/--token collector override: ${r}`);return}return ce(n)}function Mr(e,t){if(m(e,"conversation_id"))return!0;if(t==="")return!1;let n=t[0];return n?.toLowerCase()===n}function da(){return!!(E("CURSOR_VERSION")??E("CURSOR_PROJECT_DIR"))}function $t(e,t,n){return e!=="claude"&&e!=="codex"?!1:Mr(t,n)?!0:da()}function Gt(e,t,n,r){if(Mr(e,t))return"cursor";if(jt(r))return r;let o=m(e,"conversation_id"),s=m(e,"turn_id"),i=m(e,"session_id"),a=t.toLowerCase(),c="unknown";return o||t===a&&t!==""?c="cursor":s?c="codex":(i||a==="sessionstart"||a==="sessionend"||a==="stop"||a==="stopfailure"||a==="pretooluse"||a==="posttooluse"||a==="posttoolusefailure"||a==="permissiondenied"||a==="subagentstart"||a==="subagentstop"||a==="userpromptexpansion")&&(c="claude"),jt(n)&&(c=n),c}function je(e,t){let n=e.toLowerCase();return n==="sessionend"||n==="stopfailure"||n==="subagentstop"?!0:n==="stop"&&t==="codex"}function fa(e){switch(e){case"sessionstart":return"session_start";case"stop":case"sessionend":case"stopfailure":return"session_end";case"pretooluse":case"posttooluse":case"posttoolusefailure":case"permissiondenied":case"beforemcpexecution":case"beforeshellexecution":case"afterfileedit":case"subagentstart":case"subagentstop":return"tool_invoked";case"beforesubmitprompt":case"userpromptexpansion":case"userpromptsubmit":return"skill_invoked";default:return""}}function Lr(e){let t=e.toLowerCase();return t==="posttooluse"?!0:t==="posttoolusefailure"||t==="permissiondenied"?!1:null}function Hr(e,t,n){let r=m(e,"session_id")||m(e,"conversation_id"),o=m(e,"prompt.id")||m(e,"prompt_id")||m(e,"generation_id")||m(e,"turn_id"),s=m(e,"hook_event_name")||m(e,"event"),i=m(e,"source"),a=Gt(e,s,t,n);return{sessionId:r,turnId:o,runnerEvent:s,hookSource:i,runnerPlatform:a}}var pa=["session_start","session_end","tool_invoked","skill_invoked"];function ma(e){return pa.includes(e)}function Dr(e,t){return e&&ma(e)?e:fa(t.toLowerCase())}function Fr(e){let t=m(e,"tool_name")||m(e,"tool")||null,n=e.tool_input,o=(n&&typeof n=="object"?ue(n.skill)||ue(n.skill_name):"")||m(e,"skill_name")||null;return o??=Pr(e),{toolName:t,skillName:o}}var ga=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;function jr(e){for(let t of["subagent_type","agent_type"]){let n=m(e,t);if(n&&ga.test(n))return n}return null}function Br(e){let t=Y(e,"duration_ms");if(typeof t=="number")return t;let n=Y(e,"duration");return typeof n=="number"?n:null}var ha="error",_a="interrupted",Sa="permission_denied",Ea=/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/;function Kt(e){return Ea.test(e)?e:null}function ya(e){for(let t of["failure_type","error_type"]){let n=Kt(m(e,t));if(n)return n}return null}function $r(e,t){return Y(e,"is_interrupt")===!0?_a:t.toLowerCase()==="permissiondenied"?Sa:ya(e)??ha}function ka(e,t){let n=null;for(let r of t)r&&(e===r||e.startsWith(`${r}_`)||e.startsWith(`${r}-`))&&(n===null||r.length>n.length)&&(n=r);return n}function Gr(e,t=[]){if(!e)return{mcpServer:null,mcpTool:null};let n=/^mcp__(.+?)__(.+)$/i.exec(e);if(n?.[1]&&n[2])return{mcpServer:n[1],mcpTool:n[2]};if(/^MCP:/i.test(e)){let r=e.slice(4);if(!r)return{mcpServer:null,mcpTool:null};let o=r.indexOf(":");return o>0?{mcpServer:r.slice(0,o),mcpTool:r.slice(o+1)||null}:{mcpServer:ka(r,t),mcpTool:r}}return{mcpServer:null,mcpTool:null}}var _e="__post",Be="__work";function Ca(e,t){let n=e.payload,r=n&&typeof n=="object"&&!Array.isArray(n)?Object.keys(n):[],o=e.correlation&&typeof e.correlation=="object"?Object.keys(e.correlation):[];return JSON.stringify({event:e.event,schema_version:e.schema_version,agent_hook_version:e.agent_hook_version,host_arch:e.host_arch,node_version:e.node_version,build_ms:e.build_ms,body_bytes:t,correlation_keys:o,payload_keys:r})}function Vr(e){switch(e){case"session_start":return Zt;case"session_end":return Qt;case"tool_invoked":case"skill_invoked":return Xe;default:return Xe}}function xa(e,t,n){return`${JSON.stringify({url:e,timeoutMs:t})}
20
+ ${n}`}function Wr(e,t=[],n=process.execPath,r=import.meta.url,o=Kr){if(Ia(n)===J)return{command:n,args:[e,...t]};let s=Ra(r);return o(s)?{command:n,args:[s,e,...t]}:{command:n,args:[e,...t]}}function Aa(e=process.execPath,t=import.meta.url,n=Kr){return Wr(_e,[],e,t,n)}function Ta(e){let t=e.indexOf(`
21
+ `);if(t<0)return null;let n;try{n=JSON.parse(e.slice(0,t))}catch{return null}return{meta:n,body:e.slice(t+1)}}async function $e(e,t=fetch){let n=await e(),r=Ta(n);if(!r)return;let{meta:o,body:s}=r,i={"Content-Type":"application/json"};try{await t(o.url,{method:"POST",headers:i,body:s,signal:AbortSignal.timeout(Number(o.timeoutMs))})}catch{}}async function Oa(e,t,n){let r=Vr(e);d(`POST event=${e} url=${Ze(n)} size=${t.length} platform=${process.platform}`);let o={"Content-Type":"application/json"},s=Date.now();try{let i=await fetch(n,{method:"POST",headers:o,body:t,signal:AbortSignal.timeout(r)}),a=Date.now()-s;if(i.ok)return d(`POST outcome=ok elapsed_ms=${a} http=${i.status}`),!0;let c=(await i.text()).slice(0,200).replace(/[\n\r]/g,"");return d(`POST outcome=fail elapsed_ms=${a} http=${i.status} body=${c}`),!1}catch(i){let a=Date.now()-s,c=i instanceof Error?i.message:String(i);return d(`POST outcome=fail elapsed_ms=${a} http=000 body=${c}`),!1}}async function zr(e,t,n,r,o){try{let s=r(e,t,{detached:!0,stdio:["pipe","ignore","ignore"],windowsHide:!0});s.on("error",()=>{}),s.stdin.on("error",()=>{});let i=!1;return await new Promise(a=>{let c=setTimeout(()=>{if(!i){d(`WARN: ${o} stdin handoff timed out \u2014 continuing fail-open`);try{s.stdin.destroy()}catch{}}a()},en),u=()=>{i=!0,clearTimeout(c),a()};s.stdin.end(n,()=>u()),s.stdin.once("error",()=>u())}),s.unref(),s}catch(s){let i=s instanceof Error?s.message:String(s);return d(`WARN: ${o} spawn failed open: ${i}`),null}}async function va(e,t,n,r=Jr,o=Aa){let s=Vr(e),i=xa(n,s,t),{command:a,args:c}=o();return zr(a,c,i,r,"detached post")}async function Yr(e,t,n=Jr,r=Wr){let{command:o,args:s}=r(Be,t);return zr(o,s,e,n,"detached work")}async function se(e,t,n,r,o,s){if(!o)return d("WARN: collector URL missing \u2014 pass --url on the hook command or set collector_url in manifest"),!1;if(!xe(o))return d(`WARN: collector URL blocked (https required): ${Ze(o)}`),!1;let i=r(e,t,n);s!==void 0&&(i.build_ms=Math.max(0,Date.now()-s));let a=`${JSON.stringify(i)}
22
+ `,c=E("EV_AI_HOOK_DEBUG");c==="full"?d(`DEBUG envelope=${JSON.stringify(i)}`):c==="1"&&d(`DEBUG summary=${Ca(i,Buffer.byteLength(a,"utf8"))}`);let u=process.argv.includes(Be),l=E("EV_AI_HOOK_SYNC")==="1";return je(n.runnerEvent,n.runnerPlatform)||u||l?Oa(e,a,o):(await va(e,a,o),!1)}import{relative as ba,resolve as Jt,sep as Xr}from"node:path";var wa=["session_id","conversation_id","turn_id","generation_id","prompt.id","prompt_id","hook_event_name","event","source","status","stop_reason","reason","tool_name","tool","tool_use_id","skill_name","command_name","expansion_type","command_source","permission_mode","model","model_id","agent_id","agent_type","subagent_id","subagent_type","subagent_model","is_parallel_worker","effort","effort.level","duration_ms","duration","failure_type","is_interrupt"];function Ua(e){return e.capture_hook_input==="full"?!0:e.capture_hook_input==="allowlist"?!1:E("EV_AI_HOOK_CAPTURE_FULL_INPUT")==="1"}function Pa(e){let t={};for(let n of wa){let r=Y(e,n);r!==void 0&&(t[n]=r)}return t}function Na(e,t){if(typeof e!="string"||e.length===0||!t)return null;let n=Jt(e),r=Jt(t),o=ba(r,n);return!o||o==="."?".":o.startsWith(`..${Xr}`)||o===".."||Jt(r,o)!==n?null:o.split(Xr).join("/")}function qr(e,t){let n=JSON.stringify(e),r=Buffer.byteLength(n,"utf8");if(r<=t)return e;let o=Object.entries(e).filter(([i,a])=>!i.startsWith("_")&&(typeof a=="string"||typeof a=="number"||typeof a=="boolean")).sort((i,a)=>Buffer.byteLength(JSON.stringify(i[1]),"utf8")-Buffer.byteLength(JSON.stringify(a[1]),"utf8")),s={_truncated:!0,_original_bytes:r};for(let[i,a]of o){let c={...s,[i]:a};if(Buffer.byteLength(JSON.stringify(c),"utf8")>t)break;s[i]=a}return s}function Se(e,t,n={}){let r=n.gitRoot!==void 0?Na(e.cwd,n.gitRoot):null;if(Ua(t)){let s={...e};return delete s.cwd,delete s.transcript_path,r!==null&&(s.cwd_relative=r),qr(s,nn)}let o=Pa(e);return r!==null&&(o.cwd_relative=r),qr(o,tn)}import{createReadStream as Ma}from"node:fs";import{stat as La}from"node:fs/promises";import{basename as Ha,resolve as Da}from"node:path";import{createInterface as Fa}from"node:readline";var ja=1024*1024;function Ba(e){let t=e.replace(/\\/g,"/");return t.includes("/.claude/projects/")&&Ha(t).endsWith(".jsonl")}async function Zr(e){if(!e||!Ba(e))return null;try{let t=Da(e),n=await La(t);if(!n.isFile())return null;let r=Math.max(0,n.size-ja),o=[],s=Fa({input:Ma(t,{encoding:"utf8",start:r}),crlfDelay:1/0});for await(let i of s)i.length!==0&&o.push(i);r>0&&o.length>0&&o.shift();for(let i=o.length-1;i>=0;i--){let a=o[i];if(a)try{let c=JSON.parse(a);if(c.type!=="assistant")continue;let u=c.message;if(!u||typeof u!="object")continue;let l=u.model;if(typeof l=="string"&&l.length>0)return l}catch{continue}}return null}catch{return null}}function ye(e){return{sessionId:e.sessionId,turnId:e.turnId,installationId:e.manifest.installationId,runnerPlatform:e.runnerPlatform,platformAgentId:e.platformAgentId,runnerEvent:e.runnerEvent}}function $a(...e){for(let t of e)if(t)return t;return null}function N(e,t,n){if(e.status==="fulfilled")return e.value;let r=e.reason instanceof Error?e.reason.message:String(e.reason);return d(`WARN: ${n} failed open: ${r}`),t}function Ga(e){let t={present:!1,size:0},n={hash:"",count:0};return{config:{runner_platform:e,config_scope:"user",cli_version:null,claude_version:null,model:null,permission_keys:[],user_scope:{skills:n,subagents:n,commands:n,rules:n,memory:t,settings:t,mcp:t},local_settings:t},commit:()=>{}}}function Ka(e,t){return{runner_platform:e,config_scope:"user",...t?{operator:t}:{}}}var ee=new Set,Ee=null;async function Qr(e){if(Ft())return;let t=e.manifest.installationId,n=e.manifest.installationStorePath;if(ee.has(t))return;if(!At(n)){ee.add(t);return}let r=gt();if(dr(r)){if(Ee){await Ee;return}Ee=(async()=>{if(ee.has(t)||!At(n)){ee.add(t);return}if(!vn(n)){ee.add(t);return}let o=!1;try{let s=Date.now(),{gitRoot:i}=e.manifest,a=String(e.runnerPlatform),[c,u,l,f,g]=await Promise.allSettled([me(i),ht(),Et(r),_t(),Ne({gitRoot:i,installationStorePath:n,forceResend:!1})]),p=N(c,null,"gitSnapshot"),_=N(u,"","detectVirt"),R=N(l,null,"probeCloud"),b=N(f,{},"hostEnv"),x=N(g,{commit:()=>{}},"resolveOperatorForSend");await ke(e,i,p);let w={identity:{host:St(),context:r,virt:_||null,cloud:R,git:p},host_env:b,env_vars:Rt(),self_config:Ka(a,x.operator),run_meta:{trigger:"cloud_identity_bootstrap"}};o=!!await se("session_start",w,ye(e),oe,e.manifest.collectorUrl,s),o&&(x.commit(),ee.add(t))}finally{bn(n)}})().finally(()=>{Ee=null}),await Ee}}async function ke(e,t,n){try{let r=n===void 0?await me(t):n;e.platformAgentId=await ar(e.manifest.manifest,e.platformAgentId,String(e.runnerPlatform),t,r,e.manifest.installationStorePath,e.manifest.repoKey)}catch(r){let o=r instanceof Error?r.message:String(r);d(`WARN: derivePlatformAgentId failed open: ${o}`)}}async function Ja(e){let t=Date.now(),{gitRoot:n}=e.manifest,r=gt(),o=String(e.runnerPlatform),[s,i,a,c,u,l]=await Promise.allSettled([me(n),ht(),Et(r),_t(),It(e.manifest.manifest,n,o),vr(o,n,void 0,{installationStorePath:e.manifest.installationStorePath,gitRoot:n})]),f=N(s,null,"gitSnapshot"),g=N(i,"","detectVirt"),p=N(a,null,"probeCloud"),_=N(c,{},"hostEnv"),R=N(u,[],"mcpDeclared"),b=N(l,Ga(o),"selfConfig"),x=b.config;await ke(e,n,f);let w=m(e.hookInput,"model");w&&(x.model=w);let W={identity:{host:St(),context:r,virt:g||null,cloud:p,git:f},host_env:_,env_vars:Rt(),mcp:{declared:R},self_config:x,run_meta:{trigger:e.hookSource||"startup"},hook_input:Se(e.hookInput,e.manifest.manifest,{gitRoot:n})};await se("session_start",W,ye(e),oe,e.manifest.collectorUrl,t)&&(b.commit(),ee.add(e.manifest.installationId))}async function Va(e){let t=Date.now(),{gitRoot:n}=e.manifest;await ke(e,n);let r=$a(m(e.hookInput,"status"),m(e.hookInput,"stop_reason"),m(e.hookInput,"reason"),Kt(m(e.hookInput,"error"))),o=e.runnerPlatform==="claude"?await Zr(m(e.hookInput,"transcript_path")):null,s=Se(e.hookInput,e.manifest.manifest,{gitRoot:n});o&&(s.model=o),await se("session_end",{status:r,...o?{model:o}:{},hook_input:s},ye(e),oe,e.manifest.collectorUrl,t)}async function Wa(e){let t=Date.now(),n=Nr(e.hookInput);if(n.length===0)return;await Qr(e);let{gitRoot:r}=e.manifest;await ke(e,r);let o=Se(e.hookInput,e.manifest.manifest,{gitRoot:r}),s=ye(e);await Promise.all(n.map(i=>se("tool_invoked",{tool_name:"Skill",skill_name:i,success:null,duration_ms:null,hook_input:o},s,oe,e.manifest.collectorUrl,t)))}async function za(e){let t=Date.now();await Qr(e);let{gitRoot:n}=e.manifest;await ke(e,n);let{toolName:r,skillName:o}=Fr(e.hookInput),s=Br(e.hookInput),i=Lr(e.runnerEvent),a=i===!1?$r(e.hookInput,e.runnerEvent):null,c=await It(e.manifest.manifest,e.manifest.gitRoot,String(e.runnerPlatform)).catch(()=>[]),{mcpServer:u,mcpTool:l}=Gr(r,c.map(g=>g.name)),f=jr(e.hookInput);await se("tool_invoked",{tool_name:r,skill_name:o,success:i,duration_ms:s,...a?{failure_reason:a}:{},...u?{mcp_server:u}:{},...l?{mcp_tool:l}:{},...f?{subagent_type:f}:{},hook_input:Se(e.hookInput,e.manifest.manifest,{gitRoot:n})},ye(e),oe,e.manifest.collectorUrl,t)}async function eo(e){switch(e.internalEvent){case"session_start":await Ja(e);return;case"session_end":await Va(e);return;case"skill_invoked":await Wa(e);return;case"tool_invoked":await za(e);return;default:return}}function to(e){return e!=="session_start"&&e!=="session_end"&&e!=="tool_invoked"&&e!=="skill_invoked"&&e!==""}async function no(e,t,n,r){let o=t??await et(qe),s=v(o,{}),i=await Mn();if(!i)return;r&&(i.collectorUrl=r);let a=Hr(s,i.manifest.platform,n),c=Dr(e,a.runnerEvent);if(!c){d(`WARN: unknown hook event '${a.runnerEvent}'; skipping telemetry`);return}let u={hookInput:s,sessionId:a.sessionId,turnId:a.turnId,runnerEvent:a.runnerEvent,runnerPlatform:a.runnerPlatform,hookSource:a.hookSource,internalEvent:c,manifest:i,platformAgentId:i.platformAgentId};if(to(c)){d(`WARN: unsupported internal event '${c}'`);return}await eo(u)}function Ya(e,t){if(E("EV_AI_HOOK_SYNC")==="1")return!0;let n=Fe(e),r=v(t,{}),o=n.event??(m(r,"hook_event_name")||m(r,"event")),s=Gt(r,o,void 0,n.runner);return je(o,s)}async function ro(e=process.argv.slice(2)){if(e[0]===_e){try{await $e(le)}catch{}return 0}if(e[0]===Be){try{let t=Fe(e.slice(1)),n=await le(),r=v(n,{}),o=t.event??(m(r,"hook_event_name")||m(r,"event"));if($t(t.runner,r,o))return 0;await no(t.event,n,t.runner,Bt(t))}catch(t){let n=t instanceof Error?t.message:String(t);d(`WARN: detached work failed open: ${n}`)}return 0}try{let t=await et(qe),n=Fe(e),r=Bt(n),o=v(t,{}),s=n.event??(m(o,"hook_event_name")||m(o,"event"));if($t(n.runner,o,s))return 0;Ya(e,t)?await no(n.event,t,n.runner,r):await Yr(t,e)}catch(t){let n=t instanceof Error?t.message:String(t);d(`WARN: hook failed open: ${n}`)}finally{gn()}return 0}function Ge(){d("Usage: ev-ai-agent-hook <configure|install|migrate-to-plugin|update|uninstall|--version>"),d(" configure [--url <\u2026/{orgToken}/hook>]"),d(" (manifest only \u2014 pair with marketplace plugins)"),d(" install --url <\u2026/{orgToken}/hook>"),d(" [--delivery npx|binary|local] [--force]"),d(" [--no-claude] [--no-cursor] [--no-codex]"),d(" (fallback: merge hooks into .claude / .cursor / .codex configs)"),d(" (writes collector_url to shared manifest; hook commands use --runner only)"),d(" migrate-to-plugin"),d(" (strip ev-ai file hooks; keep collector manifest)"),d(" update (refresh binary pins from a local build; leaves hook configs alone)"),d(" uninstall"),d("Hook mode: --runner <platform> [--url <\u2026/hook>|--token <orgToken>] [event]"),d(" (--url/--token optional overrides; else collector_url from manifest)")}function oo(e){return e.includes("--help")||e.includes("-h")}async function ec(e=process.argv.slice(2)){let[t,...n]=e;if(t===_e){try{await $e(le)}catch{}return 0}return t==="--version"||t==="-V"?(process.stdout.write(`${H}
23
+ `),0):t==="configure"?oo(n)?(Ge(),0):(await rr(Gn(n)),0):t==="install"?oo(n)?(Ge(),0):(await tr(Kn(n)),0):t==="migrate-to-plugin"?(await sr(),0):t==="update"?(await nr(),0):t==="uninstall"?(await ir(),0):t==="help"||t==="--help"||t==="-h"?(Ge(),0):t===void 0?(Ge(),1):ro(e)}function tc(e,t,n=Xa){if(!t)return!1;try{return e===Qa(qa(t)).href?!0:n(Za(e))===n(t)}catch{return!1}}tc(import.meta.url,process.argv[1])&&process.env.VITEST===void 0&&ec().then(e=>{process.exit(e)}).catch(e=>{let t=e instanceof Error?e.message:String(e);d(t),process.exit(1)});export{tc as isCliEntrypoint,ec as main};
package/dist/hook.mjs CHANGED
@@ -1,12 +1,16 @@
1
- var Ke="https://hooks.evalon.ai";function U(t,e=Ke){let n=e.replace(/\/+$/,""),r=t.trim();return`${n}/${r}/hook`}var It=".claude/evalon-runtime-report.json";var D="evalon-agent-hook";var ro=`current/${D}`,oo=`.evalon/agent-hook/${D}`,Rt=5e3,vt=5e3,Q=3e3;var tt=3e3,wt=1500,At=4*1024,Ct=32*1024,je=4*1024,et="1.0.6",so=`@evalon-ai/agent-hook@${et}`;var Tt=["claude","cursor","codex"];import{createHash as Ye,randomBytes as Xe}from"node:crypto";import{existsSync as Ze,mkdirSync as qe,readFileSync as Qe,writeFileSync as tn}from"node:fs";import{homedir as j}from"node:os";import{dirname as en,join as rt,resolve as nn}from"node:path";import{randomBytes as Be}from"node:crypto";import{existsSync as bt,mkdirSync as ze,readdirSync as We,renameSync as xt,statSync as Ot,unlinkSync as Nt,writeFileSync as Ve}from"node:fs";import{basename as Ge,dirname as Pt,join as Lt,relative as Je}from"node:path";function u(t){process.stderr.write(`[evalon-agent-hook] ${t}
2
- `)}function w(t,e){ze(Pt(t),{recursive:!0});let n=Lt(Pt(t),`.${Ge(t)}.${process.pid}.${Be(4).toString("hex")}.tmp`);try{Ve(n,e,"utf8");try{xt(n,t)}catch(r){let o=r instanceof Error&&"code"in r?r.code:void 0;if(o==="EEXIST"||o==="EPERM"||o==="EACCES"){Nt(t),xt(n,t);return}throw r}}catch(r){try{Nt(n)}catch{}throw r}}function Mt(){return new Date().toISOString().replace(/\.\d{3}Z$/,"Z")}function Ht(){process.stdout.write('{"continue":true}')}function p(t){let e=process.env[t];return e===void 0||e===""?void 0:e}async function Ft(){return new Promise(t=>{let e="";if(process.stdin.isTTY){t("");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{e+=n}),process.stdin.on("end",()=>{t(e)}),process.stdin.on("error",()=>{t(e)}),process.stdin.resume()})}async function nt(t){return new Promise(e=>{let n="",r=!1,o=a=>{r||(r=!0,clearTimeout(s),e(a||"{}"))},s=setTimeout(()=>{o(n)},t);if(process.stdin.isTTY){o("{}");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",a=>{n+=a}),process.stdin.on("end",()=>{o(n)}),process.stdin.on("error",()=>{o(n)}),process.stdin.resume()})}async function S(t,e,n=3e3,r={}){let{execFile:o}=await import("node:child_process"),{promisify:s}=await import("node:util"),a=s(o);try{let{stdout:i}=await a(t,e,{timeout:n,windowsHide:!0,maxBuffer:1048576,cwd:r.cwd});return{ok:!0,stdout:i.trim()}}catch(i){let c=i,d=typeof c.code=="number"?c.code:typeof c.status=="number"?c.status:void 0;return{ok:!1,code:d,spawnFailed:d===void 0}}}async function m(t,e,n=3e3,r={}){let o=await S(t,e,n,r);return o.ok?o.stdout:""}async function $(t=process.cwd()){return await m("git",["rev-parse","--show-toplevel"],2e3,{cwd:t})||t}function g(t,e){try{return JSON.parse(t)}catch{return e}}function x(t){return typeof t=="string"?t:""}function R(t,e){let n=t[e];if(typeof n=="string"||typeof n=="number"||typeof n=="boolean")return n;if(!e.includes("."))return;let r=e.split("."),o=t;for(let s of r){if(o===null||typeof o!="object"||Array.isArray(o))return;o=o[s]}if(typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o}function l(t,e){let n=R(t,e);return typeof n=="string"?n:""}var K=500;function N(t,e=2){if(!bt(t))return{entries:[],truncated:!1};let n=[],r=!1,o=(s,a)=>{if(a>e||r)return;let i;try{i=We(s,{withFileTypes:!0})}catch{return}for(let c of i){if(r)return;let d=Lt(s,c.name);if(c.isDirectory()){o(d,a+1);continue}if(c.isFile()){try{n.push({name:Je(t,d),size:Ot(d).size})}catch{continue}if(n.length>=K){r=!0;return}}}};return o(t,1),{entries:n,truncated:r}}function P(t){return bt(t)?{present:!0,size:Ot(t).size}:{present:!1,size:0}}function $t(t,e){return`${t}:${e??""}`}function ot(t=j()){return rt(t,".evalon","agent-hook")}function rn(t=j()){return rt(ot(t),"installations")}function on(t,e=j()){return rt(rn(e),`${t}.json`)}function Ut(){return Xe(8).toString("hex")}async function sn(t){let n=await m("git",["config","--get","remote.origin.url"],2e3,{cwd:t})||nn(t);return Ye("sha256").update(n).digest("hex").slice(0,16)}function an(t){if(!t||typeof t!="object"||Array.isArray(t))return;let e={};for(let[n,r]of Object.entries(t))typeof r=="string"&&r.length>0&&(e[n]=r);return Object.keys(e).length>0?e:void 0}function B(t){if(Ze(t))try{let e=JSON.parse(Qe(t,"utf8"));if(typeof e.installation_id=="string"&&e.installation_id.length>0){let n=an(e.platform_agent_ids);return{installation_id:e.installation_id,...n?{platform_agent_ids:n}:{}}}}catch{}}function Kt(t,e){let r=B(t)?.platform_agent_ids?.[e];return typeof r=="string"&&r.length>0?r:void 0}function jt(t,e,n){if(!n)return;let r=B(t);if(!r||r.platform_agent_ids?.[e]===n)return;let o={installation_id:r.installation_id,platform_agent_ids:{...r.platform_agent_ids,[e]:n}};try{w(t,`${JSON.stringify(o,null,2)}
3
- `)}catch(s){let a=s instanceof Error?s.message:String(s);u(`WARN: platform_agent_id cache write failed open: ${a}`)}}function cn(t){return t instanceof Error&&"code"in t&&t.code==="EEXIST"}function ln(t,e){qe(en(t),{recursive:!0}),tn(t,`${JSON.stringify({installation_id:e},null,2)}
4
- `,{encoding:"utf8",flag:"wx"})}function Dt(t,e){try{return ln(t,e),{installation_id:e}}catch(n){if(!cn(n))throw n;return B(t)}}async function Bt(t,e={}){let n=e.home??j(),r=await sn(t),o=on(r,n),s=B(o);if(s)return{installationId:s.installation_id,storePath:o,repoKey:r};let a=e.overrideId??e.migrateFromManifestId??Ut(),i=Dt(o,a);if(i)return{installationId:i.installation_id,storePath:o,repoKey:r};let c=Dt(o,Ut());if(c)return{installationId:c.installation_id,storePath:o,repoKey:r};throw new Error(`Failed to create installation record at ${o}`)}var un={claude:".claude",cursor:".cursor",codex:".codex"};function z(t){let n=t.replace(/^\/+|\/+$/g,"").toLowerCase().split("/").filter(Boolean);return n.length<2?"":n.join("/")}function dn(t){if(!t)return"";let e=t.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1");e=e.replace(/\.git$/i,"");let n=e.match(/^git@[^:]+:(.+)$/);if(n?.[1])return z(n[1]);let r=e.match(/^ssh:\/\/[^/]+\/(.+)$/i);if(r?.[1])return z(r[1]);e=e.replace(/^https:\/\//i,""),e=e.replace(/^http:\/\//i,""),e=e.replace(/^ssh:\/\//i,"");let o=e.match(/^[^/]+\/(.+)$/);return o?.[1]?z(o[1]):z(e)}async function st(t=process.cwd()){let e=await S("git",["rev-parse","--is-inside-work-tree"],2e3,{cwd:t});if(!e.ok||e.stdout!=="true")return null;let[n,r,o,s]=await Promise.all([S("git",["remote","get-url","origin"],2e3,{cwd:t}),S("git",["branch","--show-current"],2e3,{cwd:t}),S("git",["rev-parse","HEAD"],2e3,{cwd:t}),S("git",["status","--porcelain"],2e3,{cwd:t})]),a=n.ok?n.stdout:null;return{remote:a===null?null:a.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1"),branch:r.ok?r.stdout:null,head:o.ok?o.stdout:null,dirty:s.ok?s.stdout.length>0:null}}async function zt(t,e,n,r=process.cwd(),o,s){if(e)return e;let a=un[n];if(!a)return"";let i=$t(n,t.scope_path);if(s){let E=Kt(s,i);if(E)return E}let c=o??await st(r),d=c?.remote?dn(c.remote):"";if(d||(d=process.env.GITHUB_REPOSITORY??""),!d)return"";let f=t.scope_path??"",k=f?`${f}/`:"",y=`${d}:${k}${a}`;return s&&jt(s,i,y),y}import{existsSync as fn,readFileSync as pn}from"node:fs";import{hostname as mn,userInfo as gn}from"node:os";function Wt(){if(p("GITHUB_ACTIONS"))return"github_actions";let t=p("CI");if(t&&t!=="false"&&t!=="0")return"managed";try{if(fn("/.dockerenv")||pn("/proc/1/environ","utf8").includes("container="))return"container"}catch{}return process.stdin.isTTY||process.stdout.isTTY||p("TERM")?"interactive":"cron"}async function Vt(){return await m("systemd-detect-virt",[],1e3)}async function Gt(){let t=process.platform==="darwin"?"Darwin":process.platform==="win32"?"Windows_NT":"Linux",e="";if(process.platform==="darwin")e=await m("sw_vers",["-productVersion"],1e3);else if(process.platform==="linux"){try{let{readFileSync:s}=await import("node:fs"),a=s("/etc/os-release","utf8"),i=a.match(/^PRETTY_NAME="?([^"\n]+)"?/m)?.[1],c=a.match(/^VERSION_ID="?([^"\n]+)"?/m)?.[1];e=i??c??""}catch{e=await m("lsb_release",["-sd"],1e3).then(s=>s.replace(/^"|"$/g,""))}e||(e=await m("uname",["-r"],1e3))}else e=await m("ver",[],1e3);let n=process.env.USER??gn().username??"",r=(process.env.SHELL??"").split(/[/\\]/).pop()??"",o="";try{o=await m("tty",[],500),o.includes("not a tty")&&(o="")}catch{o=""}return{os:t,os_version:e||null,user:n||null,shell:r||null,tty:o||null}}function Jt(){return mn()}import{existsSync as _n,readFileSync as hn}from"node:fs";import{homedir as Yt}from"node:os";import{join as Sn}from"node:path";var yn="cloud-cache.json",En=1440*60*1e3,kn=900*1e3;function In(t=Yt()){return Sn(ot(t),yn)}function Rn(t){if(!_n(t))return;let e=g(hn(t,"utf8"),{});if(!(typeof e.context!="string"||typeof e.probed_at!="number"||e.result!==null&&e.result!==void 0&&typeof e.result!="object"))return{context:e.context,probed_at:e.probed_at,result:e.result??null}}function vn(t,e){try{w(t,`${JSON.stringify(e)}
5
- `)}catch(n){let r=n instanceof Error?n.message:String(n);u(`WARN: cloud cache write failed open: ${r}`)}}function wn(t,e,n){if(!t||t.context!==e)return!1;let r=t.result===null?kn:En;return n-t.probed_at<r}async function An(t){let e=await fetch("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"60"},signal:AbortSignal.timeout(t)}).catch(()=>{});if(!e?.ok)return;let n=(await e.text()).trim();if(!n)return;let r={"X-aws-ec2-metadata-token":n},[o,s]=await Promise.all([fetch("http://169.254.169.254/latest/meta-data/placement/region",{headers:r,signal:AbortSignal.timeout(t)}).catch(()=>{}),fetch("http://169.254.169.254/latest/meta-data/instance-id",{headers:r,signal:AbortSignal.timeout(t)}).catch(()=>{})]);if(!o?.ok&&!s?.ok)return;let a=o?.ok?(await o.text()).trim():"",i=s?.ok?(await s.text()).trim():"";if(!(!a&&!i))return{provider:"aws",region:a,instance_id:i}}async function Cn(t){let e=await fetch("http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true",{headers:{"Metadata-Flavor":"Google"},signal:AbortSignal.timeout(t)}).catch(()=>{});if(!e?.ok)return;let n=await e.json(),r=typeof n.zone=="string"?n.zone.split("/").pop()??"":"",o=n.id===void 0?"":String(n.id);if(!(!r&&!o))return{provider:"gcp",region:r,instance_id:o}}async function Tn(t){let e=await fetch("http://169.254.169.254/metadata/instance?api-version=2021-02-01",{headers:{Metadata:"true"},signal:AbortSignal.timeout(t)}).catch(()=>{});if(!e?.ok)return;let n=await e.json(),r=n.compute?.location??"",o=n.compute?.vmId??"";if(!(!r&&!o))return{provider:"azure",region:r,instance_id:o}}async function xn(t){let e=await Promise.allSettled([An(t),Cn(t),Tn(t)]);for(let n of e)if(n.status==="fulfilled"&&n.value)return n.value;return null}async function Xt(t,e){if(t==="interactive")return null;let n=e?.home??Yt(),r=e?.timeoutMs??1e3,o=e?.nowMs??Date.now(),s=In(n),a=Rn(s);if(wn(a,t,o))return a.result;let i=await xn(r);return vn(s,{context:t,probed_at:o,result:i}),i}import{existsSync as Nn,readFileSync as Pn}from"node:fs";import{homedir as bn}from"node:os";import{join as it}from"node:path";function at(t,e,n){if(!Nn(t))return;let r=g(Pn(t,"utf8"),{});for(let o of Object.keys(r.mcpServers??{}))n.set(o,{name:o,source:e})}async function Zt(t,e=process.cwd(),n="claude",r=bn()){let o=new Map;for(let s of t.mcp_servers??[])s.name&&o.set(s.name,{name:s.name,source:"manifest"});return n==="claude"&&at(it(r,".claude.json"),"claude_json_user",o),at(it(e,".mcp.json"),"mcp_json",o),at(it(e,".cursor/mcp.json"),"cursor_mcp",o),[...o.values()]}var On=["CI","GITHUB_ACTIONS","GITLAB_CI","CIRCLECI","BUILDKITE","TF_BUILD","GITHUB_REPOSITORY","GITHUB_REF","GITHUB_SHA","GITHUB_RUN_ID","GITHUB_WORKFLOW","RUNNER_OS","RUNNER_ARCH","NODE_ENV","TERM_PROGRAM","ANTHROPIC_BASE_URL","OPENAI_BASE_URL","OPENAI_API_BASE","AZURE_OPENAI_ENDPOINT","GOOGLE_GEMINI_BASE_URL","GEMINI_API_BASE","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX"],Ln=new Set(["key","api-key","api_key","apikey","token","sig","signature","access_token","password","pwd","secret","client_secret"]);function Mn(t){try{let e=new URL(t);(e.username||e.password)&&(e.username="",e.password="");for(let[n]of e.searchParams)Ln.has(n.toLowerCase())&&e.searchParams.set(n,"[redacted]");return e.toString()}catch{return t}}function qt(t=process.env){return On.map(e=>Object.prototype.hasOwnProperty.call(t,e)?{name:e,present:!0,value:Mn(t[e]??"")}:{name:e,present:!1})}import{createHash as Hn}from"node:crypto";import{existsSync as ee,readFileSync as ne}from"node:fs";import{homedir as re}from"node:os";import{join as _}from"node:path";var Fn={claude:{skills:".claude/skills",subagents:".claude/agents",commands:".claude/commands",memory:".claude/CLAUDE.md",settings:".claude/settings.json"},cursor:{skills:[".cursor/skills",".cursor/skills-cursor"],commands:".cursor/commands",rules:".cursor/rules",mcp:".cursor/mcp.json"},codex:{skills:".agents/skills",commands:".codex/prompts",memory:".codex/AGENTS.md",settings:".codex/config.toml"}},Un=200,Qt=200,Dn=["allow","deny","ask"],$n=/(?<=^|[\s(,=:])(?:~|[A-Za-z]:)?[\\/][^\s,)]+/g,ct="<path>",Kn=new RegExp(`${ct}(?:\\s+[A-Za-z.][^\\s,)]*[\\\\/][^\\s,)]*)+`,"g");function jn(t){let e=t.replace($n,ct).replace(Kn,ct);return e.length>Qt?`${e.slice(0,Qt)}...`:e}function te(t){if(!ee(t))return{model:"",permissionKeys:[]};let e=g(ne(t,"utf8"),{}),n=[];for(let r of Dn)for(let o of e.permissions?.[r]??[])typeof o=="string"&&o.length>0&&n.push({key:jn(o),mode:r});return{model:e.model??"",permissionKeys:n}}var Bn=10,zn="self-config-cache.json",Wn={claude:["claude"],cursor:["agent","cursor-agent"],codex:["codex"]};async function Vn(t,e=m){let n=Wn[t];if(!n||n.length===0)return null;let r=async o=>{let s=n[o];if(s===void 0)return null;let i=((await e(s,["--version"],2e3)).split(`
6
- `)[0]??"").trim();return i||r(o+1)};return r(0)}function Gn(t=re()){return _(t,".evalon","agent-hook",zn)}function Jn(t){let n=[...t].sort((r,o)=>r.name.localeCompare(o.name)).map(r=>`${r.name}:${r.size}`).join(`
7
- `);return Hn("sha256").update(n).digest("hex").slice(0,16)}function W(t,e,n=!1){let r=Jn(t),o=t.length;return e===r?n?{hash:r,count:o,truncated:n}:{hash:r,count:o}:n?{hash:r,count:o,entries:t,truncated:n}:{hash:r,count:o,entries:t}}function Yn(t){return ee(t)?g(ne(t,"utf8"),{}):{}}function Xn(t,e){try{w(t,`${JSON.stringify(e)}
8
- `)}catch(n){let r=n instanceof Error?n.message:String(n);u(`WARN: self-config cache write failed open: ${r}`)}}function Zn(t,e,n){let r={...t,send_count:n};for(let o of Object.keys(e)){let s=e[o];s.entries!==void 0&&(r[o]=s.hash)}return r}async function oe(t,e=process.cwd(),n=re()){let r=t==="claude",o=await Vn(t),s="",a=[];if(r){let h=te(_(n,".claude/settings.json")),H=te(_(e,".claude/settings.local.json"));s=H.model||h.model,a=[...h.permissionKeys,...H.permissionKeys].slice(0,Un)}let i=Fn[t]??{},c={present:!1,size:0},d=h=>{let H=Array.isArray(h)?h:h?[h]:[],v=[],F=!1;for(let $e of H){let kt=N(_(n,$e));if(v=v.concat(kt.entries),F=F||kt.truncated,v.length>=K){v=v.slice(0,K),F=!0;break}}return{entries:v,truncated:F}},f=Gn(n),k=Yn(f),y=k[t]??{},E=(y.send_count??0)+1,q=E>0&&E%Bn===0,I=h=>q?void 0:y[h],C=d(i.skills),M=i.subagents?N(_(n,i.subagents)):{entries:[],truncated:!1},yt=i.commands?N(_(n,i.commands)):{entries:[],truncated:!1},Et=i.rules?N(_(n,i.rules)):{entries:[],truncated:!1},T={skills:W(C.entries,I("skills"),C.truncated),subagents:W(M.entries,I("subagents"),M.truncated),commands:W(yt.entries,I("commands"),yt.truncated),rules:W(Et.entries,I("rules"),Et.truncated)};return k[t]=Zn(y,T,E),Xn(f,k),{runner_platform:t,config_scope:"user",cli_version:o,claude_version:r?o:null,model:r&&s||null,permission_keys:a,user_scope:{skills:T.skills,subagents:T.subagents,commands:T.commands,rules:T.rules,memory:i.memory?P(_(n,i.memory)):c,settings:i.settings?P(_(n,i.settings)):c,mcp:i.mcp?P(_(n,i.mcp)):c},local_settings:r?P(_(e,".claude/settings.local.json")):c}}function b(t,e,n){let r={installation_id:n.installationId};return n.platformAgentId&&(r.platform_agent_id=n.platformAgentId),n.sessionId&&(r.session_id=n.sessionId),n.turnId&&(r.turn_id=n.turnId),{schema_version:2,event:t,timestamp:Mt(),session_id:n.sessionId||null,turn_id:n.turnId||null,installation_id:n.installationId,platform:n.runnerPlatform,platform_agent_id:n.platformAgentId||null,runner_event:n.runnerEvent||null,agent_hook_version:et,host_arch:process.arch,node_version:process.version,correlation:r,payload:e}}import{existsSync as Re}from"node:fs";import{spawn as ve}from"node:child_process";import{basename as Rr}from"node:path";import{fileURLToPath as vr}from"node:url";var qn=new Set(["localhost","127.0.0.1","[::1]","::1"]),se=/^[A-Za-z0-9._~-]+$/;function ie(t){for(let e=0;e<t.length;e++){let n=t.charCodeAt(e);if(n<=32||n===127||n===39)return!0}return!1}function V(t){try{let e=new URL(t);return e.protocol==="https:"?!0:e.protocol==="http:"?qn.has(e.hostname):!1}catch{return!1}}function ae(t){let e;try{e=new URL(t)}catch{return`invalid URL (got: ${t})`}if(!V(t))return`must be https (or http on localhost / 127.0.0.1 / ::1) (got: ${t})`;let n=Qn(t);if(!n)return`must end with /{orgToken}/hook (got: ${t})`;if(!se.test(n))return`org token must match ${se.source} (got: ${n})`;if(ie(t))return`must not contain whitespace, control characters, or single quotes (got: ${t})`;if(ie(e.pathname))return`pathname must not contain whitespace, control characters, or single quotes (got: ${t})`}function ce(t){return new URL(t).toString()}function Qn(t){try{let n=new URL(t).pathname.split("/").filter(r=>r.length>0);if(n.length>=2&&n[n.length-1]==="hook"){let r=n[n.length-2];return r.length>0?r:void 0}return}catch{return}}function ut(t){try{let e=new URL(t),n=e.pathname.split("/").filter(r=>r.length>0);return n.length>=2&&n[n.length-1]==="hook"&&(n[n.length-2]="***",e.pathname=`/${n.join("/")}`),e.toString()}catch{return"<invalid-url>"}}function le(t){if(t.collector_url)return t.collector_url;let e=t.repo_ingest_token?.trim();return e?U(e):""}var ue=/(?:^|\/|[\s"'=(])(?:\.cursor\/|\.claude\/|\.agents\/)skills(?:-cursor)?\/([^/]+)\/SKILL\.md/i,de=/(?:^|\/|[\s"'=(])\.codex\/commands\/([^/]+)\.md\b/i,tr=/(?:^|\s)\/([a-z][a-z0-9-]{1,63})\b/gi,er=new Set(["applications","app","bin","boot","data","dev","etc","home","lib","media","mnt","node_modules","opt","pkg","private","proc","projects","repos","run","sbin","src","srv","sys","tmp","usr","users","var","volumes","workspace","workspaces"]),nr=new Set(["read","read_file","view"]),rr=new Set(["bash","shell","zsh"]);function or(t){let e=t.replace(/\\/g,"/");return ue.exec(e)?.[1]??null}function sr(t){let e=t.replace(/\\/g,"/"),r=de.exec(e)?.[1];return r?r.toLowerCase():null}function ir(t){return or(t)??sr(t)}function ar(t){for(let e of["path","file_path","target_file"]){let n=t[e];if(typeof n=="string"&&n.length>0)return n}return null}function fe(t){if(typeof t=="string")try{let e=JSON.parse(t);return fe(e)}catch{return null}return!t||typeof t!="object"?null:ar(t)}function cr(t){if(!t||typeof t!="object")return null;let e=t.command;return typeof e=="string"&&e.length>0?e:null}function lr(t){let e=t.replace(/\\/g,"/"),n=ue.exec(e);if(n?.[1])return n[1];let o=de.exec(e)?.[1];return o?o.toLowerCase():null}function ur(t){return typeof t.tool_name=="string"?t.tool_name:typeof t.tool=="string"?t.tool:""}function pe(t){let e=ur(t).toLowerCase();if(nr.has(e)){let n=fe(t.tool_input);return n?ir(n):null}if(rr.has(e)){let n=cr(t.tool_input);return n?lr(n):null}return null}function dr(t){let e=new Set,n=[];for(let r of t.matchAll(tr)){let o=r[1]?.toLowerCase();!o||e.has(o)||er.has(o)||(e.add(o),n.push(o))}return n}function fr(t){return x(t.prompt)}function me(t){let e=l(t,"command_name");if(e){let r=l(t,"expansion_type");if(r&&r!=="slash_command")return[];let o=e.replace(/^\//,"").toLowerCase();return o?[o]:[]}let n=fr(t);return n?dr(n):[]}function dt(t){return t!==void 0&&Tt.includes(t)}function G(t,e){let n=t[e+1];return n&&!n.startsWith("--")?{value:n,next:e+1}:{next:e}}function J(t){let e,n,r,o,s;for(let a=0;a<t.length;a++){let i=t[a];if(i!==void 0){if(i==="--runner"){let c=G(t,a);e=c.value,a=c.next;continue}if(i.startsWith("--runner=")){e=i.slice(9);continue}if(i==="--url"){let c=G(t,a);c.value&&(r=c.value),a=c.next;continue}if(i.startsWith("--url=")){r=i.slice(6);continue}if(i==="--token"){let c=G(t,a);c.value&&(o=c.value),a=c.next;continue}if(i.startsWith("--token=")){o=i.slice(8);continue}if(i==="--base-url"){let c=G(t,a);c.value&&(s=c.value),a=c.next;continue}if(i.startsWith("--base-url=")){s=i.slice(11);continue}!i.startsWith("-")&&n===void 0&&(n=i)}}return{runner:dt(e)?e:void 0,event:n,collectorUrl:r,orgToken:o,baseUrl:s}}function ft(t){let e=t.collectorUrl?.trim(),n;if(e)n=e;else{let o=t.orgToken?.trim();o&&(n=U(o,t.baseUrl?.trim()??void 0))}if(!n)return;let r=ae(n);if(r){u(`WARN: ignoring --url/--token collector override: ${r}`);return}return ce(n)}function pr(t,e){return l(t,"conversation_id")?!0:e!==""&&e===e.toLowerCase()}function pt(t,e,n,r){if(pr(t,e))return"cursor";if(dt(r))return r;let o=l(t,"conversation_id"),s=l(t,"turn_id"),a=l(t,"session_id"),i=e.toLowerCase(),c="unknown";return o||e===i&&e!==""?c="cursor":s?c="codex":(a||i==="sessionstart"||i==="sessionend"||i==="stop"||i==="stopfailure"||i==="pretooluse"||i==="posttooluse"||i==="posttoolusefailure"||i==="permissiondenied"||i==="subagentstart"||i==="subagentstop"||i==="userpromptexpansion")&&(c="claude"),dt(n)&&(c=n),c}function Y(t,e){let n=t.toLowerCase();return n==="sessionend"||n==="stopfailure"||n==="subagentstop"?!0:n==="stop"&&e==="codex"}function mr(t){switch(t){case"sessionstart":return"session_start";case"stop":case"sessionend":case"stopfailure":return"session_end";case"pretooluse":case"posttooluse":case"posttoolusefailure":case"permissiondenied":case"beforemcpexecution":case"beforeshellexecution":case"afterfileedit":case"subagentstart":case"subagentstop":return"tool_invoked";case"beforesubmitprompt":case"userpromptexpansion":case"userpromptsubmit":return"skill_invoked";default:return""}}function ge(t){let e=t.toLowerCase();return e==="posttooluse"?!0:e==="posttoolusefailure"||e==="permissiondenied"?!1:null}function _e(t,e,n){let r=l(t,"session_id")||l(t,"conversation_id"),o=l(t,"prompt.id")||l(t,"prompt_id")||l(t,"generation_id")||l(t,"turn_id"),s=l(t,"hook_event_name")||l(t,"event"),a=l(t,"source"),i=pt(t,s,e,n);return{sessionId:r,turnId:o,runnerEvent:s,hookSource:a,runnerPlatform:i}}var gr=["session_start","session_end","tool_invoked","skill_invoked"];function _r(t){return gr.includes(t)}function he(t,e){return t&&_r(t)?t:mr(e.toLowerCase())}function Se(t){let e=l(t,"tool_name")||l(t,"tool")||null,n=t.tool_input,o=(n&&typeof n=="object"?x(n.skill)||x(n.skill_name):"")||l(t,"skill_name")||null;return o??=pe(t),{toolName:e,skillName:o}}var hr=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;function ye(t){for(let e of["subagent_type","agent_type"]){let n=l(t,e);if(n&&hr.test(n))return n}return null}function Ee(t){let e=R(t,"duration_ms");if(typeof e=="number")return e;let n=R(t,"duration");return typeof n=="number"?n:null}var Sr="error",yr="interrupted",Er="permission_denied",kr=/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/;function mt(t){return kr.test(t)?t:null}function Ir(t){for(let e of["failure_type","error_type"]){let n=mt(l(t,e));if(n)return n}return null}function ke(t,e){return R(t,"is_interrupt")===!0?yr:e.toLowerCase()==="permissiondenied"?Er:Ir(t)??Sr}function Ie(t){if(!t)return{mcpServer:null,mcpTool:null};let e=/^mcp__(.+?)__(.+)$/i.exec(t);if(e?.[1]&&e[2])return{mcpServer:e[1],mcpTool:e[2]};if(/^MCP:/i.test(t)){let n=t.slice(4);if(!n)return{mcpServer:null,mcpTool:null};let r=n.indexOf(":");return r>0?{mcpServer:n.slice(0,r),mcpTool:n.slice(r+1)||null}:{mcpServer:null,mcpTool:n}}return{mcpServer:null,mcpTool:null}}var gt="__post",_t="__work";function wr(t,e){let n=t.payload,r=n&&typeof n=="object"&&!Array.isArray(n)?Object.keys(n):[],o=t.correlation&&typeof t.correlation=="object"?Object.keys(t.correlation):[];return JSON.stringify({event:t.event,schema_version:t.schema_version,agent_hook_version:t.agent_hook_version,host_arch:t.host_arch,node_version:t.node_version,body_bytes:e,correlation_keys:o,payload_keys:r})}function we(t){switch(t){case"session_start":return Rt;case"session_end":return vt;case"tool_invoked":case"skill_invoked":return Q;default:return Q}}function Ar(t,e,n){return`${JSON.stringify({url:t,timeoutMs:e})}
9
- ${n}`}function Ae(t,e=[],n=process.execPath,r=import.meta.url,o=Re){if(Rr(n)===D)return{command:n,args:[t,...e]};let s=vr(r);return o(s)?{command:n,args:[s,t,...e]}:{command:n,args:[t,...e]}}function Cr(t=process.execPath,e=import.meta.url,n=Re){return Ae(gt,[],t,e,n)}function Tr(t){let e=t.indexOf(`
10
- `);if(e<0)return null;let n;try{n=JSON.parse(t.slice(0,e))}catch{return null}return{meta:n,body:t.slice(e+1)}}async function Ce(t,e=fetch){let n=await t(),r=Tr(n);if(!r)return;let{meta:o,body:s}=r,a={"Content-Type":"application/json"};try{await e(o.url,{method:"POST",headers:a,body:s,signal:AbortSignal.timeout(Number(o.timeoutMs))})}catch{}}async function xr(t,e,n){let r=we(t);u(`POST event=${t} url=${ut(n)} size=${e.length} platform=${process.platform}`);let o={"Content-Type":"application/json"},s=Date.now();try{let a=await fetch(n,{method:"POST",headers:o,body:e,signal:AbortSignal.timeout(r)}),i=Date.now()-s;if(a.ok)return u(`POST outcome=ok elapsed_ms=${i} http=${a.status}`),!0;let c=(await a.text()).slice(0,200).replace(/[\n\r]/g,"");return u(`POST outcome=fail elapsed_ms=${i} http=${a.status} body=${c}`),!1}catch(a){let i=Date.now()-s,c=a instanceof Error?a.message:String(a);return u(`POST outcome=fail elapsed_ms=${i} http=000 body=${c}`),!1}}async function Te(t,e,n,r,o){try{let s=r(t,e,{detached:!0,stdio:["pipe","ignore","ignore"],windowsHide:!0});s.on("error",()=>{}),s.stdin.on("error",()=>{});let a=!1;return await new Promise(i=>{let c=setTimeout(()=>{if(!a){u(`WARN: ${o} stdin handoff timed out \u2014 continuing fail-open`);try{s.stdin.destroy()}catch{}}i()},wt),d=()=>{a=!0,clearTimeout(c),i()};s.stdin.end(n,()=>d()),s.stdin.once("error",()=>d())}),s.unref(),s}catch(s){let a=s instanceof Error?s.message:String(s);return u(`WARN: ${o} spawn failed open: ${a}`),null}}async function Nr(t,e,n,r=ve,o=Cr){let s=we(t),a=Ar(n,s,e),{command:i,args:c}=o();return Te(i,c,a,r,"detached post")}async function xe(t,e,n=ve,r=Ae){let{command:o,args:s}=r(_t,e);return Te(o,s,t,n,"detached work")}async function O(t,e,n,r,o){if(!o){u("WARN: collector URL missing \u2014 pass --url on the hook command or set collector_url in manifest");return}if(!V(o)){u(`WARN: collector URL blocked (https required): ${ut(o)}`);return}let s=r(t,e,n),a=`${JSON.stringify(s)}
11
- `,i=p("EVALON_HOOK_DEBUG");if(i==="full"?u(`DEBUG envelope=${JSON.stringify(s)}`):i==="1"&&u(`DEBUG summary=${wr(s,Buffer.byteLength(a,"utf8"))}`),!Y(n.runnerEvent,n.runnerPlatform)){await Nr(t,a,o);return}await xr(t,a,o)}import{relative as Pr,resolve as ht,sep as Ne}from"node:path";var br=["session_id","conversation_id","turn_id","generation_id","prompt.id","prompt_id","hook_event_name","event","source","status","stop_reason","reason","tool_name","tool","tool_use_id","skill_name","command_name","expansion_type","command_source","permission_mode","model","model_id","agent_id","agent_type","subagent_id","subagent_type","subagent_model","is_parallel_worker","effort","effort.level","duration_ms","duration","failure_type","is_interrupt"];function Or(t){return t.capture_hook_input==="full"?!0:t.capture_hook_input==="allowlist"?!1:p("EVALON_HOOK_CAPTURE_FULL_INPUT")==="1"}function Lr(t){let e={};for(let n of br){let r=R(t,n);r!==void 0&&(e[n]=r)}return e}function Mr(t,e){if(typeof t!="string"||t.length===0||!e)return null;let n=ht(t),r=ht(e),o=Pr(r,n);return!o||o==="."?".":o.startsWith(`..${Ne}`)||o===".."||ht(r,o)!==n?null:o.split(Ne).join("/")}function Pe(t,e){let n=JSON.stringify(t),r=Buffer.byteLength(n,"utf8");if(r<=e)return t;let o=Object.entries(t).filter(([a,i])=>!a.startsWith("_")&&(typeof i=="string"||typeof i=="number"||typeof i=="boolean")).sort((a,i)=>Buffer.byteLength(JSON.stringify(a[1]),"utf8")-Buffer.byteLength(JSON.stringify(i[1]),"utf8")),s={_truncated:!0,_original_bytes:r};for(let[a,i]of o){let c={...s,[a]:i};if(Buffer.byteLength(JSON.stringify(c),"utf8")>e)break;s[a]=i}return s}function L(t,e,n={}){let r=n.gitRoot!==void 0?Mr(t.cwd,n.gitRoot):null;if(Or(e)){let s={...t};return delete s.cwd,delete s.transcript_path,r!==null&&(s.cwd_relative=r),Pe(s,Ct)}let o=Lr(t);return r!==null&&(o.cwd_relative=r),Pe(o,At)}import{createReadStream as Hr}from"node:fs";import{stat as Fr}from"node:fs/promises";import{basename as Ur,resolve as Dr}from"node:path";import{createInterface as $r}from"node:readline";var Kr=1024*1024;function jr(t){let e=t.replace(/\\/g,"/");return e.includes("/.claude/projects/")&&Ur(e).endsWith(".jsonl")}async function be(t){if(!t||!jr(t))return null;try{let e=Dr(t),n=await Fr(e);if(!n.isFile())return null;let r=Math.max(0,n.size-Kr),o=[],s=$r({input:Hr(e,{encoding:"utf8",start:r}),crlfDelay:1/0});for await(let a of s)a.length!==0&&o.push(a);r>0&&o.length>0&&o.shift();for(let a=o.length-1;a>=0;a--){let i=o[a];if(i)try{let c=JSON.parse(i);if(c.type!=="assistant")continue;let d=c.message;if(!d||typeof d!="object")continue;let f=d.model;if(typeof f=="string"&&f.length>0)return f}catch{continue}}return null}catch{return null}}function X(t){return{sessionId:t.sessionId,turnId:t.turnId,installationId:t.manifest.installationId,runnerPlatform:t.runnerPlatform,platformAgentId:t.platformAgentId,runnerEvent:t.runnerEvent}}function Br(...t){for(let e of t)if(e)return e;return null}function A(t,e,n){if(t.status==="fulfilled")return t.value;let r=t.reason instanceof Error?t.reason.message:String(t.reason);return u(`WARN: ${n} failed open: ${r}`),e}function zr(t){let e={present:!1,size:0},n={hash:"",count:0};return{runner_platform:t,config_scope:"user",cli_version:null,claude_version:null,model:null,permission_keys:[],user_scope:{skills:n,subagents:n,commands:n,rules:n,memory:e,settings:e,mcp:e},local_settings:e}}async function Z(t,e,n){try{t.platformAgentId=await zt(t.manifest.manifest,t.platformAgentId,String(t.runnerPlatform),e,n,t.manifest.installationStorePath)}catch(r){let o=r instanceof Error?r.message:String(r);u(`WARN: derivePlatformAgentId failed open: ${o}`)}}async function Wr(t){let{gitRoot:e}=t.manifest,n=Wt(),r=String(t.runnerPlatform),[o,s,a,i,c,d]=await Promise.allSettled([st(e),Vt(),Xt(n),Gt(),Zt(t.manifest.manifest,e,r),oe(r,e)]),f=A(o,null,"gitSnapshot"),k=A(s,"","detectVirt"),y=A(a,null,"probeCloud"),E=A(i,{},"hostEnv"),q=A(c,[],"mcpDeclared"),I=A(d,zr(r),"selfConfig");await Z(t,e,f);let C=l(t.hookInput,"model");C&&(I.model=C);let M={identity:{host:Jt(),context:n,virt:k||null,cloud:y,git:f},host_env:E,env_vars:qt(),mcp:{declared:q},self_config:I,run_meta:{trigger:t.hookSource||"startup"},hook_input:L(t.hookInput,t.manifest.manifest,{gitRoot:e})};await O("session_start",M,X(t),b,t.manifest.collectorUrl)}async function Vr(t){let{gitRoot:e}=t.manifest;await Z(t,e);let n=Br(l(t.hookInput,"status"),l(t.hookInput,"stop_reason"),l(t.hookInput,"reason"),mt(l(t.hookInput,"error"))),r=t.runnerPlatform==="claude"?await be(l(t.hookInput,"transcript_path")):null,o=L(t.hookInput,t.manifest.manifest,{gitRoot:e});r&&(o.model=r),await O("session_end",{status:n,...r?{model:r}:{},hook_input:o},X(t),b,t.manifest.collectorUrl)}async function Gr(t){let e=me(t.hookInput);if(e.length===0)return;let{gitRoot:n}=t.manifest;await Z(t,n);let r=L(t.hookInput,t.manifest.manifest,{gitRoot:n}),o=X(t);await Promise.all(e.map(s=>O("tool_invoked",{tool_name:"Skill",skill_name:s,success:null,duration_ms:null,hook_input:r},o,b,t.manifest.collectorUrl)))}async function Jr(t){let{gitRoot:e}=t.manifest;await Z(t,e);let{toolName:n,skillName:r}=Se(t.hookInput),o=Ee(t.hookInput),s=ge(t.runnerEvent),a=s===!1?ke(t.hookInput,t.runnerEvent):null,{mcpServer:i,mcpTool:c}=Ie(n),d=ye(t.hookInput);await O("tool_invoked",{tool_name:n,skill_name:r,success:s,duration_ms:o,...a?{failure_reason:a}:{},...i?{mcp_server:i}:{},...c?{mcp_tool:c}:{},...d?{subagent_type:d}:{},hook_input:L(t.hookInput,t.manifest.manifest,{gitRoot:e})},X(t),b,t.manifest.collectorUrl)}async function Oe(t){switch(t.internalEvent){case"session_start":await Wr(t);return;case"session_end":await Vr(t);return;case"skill_invoked":await Gr(t);return;case"tool_invoked":await Jr(t);return;default:return}}function Le(t){return t!=="session_start"&&t!=="session_end"&&t!=="tool_invoked"&&t!=="skill_invoked"&&t!==""}import{existsSync as St,readFileSync as Yr}from"node:fs";import{dirname as Xr,join as Me,relative as Zr}from"node:path";var He=[It,".cursor/evalon-runtime-report.json",".codex/evalon-runtime-report.json"];async function qr(t=process.cwd(),e){let n=p("EVALON_HOOK_MANIFEST");if(n&&St(n))return n;let r=e??await $(t);for(let o of He){let s=Me(r,o);if(St(s))return s}for(let o of He){let s=Me(t,o);if(St(s))return s}}async function Qr(t,e){let n=e??await $(Xr(t)),r=Zr(n,t),o=await S("git",["ls-files","--error-unmatch",r],2e3,{cwd:n});return o.ok?!0:o.code===1?!1:(u(`WARN: git ls-files failed for manifest ${t} (code=${String(o.code)}); treating as tracked`),!0)}function to(t){let e=Yr(t,"utf8");return g(e,{})}function eo(){return{schema_version:2,mcp_servers:[]}}async function Fe(t=process.cwd()){let e=await $(t),n=await qr(t,e),r=n?to(n):eo(),o,s=n?await Qr(n,e):!1;s&&r.installation_id?(u(`WARN: ignoring installation_id in git-tracked manifest ${n}; identity is per-machine under ~/.evalon/agent-hook/installations/`),delete r.installation_id):!s&&r.installation_id&&(o=r.installation_id,delete r.installation_id),r.capture_hook_input==="full"&&n&&s&&(u(`WARN: ignoring capture_hook_input=full in git-tracked manifest ${n}; use EVALON_HOOK_CAPTURE_FULL_INPUT=1 or an untracked operator manifest`),delete r.capture_hook_input);let{installationId:a,storePath:i}=await Bt(e,{migrateFromManifestId:o});return r.installation_id=a,{manifestPath:n??i,manifest:r,installationId:a,installationStorePath:i,collectorUrl:le(r),platformAgentId:r.platform_agent_id??"",gitRoot:e}}async function Ue(t,e,n,r){let o=e??await nt(tt),s=g(o,{}),a=await Fe();if(!a)return;r&&(a.collectorUrl=r);let i=_e(s,a.manifest.platform,n),c=he(t,i.runnerEvent);if(!c){u(`WARN: unknown hook event '${i.runnerEvent}'; skipping telemetry`);return}let d={hookInput:s,sessionId:i.sessionId,turnId:i.turnId,runnerEvent:i.runnerEvent,runnerPlatform:i.runnerPlatform,hookSource:i.hookSource,internalEvent:c,manifest:a,platformAgentId:a.platformAgentId};if(Le(c)){u(`WARN: unsupported internal event '${c}'`);return}await Oe(d)}function no(t,e){if(p("EVALON_HOOK_SYNC")==="1")return!0;let n=J(t),r=g(e,{}),o=n.event??(l(r,"hook_event_name")||l(r,"event")),s=pt(r,o,void 0,n.runner);return Y(o,s)}async function De(t=process.argv.slice(2)){if(t[0]===gt){try{await Ce(Ft)}catch{}return 0}if(t[0]===_t){try{let e=J(t.slice(1));await Ue(e.event,void 0,e.runner,ft(e))}catch(e){let n=e instanceof Error?e.message:String(e);u(`WARN: detached work failed open: ${n}`)}return 0}try{let e=await nt(tt),n=J(t),r=ft(n);no(t,e)?await Ue(n.event,e,n.runner,r):await xe(e,t)}catch(e){let n=e instanceof Error?e.message:String(e);u(`WARN: hook failed open: ${n}`)}finally{Ht()}return 0}De().then(t=>{process.exit(t)}).catch(t=>{let e=t instanceof Error?t.message:String(t);process.stderr.write(`[evalon-agent-hook] ${e}
1
+ var dr="https://hooks.ev-ai.ai";function le(e,t=dr){let n=t.replace(/\/+$/,""),r=e.trim();return`${n}/${r}/hook`}var Tt=".claude/ev-ai-runtime-report.json";var ue="ev-ai-agent-hook";var fi=`current/${ue}`,mi=`.ev-ai/agent-hook/${ue}`,At=5e3,kt=5e3,xe=3e3;var Ue=3e3,Ot=1500,xt=4*1024,Ut=32*1024,pr=4*1024,be="1.0.7",gi=`@ev-ai/agent-hook@${be}`;var bt=["claude","cursor","codex"];import{createHash as Bt,randomBytes as yr}from"node:crypto";import{existsSync as $t,mkdirSync as Gt,readFileSync as Kt,unlinkSync as jt,writeFileSync as Vt}from"node:fs";import{homedir as Me}from"node:os";import{dirname as Le,join as Pe,resolve as Ir}from"node:path";import{randomBytes as fr}from"node:crypto";import{existsSync as Mt,mkdirSync as mr,readdirSync as gr,readFileSync as _r,renameSync as wt,statSync as Lt,unlinkSync as Nt,writeFileSync as hr}from"node:fs";import{basename as Er,dirname as vt,join as Pt,relative as Sr}from"node:path";function m(e){process.stderr.write(`[ev-ai-agent-hook] ${e}
2
+ `)}function B(e,t){mr(vt(e),{recursive:!0});let n=Pt(vt(e),`.${Er(e)}.${process.pid}.${fr(4).toString("hex")}.tmp`);try{hr(n,t,"utf8");try{wt(n,e)}catch(r){let o=r instanceof Error&&"code"in r?r.code:void 0;if(o==="EEXIST"||o==="EPERM"||o==="EACCES"){Nt(e),wt(n,e);return}throw r}}catch(r){try{Nt(n)}catch{}throw r}}function de(){return new Date().toISOString().replace(/\.\d{3}Z$/,"Z")}function Dt(){process.stdout.write('{"continue":true}')}function E(e){let t=process.env[e];return t===void 0||t===""?void 0:t}async function Ne(){return new Promise(e=>{let t="";if(process.stdin.isTTY){e("");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",n=>{t+=n}),process.stdin.on("end",()=>{e(t)}),process.stdin.on("error",()=>{e(t)}),process.stdin.resume()})}async function ve(e){return new Promise(t=>{let n="",r=!1,o=i=>{r||(r=!0,clearTimeout(s),t(i||"{}"))},s=setTimeout(()=>{o(n)},e);if(process.stdin.isTTY){o("{}");return}process.stdin.setEncoding("utf8"),process.stdin.on("data",i=>{n+=i}),process.stdin.on("end",()=>{o(n)}),process.stdin.on("error",()=>{o(n)}),process.stdin.resume()})}async function L(e,t,n=3e3,r={}){let{execFile:o}=await import("node:child_process"),{promisify:s}=await import("node:util"),i=s(o);try{let{stdout:a}=await i(e,t,{timeout:n,windowsHide:!0,maxBuffer:1048576,cwd:r.cwd});return{ok:!0,stdout:a.trim()}}catch(a){let c=a,l=typeof c.code=="number"?c.code:typeof c.status=="number"?c.status:void 0;return{ok:!1,code:l,spawnFailed:l===void 0}}}async function R(e,t,n=3e3,r={}){let o=await L(e,t,n,r);return o.ok?o.stdout:""}async function pe(e=process.cwd()){return await R("git",["rev-parse","--show-toplevel"],2e3,{cwd:e})||e}function O(e,t){try{return JSON.parse(e)}catch{return t}}var we=new Map;function W(e,t){let n=we.get(e);if(n!==void 0)return n;try{let r=O(_r(e,"utf8"),t);return we.set(e,r),r}catch{return we.set(e,t),t}}function Q(e){return typeof e=="string"?e:""}function $(e,t){let n=e[t];if(typeof n=="string"||typeof n=="number"||typeof n=="boolean")return n;if(!t.includes("."))return;let r=t.split("."),o=e;for(let s of r){if(o===null||typeof o!="object"||Array.isArray(o))return;o=o[s]}if(typeof o=="string"||typeof o=="number"||typeof o=="boolean")return o}function p(e,t){let n=$(e,t);return typeof n=="string"?n:""}var G=500;function q(e,t=2){if(!Mt(e))return{entries:[],truncated:!1};let n=[],r=!1,o=(s,i)=>{if(i>t||r)return;let a;try{a=gr(s,{withFileTypes:!0})}catch{return}for(let c of a){if(r)return;let l=Pt(s,c.name);if(c.isDirectory()){o(l,i+1);continue}if(c.isFile()){try{n.push({name:Sr(e,l),size:Lt(l).size})}catch{continue}if(n.length>=G){r=!0;return}}}};return o(e,1),{entries:n,truncated:r}}function ee(e){return Mt(e)?{present:!0,size:Lt(e).size}:{present:!1,size:0}}var Rr="installation.json",Cr="cloud-bootstrap.lock",Tr=6e4;function zt(e,t,n){let r=`${e}:${t??""}`;return n?`${n}:${r}`:r}function De(e=Me()){return Pe(e,".ev-ai","agent-hook")}function Ar(e=Me()){return Pe(De(e),Rr)}function Wt(e){return Pe(Le(e),Cr)}function Jt(){return yr(8).toString("hex")}function fe(e){return Bt("sha256").update(e).digest("hex").slice(0,16)}function y(e){if(e===void 0)return null;let t=e.trim();return t.length>0?t:null}function Yt(e){return/^[A-Za-z0-9._-]{8,64}$/.test(e)}function kr(e=process.env){let t=y(e.EV_AI_HOOK_INSTALLATION_ID);if(t){if(!Yt(t)){m(`WARN: ignoring EV_AI_HOOK_INSTALLATION_ID (expected 8\u201364 chars [A-Za-z0-9._-], got length ${t.length})`);return}return t}}function Or(e=process.env){if(y(e.GITHUB_ACTIONS)){let t=y(e.GITHUB_REPOSITORY_ID)??y(e.GITHUB_REPOSITORY),n=y(e.GITHUB_ACTOR)??y(e.GITHUB_TRIGGERING_ACTOR)??y(e.GITHUB_USER);if(t&&n)return fe(`github_actions|${t}|${n}`)}if(y(e.CODESPACES)||y(e.CODESPACE_NAME)){let t=y(e.CODESPACE_NAME);if(t)return fe(`codespaces|${t}`);let n=y(e.GITHUB_REPOSITORY_ID)??y(e.GITHUB_REPOSITORY),r=y(e.GITHUB_USER)??y(e.GITHUB_ACTOR);if(n&&r)return fe(`codespaces|${n}|${r}`)}if(y(e.GITLAB_CI)){let t=y(e.CI_PROJECT_ID)??y(e.CI_PROJECT_PATH),n=y(e.GITLAB_USER_LOGIN)??y(e.GITLAB_USER_EMAIL)??y(e.GITLAB_USER_NAME);if(t&&n)return fe(`gitlab|${t}|${n}`)}return null}function Ht(e,t){if(e&&Yt(e))return e;e&&m(`WARN: ignoring installation id override (expected 8\u201364 chars [A-Za-z0-9._-], got length ${e.length})`);let n=kr(t);if(n)return n;let r=Or(t);return r||Jt()}async function xr(e){let n=await R("git",["config","--get","remote.origin.url"],2e3,{cwd:e})||Ir(e);return Bt("sha256").update(n).digest("hex").slice(0,16)}function Ur(e){if(!e||typeof e!="object"||Array.isArray(e))return;let t={};for(let[n,r]of Object.entries(e))typeof r=="string"&&r.length>0&&(t[n]=r);return Object.keys(t).length>0?t:void 0}function br(e){try{let t=JSON.parse(e);if(typeof t.installation_id!="string"||t.installation_id.length===0)return;let n=Ur(t.platform_agent_ids);return{installation_id:t.installation_id,...n?{platform_agent_ids:n}:{},...typeof t.operator_identity_hash=="string"?{operator_identity_hash:t.operator_identity_hash}:{},...typeof t.operator_identity_sent_at=="string"?{operator_identity_sent_at:t.operator_identity_sent_at}:{}}}catch{return}}function K(e){if($t(e))try{return br(Kt(e,"utf8"))}catch{}}function He(e){return K(e)}function Xt(e,t,n){let r=K(e);if(!r||r.operator_identity_hash===t&&r.operator_identity_sent_at===n)return;let o={...r,operator_identity_hash:t,operator_identity_sent_at:n};try{B(e,`${JSON.stringify(o,null,2)}
3
+ `)}catch(s){let i=s instanceof Error?s.message:String(s);m(`WARN: operator identity cache write failed open: ${i}`)}}function Zt(e,t=Date.now()){if(!e)return!0;if(K(e)?.operator_identity_hash)return!1;let n=Wt(e);try{if($t(n)){let r=Number.NaN;try{r=Number(Kt(n,"utf8").trim())}catch{}let o=t-r;if(Number.isFinite(o)&&o>=0&&o<Tr)return!1;try{jt(n)}catch{}}}catch{}try{return Gt(Le(n),{recursive:!0}),Vt(n,`${t}
4
+ `,{encoding:"utf8",flag:"wx"}),!0}catch(r){if(tn(r))return!1;let o=r instanceof Error?r.message:String(r);return m(`WARN: cloud bootstrap claim failed open: ${o}`),!0}}function Qt(e){if(e)try{jt(Wt(e))}catch{}}function qt(e,t){let r=K(e)?.platform_agent_ids?.[t];return typeof r=="string"&&r.length>0?r:void 0}function en(e,t,n){if(!n)return;let r=K(e);if(!r||r.platform_agent_ids?.[t]===n)return;let o={installation_id:r.installation_id,platform_agent_ids:{...r.platform_agent_ids,[t]:n},...r.operator_identity_hash?{operator_identity_hash:r.operator_identity_hash}:{},...r.operator_identity_sent_at?{operator_identity_sent_at:r.operator_identity_sent_at}:{}};try{B(e,`${JSON.stringify(o,null,2)}
5
+ `)}catch(s){let i=s instanceof Error?s.message:String(s);m(`WARN: platform_agent_id cache write failed open: ${i}`)}}function tn(e){return e instanceof Error&&"code"in e&&e.code==="EEXIST"}function wr(e,t){Gt(Le(e),{recursive:!0}),Vt(e,`${JSON.stringify(t,null,2)}
6
+ `,{encoding:"utf8",flag:"wx"})}function Ft(e,t){try{return wr(e,t),t}catch(n){if(!tn(n))throw n;return K(e)}}async function nn(e,t={}){let n=t.home??Me(),r=t.env??process.env,o=await xr(e),s=Ar(n),i=K(s);if(i)return{installationId:i.installation_id,storePath:s,repoKey:o};let a=Ht(t.overrideId,r),c=Ft(s,{installation_id:a});if(c)return{installationId:c.installation_id,storePath:s,repoKey:o};let l=Ht(void 0,r),u=Ft(s,{installation_id:l===a?Jt():l});if(u)return{installationId:u.installation_id,storePath:s,repoKey:o};throw new Error(`Failed to create installation record at ${s}`)}var Nr={claude:".claude",cursor:".cursor",codex:".codex"};function te(e){let n=e.replace(/^\/+|\/+$/g,"").toLowerCase().split("/").filter(Boolean);return n.length<2?"":n.join("/")}function vr(e){if(!e)return"";let t=e.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1");t=t.replace(/\.git$/i,"");let n=t.match(/^git@[^:]+:(.+)$/);if(n?.[1])return te(n[1]);let r=t.match(/^ssh:\/\/[^/]+\/(.+)$/i);if(r?.[1])return te(r[1]);t=t.replace(/^https:\/\//i,""),t=t.replace(/^http:\/\//i,""),t=t.replace(/^ssh:\/\//i,"");let o=t.match(/^[^/]+\/(.+)$/);return o?.[1]?te(o[1]):te(t)}async function ne(e=process.cwd()){let t=await L("git",["rev-parse","--is-inside-work-tree"],2e3,{cwd:e});if(!t.ok||t.stdout!=="true")return null;let[n,r,o,s]=await Promise.all([L("git",["remote","get-url","origin"],2e3,{cwd:e}),L("git",["branch","--show-current"],2e3,{cwd:e}),L("git",["rev-parse","HEAD"],2e3,{cwd:e}),L("git",["status","--porcelain"],2e3,{cwd:e})]),i=n.ok?n.stdout:null;return{remote:i===null?null:i.replace(/^([a-z]+:\/\/)[^/@]+@/i,"$1"),branch:r.ok?r.stdout:null,head:o.ok?o.stdout:null,dirty:s.ok?s.stdout.length>0:null}}async function rn(e,t,n,r=process.cwd(),o,s,i){if(t)return t;let a=Nr[n];if(!a)return"";let c=zt(n,e.scope_path,i);if(s){let h=qt(s,c);if(h)return h}let l=o??await ne(r),u=l?.remote?vr(l.remote):"";if(u||(u=te(process.env.GITHUB_REPOSITORY??"")),!u)return"";let d=e.scope_path??"",g=d?`${d}/`:"",f=`${u}:${g}${a}`;return s&&en(s,c,f),f}import{existsSync as Mr,readFileSync as Lr}from"node:fs";import{hostname as Pr,userInfo as Dr}from"node:os";function me(e){if(e===void 0||e==="")return!1;let t=e.trim().toLowerCase();return t!=="0"&&t!=="false"&&t!=="no"}var Hr=["GITLAB_CI","CIRCLECI","BUILDKITE","TF_BUILD","JENKINS_URL","JENKINS_HOME","CODEBUILD_BUILD_ID","DRONE","DRONE_BUILD_NUMBER","TEAMCITY_VERSION","TRAVIS","APPVEYOR","BITBUCKET_BUILD_NUMBER"];function Fr(){return Hr.some(e=>!!E(e))}function Br(){if(E("KUBERNETES_SERVICE_HOST")||me(E("REMOTE_CONTAINERS"))||me(E("DEVCONTAINER")))return!0;try{if(Mr("/.dockerenv")||Lr("/proc/1/environ","utf8").includes("container="))return!0}catch{}return!1}function Fe(){if(E("GITHUB_ACTIONS"))return"github_actions";if(me(E("CLAUDE_CODE_REMOTE")))return"claude_remote";if(me(E("CURSOR_AGENT")))return"cursor_cloud";if(E("CODESPACES")||E("CODESPACE_NAME"))return"codespaces";if(Fr())return"managed";let e=E("CI");return e&&e!=="false"&&e!=="0"?"managed":Br()?"container":process.stdin.isTTY||process.stdout.isTTY||E("TERM")?"interactive":"cron"}async function Be(){return await R("systemd-detect-virt",[],1e3)}function $r(e=process.env,t=Dr){for(let n of["USER","LOGNAME","USERNAME"]){let r=e[n];if(typeof r=="string"){let o=r.trim();if(o.length>0)return o}}try{return t().username??""}catch{return""}}async function $e(){let e=process.platform==="darwin"?"Darwin":process.platform==="win32"?"Windows_NT":"Linux",t="";if(process.platform==="darwin")t=await R("sw_vers",["-productVersion"],1e3);else if(process.platform==="linux"){try{let{readFileSync:s}=await import("node:fs"),i=s("/etc/os-release","utf8"),a=i.match(/^PRETTY_NAME="?([^"\n]+)"?/m)?.[1],c=i.match(/^VERSION_ID="?([^"\n]+)"?/m)?.[1];t=a??c??""}catch{t=await R("lsb_release",["-sd"],1e3).then(s=>s.replace(/^"|"$/g,""))}t||(t=await R("uname",["-r"],1e3))}else t=await R("ver",[],1e3);let n=$r(),r=(process.env.SHELL??"").split(/[/\\]/).pop()??"",o="";try{o=await R("tty",[],500),o.includes("not a tty")&&(o="")}catch{o=""}return{os:e,os_version:t||null,user:n||null,shell:r||null,tty:o||null}}function Ge(){return Pr()}import{existsSync as Gr,readFileSync as Kr}from"node:fs";import{homedir as on}from"node:os";import{join as jr}from"node:path";var Vr="cloud-cache.json",zr=1440*60*1e3,Wr=900*1e3;function Jr(e=on()){return jr(De(e),Vr)}function Yr(e){if(!Gr(e))return;let t=O(Kr(e,"utf8"),{});if(!(typeof t.context!="string"||typeof t.probed_at!="number"||t.result!==null&&t.result!==void 0&&typeof t.result!="object"))return{context:t.context,probed_at:t.probed_at,result:t.result??null}}function Xr(e,t){try{B(e,`${JSON.stringify(t)}
7
+ `)}catch(n){let r=n instanceof Error?n.message:String(n);m(`WARN: cloud cache write failed open: ${r}`)}}function Zr(e,t,n){if(!e||e.context!==t)return!1;let r=e.result===null?Wr:zr;return n-e.probed_at<r}async function Qr(e){let t=await fetch("http://169.254.169.254/latest/api/token",{method:"PUT",headers:{"X-aws-ec2-metadata-token-ttl-seconds":"60"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=(await t.text()).trim();if(!n)return;let r={"X-aws-ec2-metadata-token":n},[o,s]=await Promise.all([fetch("http://169.254.169.254/latest/meta-data/placement/region",{headers:r,signal:AbortSignal.timeout(e)}).catch(()=>{}),fetch("http://169.254.169.254/latest/meta-data/instance-id",{headers:r,signal:AbortSignal.timeout(e)}).catch(()=>{})]);if(!o?.ok&&!s?.ok)return;let i=o?.ok?(await o.text()).trim():"",a=s?.ok?(await s.text()).trim():"";if(!(!i&&!a))return{provider:"aws",region:i,instance_id:a}}async function qr(e){let t=await fetch("http://metadata.google.internal/computeMetadata/v1/instance/?recursive=true",{headers:{"Metadata-Flavor":"Google"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=await t.json(),r=typeof n.zone=="string"?n.zone.split("/").pop()??"":"",o=n.id===void 0?"":String(n.id);if(!(!r&&!o))return{provider:"gcp",region:r,instance_id:o}}async function eo(e){let t=await fetch("http://169.254.169.254/metadata/instance?api-version=2021-02-01",{headers:{Metadata:"true"},signal:AbortSignal.timeout(e)}).catch(()=>{});if(!t?.ok)return;let n=await t.json(),r=n.compute?.location??"",o=n.compute?.vmId??"";if(!(!r&&!o))return{provider:"azure",region:r,instance_id:o}}async function to(e){let t=await Promise.allSettled([Qr(e),qr(e),eo(e)]);for(let n of t)if(n.status==="fulfilled"&&n.value)return n.value;return null}async function Ke(e,t){if(e==="interactive")return null;let n=t?.home??on(),r=t?.timeoutMs??1e3,o=t?.nowMs??Date.now(),s=Jr(n),i=Yr(s);if(Zr(i,e,o))return i.result;let a=await to(r);return Xr(s,{context:e,probed_at:o,result:a}),a}import{existsSync as no}from"node:fs";import{homedir as ro}from"node:os";import{join as je}from"node:path";function Ve(e,t,n){if(!no(e))return;let r=W(e,{});for(let o of Object.keys(r.mcpServers??{}))n.set(o,{name:o,source:t})}async function ze(e,t=process.cwd(),n="claude",r=ro()){let o=new Map;for(let s of e.mcp_servers??[])s.name&&o.set(s.name,{name:s.name,source:"manifest"});return n==="claude"&&Ve(je(r,".claude.json"),"claude_json_user",o),Ve(je(t,".mcp.json"),"mcp_json",o),Ve(je(t,".cursor/mcp.json"),"cursor_mcp",o),[...o.values()]}var oo=["CI","GITHUB_ACTIONS","GITLAB_CI","CIRCLECI","BUILDKITE","TF_BUILD","JENKINS_URL","JENKINS_HOME","CODEBUILD_BUILD_ID","DRONE","DRONE_BUILD_NUMBER","TEAMCITY_VERSION","TRAVIS","APPVEYOR","BITBUCKET_BUILD_NUMBER","KUBERNETES_SERVICE_HOST","REMOTE_CONTAINERS","DEVCONTAINER","GITHUB_REPOSITORY","GITHUB_REPOSITORY_ID","GITHUB_REF","GITHUB_SHA","GITHUB_RUN_ID","GITHUB_WORKFLOW","GITHUB_ACTOR","GITHUB_TRIGGERING_ACTOR","GITHUB_ACTOR_ID","GITHUB_USER","GITLAB_USER_LOGIN","GITLAB_USER_NAME","GITLAB_USER_EMAIL","BUILD_REQUESTEDFOR","BUILD_REQUESTEDFOREMAIL","BUILDKITE_BUILD_CREATOR","BUILDKITE_BUILD_CREATOR_EMAIL","BUILD_USER","BUILD_USER_ID","BUILD_USER_EMAIL","CHANGE_AUTHOR","CHANGE_AUTHOR_EMAIL","CIRCLE_USERNAME","CODEBUILD_INITIATOR","DRONE_COMMIT_AUTHOR","DRONE_COMMIT_AUTHOR_NAME","DRONE_COMMIT_AUTHOR_EMAIL","EV_AI_HOOK_OPERATOR_NAME","EV_AI_HOOK_OPERATOR_EMAIL","GIT_AUTHOR_NAME","GIT_AUTHOR_EMAIL","GIT_COMMITTER_NAME","GIT_COMMITTER_EMAIL","EMAIL","RUNNER_OS","RUNNER_ARCH","NODE_ENV","TERM_PROGRAM","CLAUDE_CODE_REMOTE","CLAUDE_CODE_REMOTE_SESSION_ID","CURSOR_AGENT","CODESPACES","CODESPACE_NAME","ANTHROPIC_BASE_URL","OPENAI_BASE_URL","OPENAI_API_BASE","AZURE_OPENAI_ENDPOINT","GOOGLE_GEMINI_BASE_URL","GEMINI_API_BASE","CLAUDE_CODE_USE_BEDROCK","CLAUDE_CODE_USE_VERTEX"],so=new Set(["key","api-key","api_key","apikey","token","sig","signature","access_token","password","pwd","secret","client_secret"]);function io(e){try{let t=new URL(e);(t.username||t.password)&&(t.username="",t.password="");for(let[n]of t.searchParams)so.has(n.toLowerCase())&&t.searchParams.set(n,"[redacted]");return t.toString()}catch{return e}}function We(e=process.env){return oo.map(t=>Object.prototype.hasOwnProperty.call(e,t)?{name:t,present:!0,value:io(e[t]??"")}:{name:t,present:!1})}import{createHash as ao}from"node:crypto";function I(e){return ao("sha256").update(e).digest("hex").slice(0,16)}function P(e,t){return`${e}\0${t}`}function sn(e){let t=e.indexOf("\0");return t<=0?null:{path:e.slice(0,t),name:e.slice(t+1)}}function Je(e){let n=[...e].sort((r,o)=>{let s=r.path.localeCompare(o.path);return s!==0?s:r.name.localeCompare(o.name)}).map(r=>`${r.path}|${r.name}|${r.content_hash}`).join(`
8
+ `);return I(n)}function co(e,t,n="git_config",r=null){return I(`${e??""}|${t??""}|${r??""}|${n}`)}function lo(e){let t=null,n=null;for(let r of e.split(`
9
+ `)){let o=r.trim();if(!o)continue;let s=o.indexOf(" ");if(s<=0)continue;let i=o.slice(0,s).toLowerCase(),a=o.slice(s+1).trim();a&&(i==="user.name"?t=a:i==="user.email"&&(n=a))}return{git_user_name:t,git_user_email:n,platform_login:null}}async function uo(e,t=R){let n=await t("git",["config","--get-regexp","^user\\.(name|email)$"],2e3,{cwd:e});return lo(n)}function po(e=process.env){let t=_(e.GIT_AUTHOR_NAME),n=_(e.GIT_AUTHOR_EMAIL);if(t||n)return{git_user_name:t,git_user_email:n,platform_login:null,identity_source:"git_env"};let r=_(e.GIT_COMMITTER_NAME),o=_(e.GIT_COMMITTER_EMAIL);if(r||o)return{git_user_name:r,git_user_email:o,platform_login:null,identity_source:"git_env"};let s=_(e.EMAIL);return s?{git_user_name:null,git_user_email:s,platform_login:null,identity_source:"git_env"}:null}async function fo(e,t=R){let n=await t("git",["log","-1","--format=%an%x00%ae"],2e3,{cwd:e});if(!n)return null;let r=n.indexOf("\0"),o=(r>=0?n.slice(0,r):n).trim(),s=(r>=0?n.slice(r+1):"").trim();return!o&&!s?null:{git_user_name:o||null,git_user_email:s||null,platform_login:null,identity_source:"git_log"}}function D(e,t,n,r=null){return!e&&!t&&!r?null:{git_user_name:e,git_user_email:t,platform_login:r,identity_source:n}}function mo(e=process.env){let t=D(_(e.EV_AI_HOOK_OPERATOR_NAME),_(e.EV_AI_HOOK_OPERATOR_EMAIL),"configured");if(t)return t;let n=_(e.GITHUB_ACTOR)??_(e.GITHUB_TRIGGERING_ACTOR)??_(e.GITHUB_USER),r=D(n,null,"github",n);if(r)return r;let o=_(e.GITLAB_USER_LOGIN),s=D(_(e.GITLAB_USER_NAME)??o,_(e.GITLAB_USER_EMAIL),"gitlab",o);if(s)return s;let i=D(_(e.BUILD_REQUESTEDFOR),_(e.BUILD_REQUESTEDFOREMAIL),"azure_devops");if(i)return i;let a=D(_(e.BUILDKITE_BUILD_CREATOR),_(e.BUILDKITE_BUILD_CREATOR_EMAIL),"buildkite");if(a)return a;let c=D(_(e.BUILD_USER)??_(e.CHANGE_AUTHOR),_(e.BUILD_USER_EMAIL)??_(e.CHANGE_AUTHOR_EMAIL),"jenkins",_(e.BUILD_USER_ID));if(c)return c;let l=_(e.CIRCLE_USERNAME),u=D(l,null,"circleci",l);if(u)return u;let d=_(e.CODEBUILD_INITIATOR),g=D(d,null,"codebuild",d);if(g)return g;let f=D(_(e.DRONE_COMMIT_AUTHOR)??_(e.DRONE_COMMIT_AUTHOR_NAME),_(e.DRONE_COMMIT_AUTHOR_EMAIL),"drone",_(e.DRONE_COMMIT_AUTHOR));return f||(an(e.CLAUDE_CODE_REMOTE)||an(e.CURSOR_AGENT)?{git_user_name:null,git_user_email:null,platform_login:null,identity_source:"cloud"}:null)}function Ye(e){return!!((e.git_user_name??e.git_user_email)&&!ho(e.git_user_name,e.git_user_email))}function _(e){if(e===void 0)return null;let t=e.trim();return t.length>0?t:null}function an(e){if(e===void 0||e==="")return!1;let t=e.trim().toLowerCase();return t!=="0"&&t!=="false"&&t!=="no"}var go=new Set(["action@github.com","noreply@github.com","noreply@anthropic.com","cursoragent@cursor.com"]),_o=new Set(["github-actions","github actions","dependabot","renovate","cursoragent","cursor agent"]);function ho(e,t){let n=(e??"").trim().toLowerCase(),r=(t??"").trim().toLowerCase();if(!n&&!r)return!1;if(n.includes("[bot]")||_o.has(n)||r.includes("[bot]")||go.has(r))return!0;if(r.endsWith("@users.noreply.github.com")){let o=r.slice(0,r.indexOf("@")),s=o.includes("+")?o.slice(o.indexOf("+")+1):o;if(s.endsWith("bot")||s.includes("[bot]"))return!0}return!1}async function Eo(e,t=R,n=process.env){let r=await uo(e,t);if(Ye(r))return{...r,identity_source:"git_config"};let o=po(n);if(o&&Ye(o))return o;let s=mo(n);if(s&&(s.git_user_name||s.git_user_email||s.platform_login))return s;let i=await fo(e,t);return i&&Ye(i)?i:s||(r.git_user_name||r.git_user_email?{...r,identity_source:"git_config"}:o||i||{git_user_name:null,git_user_email:null,platform_login:null,identity_source:"git_config"})}async function ge(e){let{gitRoot:t,installationStorePath:n,forceResend:r}=e,o=e.exec??R,s=e.env??process.env,i=await Eo(t,o,s),a=co(i.git_user_name,i.git_user_email,i.identity_source,i.platform_login),l=(n?He(n):void 0)?.operator_identity_hash;if(!(r||l!==void 0&&l!==a||!l))return{commit:()=>{}};let f=n;return{operator:i,commit:()=>{f&&Xt(f,a,de())}}}function Xe(e){return e?!He(e)?.operator_identity_hash:!0}function cn(e){return!0}import{existsSync as $o,readFileSync as Go}from"node:fs";import{homedir as An}from"node:os";import{join as w}from"node:path";import{basename as Fo,join as J}from"node:path";import{existsSync as ln,readdirSync as So}from"node:fs";import{basename as yo,dirname as Io,relative as Ro}from"node:path";var _e=class{constructor(t){this.home=t}components=[];truncated=!1;pluginExpandRemaining;homeRel(t){let n=Ro(this.home,t).replace(/\\/g,"/");if(!n||n.startsWith("..")){let r=Io(t);return`external/${I(r)}/${yo(t)}`}return n}get atGlobalCap(){return this.truncated||this.components.length>=G}get pluginBudgetSpent(){return this.pluginExpandRemaining!==void 0&&this.pluginExpandRemaining<=0}readEntries(t){if(!ln(t))return[];try{return So(t,{withFileTypes:!0})}catch{return[]}}readJson(t,n){if(ln(t))return W(t,n)}push(t){return this.components.length>=G?(this.truncated=!0,!1):this.pluginExpandRemaining!==void 0&&this.pluginExpandRemaining<=0?!1:(this.pluginExpandRemaining!==void 0&&(this.pluginExpandRemaining-=1),this.components.push(t),!0)}withPluginExpandCap(t,n){let r=this.pluginExpandRemaining;this.pluginExpandRemaining=t;try{let o=n(),s=t-(this.pluginExpandRemaining??0);return{result:o,expanded:s}}finally{this.pluginExpandRemaining=r}}};import{existsSync as Ze,readFileSync as Co,statSync as To}from"node:fs";import{basename as dn,join as re,relative as pn}from"node:path";var Qe=2e4,Ao=4;function ko(e){return e.length<=Qe?e:`${e.slice(0,Qe-1)}\u2026`}function Oo(e){try{let t=Co(e),n=t.toString("utf8");return{hash:I(t),length:t.length,text:ko(n)}}catch{return null}}var un={HOOK:"EVENT",COMMAND:"EXPLICIT_INVOCATION",MEMORY:void 0,MCP_SERVER:void 0,PLUGIN:void 0,SKILL:"UNSPECIFIED",RULE:"UNSPECIFIED",SUBAGENT:"UNSPECIFIED"};function xo(e){return e in un?un[e]:"UNSPECIFIED"}function he(e,t){let n=Oo(t.absolutePath);if(!n)return!1;let r=t.name??dn(t.absolutePath).replace(/\.(md|mdc|toml)$/i,""),o={kind:t.kind,name:r,path:e.homeRel(t.absolutePath),text:n.text,content_hash:n.hash,content_length:n.length,origin:t.origin,enabled:t.enabled},s=xo(t.kind);return s&&(o.trigger=s),e.push(o)}function Uo(e,t,n){let r=pn(e,t).replace(/\\/g,"/");return!r||r.startsWith("..")?dn(t).replace(/\.(md|mdc|toml)$/i,""):n?r.replace(/\.(md|mdc|toml)$/i,""):r}function j(e,t){let{dir:n,kind:r,origin:o,enabled:s,nested:i,extensions:a}=t;qe(e,{walkRoot:n,currentDir:n,depth:0,kind:r,origin:o,enabled:s,nested:i,extensions:a})}function qe(e,t){let{walkRoot:n,currentDir:r,depth:o,kind:s,origin:i,enabled:a,nested:c,extensions:l}=t;if(!(o>Ao))for(let u of e.readEntries(r)){if(e.atGlobalCap){e.truncated=!0;return}if(e.pluginBudgetSpent)return;if(c){if(!u.isDirectory())continue;let f=re(r,u.name,c);if(Ze(f)){let h=pn(n,re(r,u.name)).replace(/\\/g,"/");he(e,{absolutePath:f,kind:s,origin:i,enabled:a,name:h||u.name});continue}qe(e,{walkRoot:n,currentDir:re(r,u.name),depth:o+1,kind:s,origin:i,enabled:a,nested:c,extensions:l});continue}if(u.isDirectory()){qe(e,{walkRoot:n,currentDir:re(r,u.name),depth:o+1,kind:s,origin:i,enabled:a,nested:c,extensions:l});continue}if(!u.isFile()||!l)continue;let d=u.name.toLowerCase();if(!l.some(f=>d.endsWith(f)))continue;let g=re(r,u.name);he(e,{absolutePath:g,kind:s,origin:i,enabled:a,name:Uo(n,g,!0)})}}function fn(e){for(let t of e)if(Ze(t))try{if(To(t).size>0)return t}catch{continue}return e.find(t=>Ze(t))}function bo(e){if(e.prompt||e.type==="prompt")return"prompt";let t=e.command??e.bash??e.powershell??"";return/\bnpx\b/i.test(t)?"npx":/\.(sh|bash|zsh|js|mjs|cjs|ts|py)(\s|$|"|')/i.test(t)||/^(\.\/|~\/|\/|[A-Za-z]:[\\/])/.test(t.trim())?"script":"inline"}function wo(e){return Array.isArray(e.hooks)&&e.hooks.length>0?e.hooks:[{type:e.type,command:e.command,bash:e.bash,powershell:e.powershell,prompt:e.prompt}]}function No(e,t,n,r){let o=e.homeRel(t);for(let[s,i]of Object.entries(n))if(!(!Array.isArray(i)||e.truncated))for(let a of i){if(!a||typeof a!="object"||e.truncated)continue;let c=a;for(let l of wo(c)){if(e.truncated)return;let u=l.command??l.bash??l.prompt??l.powershell??c.powershell??"",d=bo({type:l.type??c.type,command:l.command??c.command,bash:l.bash??c.bash,powershell:l.powershell??c.powershell,prompt:l.prompt??c.prompt}),g=typeof c.matcher=="string"?c.matcher:"",f=I(u),h=g?`${s}:${g}:${d}:${f}`:`${s}:${d}:${f}`,x=`${s}|${g}|${d}|${u}`;e.push({kind:"HOOK",name:h,path:o,content_hash:I(x),origin:r,enabled:!0,trigger:"EVENT",attributes:{event:s,...g?{matcher:g}:{},action_kind:d,action_hash:f}})}}}function oe(e,t,n){let r=e.readJson(t,{});!r?.hooks||typeof r.hooks!="object"||No(e,t,r.hooks,n)}var mn={claude:{skillRoots:[".claude/skills"],dirs:[{dir:".claude/agents",kind:"SUBAGENT",extensions:[".md"]},{dir:".claude/commands",kind:"COMMAND",extensions:[".md"]}],memory:[".claude/CLAUDE.md"],hooks:[".claude/settings.json"],mcpJson:[".claude.json"],plugins:"claude"},cursor:{skillRoots:[".cursor/skills",".cursor/skills-cursor"],dirs:[{dir:".cursor/agents",kind:"SUBAGENT",extensions:[".md"]},{dir:".cursor/commands",kind:"COMMAND",extensions:[".md"]},{dir:".cursor/rules",kind:"RULE",extensions:[".mdc",".md"]}],memory:[".cursor/AGENTS.md"],hooks:[".cursor/hooks.json"],mcpJson:[".cursor/mcp.json"],plugins:"cursor"},codex:{skillRoots:[".agents/skills",".codex/skills"],dirs:[{dir:".codex/agents",kind:"SUBAGENT",extensions:[".toml",".md"]},{dir:".codex/prompts",kind:"COMMAND",extensions:[".md"]}],memory:[".codex/AGENTS.override.md",".codex/AGENTS.md"],hooks:[".codex/hooks.json"],mcpToml:[".codex/config.toml"]}};import{existsSync as vo,readFileSync as Mo}from"node:fs";function Lo(e){if(!e||typeof e!="object"||Array.isArray(e))return"unknown";let t=e;return typeof t.type=="string"&&t.type.length>0?t.type:typeof t.url=="string"?"http":typeof t.command=="string"?"stdio":"unknown"}function gn(e,t,n){let o=e.readJson(t,{})?.mcpServers;if(!o||typeof o!="object")return;let s=e.homeRel(t);for(let[i,a]of Object.entries(o)){if(e.truncated)return;let c=Lo(a);e.push({kind:"MCP_SERVER",name:i,path:s,content_hash:I(`${i}|${c}`),origin:n,enabled:!0,attributes:{transport:c}})}}function _n(e,t,n){if(!vo(t))return;let r;try{r=Mo(t,"utf8")}catch{return}let o=e.homeRel(t),s=/^\[mcp_servers(?:\.(\w+)|\."([^"]+)"|\.'([^']+)')\]\s*$/gm,i;for(;(i=s.exec(r))!==null;){if(e.truncated)return;let a=i[1]??i[2]??i[3];if(!a)continue;let c=r.slice(i.index+i[0].length),l=c.search(/^\[/m),u=l===-1?c:c.slice(0,l),d="unknown";/^\s*url\s*=/m.test(u)?d="http":/^\s*command\s*=/m.test(u)&&(d="stdio"),e.push({kind:"MCP_SERVER",name:a,path:o,content_hash:I(`${a}|${d}`),origin:n,enabled:!0,attributes:{transport:d}})}}import{existsSync as Po,readdirSync as Do}from"node:fs";import{join as T}from"node:path";var hn=50;function et(e,t,n,r){if(!Po(t))return{componentCount:0,expandTruncated:!1};let o=e.components.length,{expanded:s}=e.withPluginExpandCap(hn,()=>{j(e,{dir:T(t,"skills"),kind:"SKILL",origin:n,enabled:r,nested:"SKILL.md"}),j(e,{dir:T(t,"commands"),kind:"COMMAND",origin:n,enabled:r,extensions:[".md"]}),j(e,{dir:T(t,"agents"),kind:"SUBAGENT",origin:n,enabled:r,extensions:[".md"]})});oe(e,T(t,"hooks","hooks.json"),n),oe(e,T(t,"hooks.json"),n);let i=e.components.length-o,a=s>=hn;return{componentCount:i,expandTruncated:a}}function tt(e,t){e.push({kind:"PLUGIN",name:t.pluginKey,path:t.rowPath,content_hash:t.contentHash,origin:"user",enabled:t.enabled,attributes:{...t.marketplace?{marketplace:t.marketplace}:{},...t.version?{version:t.version}:{},scope:t.scope,component_count:t.componentCount,...t.expandTruncated?{expand_truncated:!0}:{}}})}function En(e){let t=T(e.home,".claude/plugins/installed_plugins.json"),n=e.readJson(t,{});if(!n)return;let r=n.plugins??{},s=e.readJson(T(e.home,".claude/settings.json"),{})?.enabledPlugins??{},i=e.homeRel(t);for(let[a,c]of Object.entries(r)){if(e.truncated)return;let l=Array.isArray(c)?c:[c],u=l[0]??{},d=s[a]===!0,g=a.includes("@")?a.split("@").slice(1).join("@"):"",f=typeof u.version=="string"?u.version:"",h=typeof u.scope=="string"?u.scope:"user",x=`plugin:${a}`,v=0,C=!1;for(let U of l)if(typeof U.installPath=="string"&&U.installPath.length>0){let F=et(e,U.installPath,x,d);v+=F.componentCount,C=C||F.expandTruncated}tt(e,{pluginKey:a,rowPath:i,enabled:d,scope:h,version:f||void 0,marketplace:g||void 0,componentCount:v,expandTruncated:C,contentHash:I(`${a}|${f}|${h}|${d}|${v}`)})}}function Ho(e){let t=e,n="";try{let r=Do(e,{withFileTypes:!0}).filter(o=>o.isDirectory()).map(o=>o.name);if(r.length===1&&r[0])t=T(e,r[0]),n=r[0];else if(r.length>1){let o=[...r].sort(),s=o[o.length-1];s&&(t=T(e,s),n=s)}}catch{}return{installPath:t,version:n}}function Sn(e){let t=[{base:T(e.home,".cursor/plugins/local"),scope:"local"},{base:T(e.home,".cursor/plugins/cache"),scope:"cache"}];for(let{base:n,scope:r}of t)if(!e.truncated)for(let o of e.readEntries(n)){if(!o.isDirectory()||e.truncated)continue;if(r==="local"){let i=o.name,a=T(n,o.name),c=`plugin:${i}`,{componentCount:l,expandTruncated:u}=et(e,a,c,!0);tt(e,{pluginKey:i,rowPath:e.homeRel(a),enabled:!0,scope:"local",componentCount:l,expandTruncated:u,contentHash:I(`${i}|local|${l}`)});continue}let s=o.name;for(let i of e.readEntries(T(n,s))){if(!i.isDirectory()||e.truncated)continue;let a=T(n,s,i.name),{installPath:c,version:l}=Ho(a),u=`${i.name}@${s}`,d=`plugin:${u}`,{componentCount:g,expandTruncated:f}=et(e,c,d,!0);tt(e,{pluginKey:u,rowPath:e.homeRel(c),enabled:!0,scope:"cache",version:l||void 0,marketplace:s,componentCount:g,expandTruncated:f,contentHash:I(`${u}|${l}|${g}`)})}}}function nt(e,t){let n=mn[e],r=new _e(t),o="user";if(!n)return{components:[],truncated:!1};for(let i of n.skillRoots)j(r,{dir:J(t,i),kind:"SKILL",origin:o,enabled:!0,nested:"SKILL.md"});for(let i of n.dirs)j(r,{dir:J(t,i.dir),kind:i.kind,origin:o,enabled:!0,extensions:i.extensions});let s=fn(n.memory.map(i=>J(t,i)));s&&he(r,{absolutePath:s,kind:"MEMORY",origin:o,enabled:!0,name:Fo(s)});for(let i of n.hooks)oe(r,J(t,i),o);for(let i of n.mcpJson??[])gn(r,J(t,i),o);for(let i of n.mcpToml??[])_n(r,J(t,i),o);return n.plugins==="claude"?En(r):n.plugins==="cursor"&&Sn(r),{components:r.components,truncated:r.truncated}}function rt(e,t,n={}){let r=n.truncated===!0,o=Je(e),s=new Set(e.map(u=>P(u.path,u.name)));if(n.forceFull===!0||t===void 0)return{hash:o,count:e.length,truncated:r,full:!0,upserts:e,removed:[],unchanged:!1};let a=[],c=t;for(let u of e){let d=P(u.path,u.name);c[d]!==u.content_hash&&a.push(u)}let l=[];if(!r){for(let u of Object.keys(c))if(!s.has(u)){let d=sn(u);d&&l.push(d)}}return{hash:o,count:e.length,truncated:r,full:!1,upserts:a,removed:l,unchanged:a.length===0&&l.length===0}}var In=3e5,Bo=new Set(["HOOK","MCP_SERVER","PLUGIN"]);function ot(e,t,n){let r=new Set(t.map(s=>P(s.path,s.name))),o=[];for(let s of e)s.text!==void 0&&(n.has(s.content_hash)||r.has(P(s.path,s.name))||o.push(s));return o}function st(e,t,n){let r=new Set(e);for(let s of t)r.add(s);let o=new Set(n.map(s=>s.content_hash));return[...r].filter(s=>o.has(s))}function yn(e){return Buffer.byteLength(JSON.stringify(e),"utf8")}function Rn(e){if(e.text===void 0)return e;let{text:t,...n}=e;return n}function it(e,t=In){let n=[],r=[];for(let u of e)Bo.has(u.kind)?n.push(u):r.push(u);r.sort((u,d)=>(u.text?.length??0)-(d.text?.length??0));let o=[...n,...r],s=[],i=2,a=0,c=0,l=[];for(let u of o){let d=s.length>0?1:0,g=yn(u)+d;if(i+g<=t){s.push(u),i+=g,u.text!==void 0&&l.push(u.content_hash);continue}if(u.text!==void 0){let f=Rn(u),h=yn(f)+d;if(i+h<=t){s.push(f),i+=h,a+=1;continue}}c+=1}return{components:s,textDeferredCount:a,droppedCount:c,textHashesSent:l}}function at(e,t){return t.size===0?e:e.map(n=>n.text===void 0||!t.has(n.content_hash)?n:Rn(n))}var Ko={claude:{skills:".claude/skills",subagents:".claude/agents",commands:".claude/commands",memory:".claude/CLAUDE.md",settings:".claude/settings.json"},cursor:{skills:[".cursor/skills",".cursor/skills-cursor"],subagents:".cursor/agents",commands:".cursor/commands",rules:".cursor/rules",mcp:".cursor/mcp.json"},codex:{skills:[".agents/skills",".codex/skills"],subagents:".codex/agents",commands:".codex/prompts",memory:".codex/AGENTS.md",settings:".codex/config.toml"}},jo=200,Cn=200,Vo=["allow","deny","ask"],zo=/(?<=^|[\s(,=:])(?:~|[A-Za-z]:)?[\\/][^\s,)]+/g,ct="<path>",Wo=new RegExp(`${ct}(?:\\s+[A-Za-z.][^\\s,)]*[\\\\/][^\\s,)]*)+`,"g");function Jo(e){let t=e.replace(zo,ct).replace(Wo,ct);return t.length>Cn?`${t.slice(0,Cn)}...`:t}function Tn(e){let t=W(e,{}),n=[];for(let r of Vo)for(let o of t.permissions?.[r]??[])typeof o=="string"&&o.length>0&&n.push({key:Jo(o),mode:r});return{model:t.model??"",permissionKeys:n}}var Yo=10,Xo=840*60*1e3,Zo="self-config-cache.json";function lt(){return E("EV_AI_HOOK_USER_SPEC")?.toLowerCase()==="off"}function Qo(e,t=Date.now()){return e===void 0||!Number.isFinite(e)?!0:t-e>=Xo}var qo={claude:["claude"],cursor:["agent","cursor-agent"],codex:["codex"]};async function es(e,t=R){let n=qo[e];if(!n||n.length===0)return null;let r=async o=>{let s=n[o];if(s===void 0)return null;let a=((await t(s,["--version"],2e3)).split(`
10
+ `)[0]??"").trim();return a||r(o+1)};return r(0)}function ts(e=An()){return w(e,".ev-ai","agent-hook",Zo)}function ns(e){let n=[...e].sort((r,o)=>r.name.localeCompare(o.name)).map(r=>`${r.name}:${r.size}`).join(`
11
+ `);return I(n)}function Ee(e,t,n=!1){let r=ns(e),o=e.length;return t===r?n?{hash:r,count:o,truncated:n}:{hash:r,count:o}:n?{hash:r,count:o,entries:e,truncated:n}:{hash:r,count:o,entries:e}}function rs(e){return $o(e)?O(Go(e,"utf8"),{}):{}}function os(e,t){try{B(e,`${JSON.stringify(t)}
12
+ `)}catch(n){let r=n instanceof Error?n.message:String(n);m(`WARN: self-config cache write failed open: ${r}`)}}function ss(e,t,n,r){let o={...e,send_count:n};for(let s of Object.keys(t)){let i=t[s];i.entries!==void 0&&(o[s]=i.hash)}return r&&(o.user_spec_collected_at_ms=r.collectedAtMs,r.included&&(o.user_spec=r.hash,o.user_spec_components=r.componentHashes),o.user_spec_text_hashes=r.textHashes),o}async function kn(e,t=process.cwd(),n=An(),r={}){let o=e==="claude",s=r.gitRoot??t,i=await es(e),a="",c=[];if(o){let b=Tn(w(n,".claude/settings.json")),M=Tn(w(t,".claude/settings.local.json"));a=M.model||b.model,c=[...b.permissionKeys,...M.permissionKeys].slice(0,jo)}let l=Ko[e]??{},u={present:!1,size:0},d=b=>{let M=Array.isArray(b)?b:b?[b]:[],S=[],H=!1;for(let Ae of M){let k=q(w(n,Ae));if(S=S.concat(k.entries),H=H||k.truncated,S.length>=G){S=S.slice(0,G),H=!0;break}}return{entries:S,truncated:H}},g=ts(n),f=rs(g),h=f[e]??{},x=(h.send_count??0)+1,v=x>0&&x%Yo===0,C=b=>v?void 0:h[b],U=d(l.skills),F=l.subagents?q(w(n,l.subagents)):{entries:[],truncated:!1},Te=l.commands?q(w(n,l.commands)):{entries:[],truncated:!1},yt=l.rules?q(w(n,l.rules)):{entries:[],truncated:!1},Z={skills:Ee(U.entries,C("skills"),U.truncated),subagents:Ee(F.entries,C("subagents"),F.truncated),commands:Ee(Te.entries,C("commands"),Te.truncated),rules:Ee(yt.entries,C("rules"),yt.truncated)},A={runner_platform:e,config_scope:"user",cli_version:i,claude_version:o?i:null,model:o&&a||null,permission_keys:c,user_scope:{skills:Z.skills,subagents:Z.subagents,commands:Z.commands,rules:Z.rules,memory:l.memory?ee(w(n,l.memory)):u,settings:l.settings?ee(w(n,l.settings)):u,mcp:l.mcp?ee(w(n,l.mcp)):u},local_settings:o?ee(w(t,".claude/settings.local.json")):u},It=null,Rt=()=>{},Ct=r.nowMs??Date.now();if(!lt()&&Qo(h.user_spec_collected_at_ms,Ct)){let b=h.user_spec_collected_at_ms!==void 0,M=nt(e,n),S=rt(M.components,h.user_spec_components,{forceFull:!h.user_spec_components,truncated:M.truncated}),H=new Set(h.user_spec_text_hashes??[]),Ae=ot(M.components,S.upserts,H),k=it(at([...S.upserts,...Ae],H));A.user_spec_hash=S.hash,A.user_spec_count=S.count,A.user_spec_truncated=S.truncated||k.droppedCount>0,(k.components.length>0||S.removed.length>0||S.full)&&(S.full&&(A.user_spec_full=!0),k.components.length>0&&(A.user_spec=k.components),S.removed.length>0&&!A.user_spec_truncated&&(A.user_spec_removed=S.removed),k.textDeferredCount>0&&(A.user_spec_text_deferred=k.textDeferredCount));let ke=S.full?{}:{...h.user_spec_components??{}};if(!A.user_spec_truncated)for(let z of S.removed)delete ke[P(z.path,z.name)];for(let z of k.components)ke[P(z.path,z.name)]=z.content_hash;It={hash:S.hash,componentHashes:ke,textHashes:st(H,k.textHashesSent,M.components),included:k.components.length>0||S.removed.length>0&&!A.user_spec_truncated||S.full,collectedAtMs:Ct};let Oe=await ge({gitRoot:s,installationStorePath:r.installationStorePath,forceResend:b});Oe.operator&&(A.operator=Oe.operator),Rt=Oe.commit}let ur=ss(h,Z,x,It);return{config:A,commit:()=>{f[e]=ur,os(g,f),Rt()}}}function Y(e,t,n){let r={installation_id:n.installationId};return n.platformAgentId&&(r.platform_agent_id=n.platformAgentId),n.sessionId&&(r.session_id=n.sessionId),n.turnId&&(r.turn_id=n.turnId),{schema_version:2,event:e,timestamp:de(),session_id:n.sessionId||null,turn_id:n.turnId||null,installation_id:n.installationId,platform:n.runnerPlatform,platform_agent_id:n.platformAgentId||null,runner_event:n.runnerEvent||null,agent_hook_version:be,host_arch:process.arch,node_version:process.version,correlation:r,payload:t}}import{existsSync as zn}from"node:fs";import{spawn as Wn}from"node:child_process";import{basename as Ns}from"node:path";import{fileURLToPath as vs}from"node:url";var is=new Set(["localhost","127.0.0.1","[::1]","::1"]),On=/^[A-Za-z0-9._~-]+$/;function xn(e){for(let t=0;t<e.length;t++){let n=e.charCodeAt(t);if(n<=32||n===127||n===39)return!0}return!1}function Se(e){try{let t=new URL(e);return t.protocol==="https:"?!0:t.protocol==="http:"?is.has(t.hostname):!1}catch{return!1}}function Un(e){let t;try{t=new URL(e)}catch{return`invalid URL (got: ${e})`}if(!Se(e))return`must be https (or http on localhost / 127.0.0.1 / ::1) (got: ${e})`;let n=as(e);if(!n)return`must end with /{orgToken}/hook (got: ${e})`;if(!On.test(n))return`org token must match ${On.source} (got: ${n})`;if(xn(e))return`must not contain whitespace, control characters, or single quotes (got: ${e})`;if(xn(t.pathname))return`pathname must not contain whitespace, control characters, or single quotes (got: ${e})`}function bn(e){return new URL(e).toString()}function as(e){try{let n=new URL(e).pathname.split("/").filter(r=>r.length>0);if(n.length>=2&&n[n.length-1]==="hook"){let r=n[n.length-2];return r.length>0?r:void 0}return}catch{return}}function dt(e){try{let t=new URL(e),n=t.pathname.split("/").filter(r=>r.length>0);return n.length>=2&&n[n.length-1]==="hook"&&(n[n.length-2]="***",t.pathname=`/${n.join("/")}`),t.toString()}catch{return"<invalid-url>"}}function wn(e){if(e.collector_url)return e.collector_url;let t=e.repo_ingest_token?.trim();return t?le(t):""}var Nn=/(?:^|\/|[\s"'=(])(?:\.cursor\/|\.claude\/|\.agents\/)skills(?:-cursor)?\/([^/]+)\/SKILL\.md/i,vn=/(?:^|\/|[\s"'=(])\.codex\/commands\/([^/]+)\.md\b/i,cs=/(?:^|\s)\/([a-z][a-z0-9-]{1,63})\b/gi,ls=new Set(["applications","app","bin","boot","data","dev","etc","home","lib","media","mnt","node_modules","opt","pkg","private","proc","projects","repos","run","sbin","src","srv","sys","tmp","usr","users","var","volumes","workspace","workspaces"]),us=new Set(["read","read_file","view"]),ds=new Set(["bash","shell","zsh"]);function ps(e){let t=e.replace(/\\/g,"/");return Nn.exec(t)?.[1]??null}function fs(e){let t=e.replace(/\\/g,"/"),r=vn.exec(t)?.[1];return r?r.toLowerCase():null}function ms(e){return ps(e)??fs(e)}function gs(e){for(let t of["path","file_path","target_file"]){let n=e[t];if(typeof n=="string"&&n.length>0)return n}return null}function Mn(e){if(typeof e=="string")try{let t=JSON.parse(e);return Mn(t)}catch{return null}return!e||typeof e!="object"?null:gs(e)}function _s(e){if(!e||typeof e!="object")return null;let t=e.command;return typeof t=="string"&&t.length>0?t:null}function hs(e){let t=e.replace(/\\/g,"/"),n=Nn.exec(t);if(n?.[1])return n[1];let o=vn.exec(t)?.[1];return o?o.toLowerCase():null}function Es(e){return typeof e.tool_name=="string"?e.tool_name:typeof e.tool=="string"?e.tool:""}function Ln(e){let t=Es(e).toLowerCase();if(us.has(t)){let n=Mn(e.tool_input);return n?ms(n):null}if(ds.has(t)){let n=_s(e.tool_input);return n?hs(n):null}return null}function Ss(e){let t=new Set,n=[];for(let r of e.matchAll(cs)){let o=r[1]?.toLowerCase();!o||t.has(o)||ls.has(o)||(t.add(o),n.push(o))}return n}function ys(e){return Q(e.prompt)}function Pn(e){let t=p(e,"command_name");if(t){let r=p(e,"expansion_type");if(r&&r!=="slash_command")return[];let o=t.replace(/^\//,"").toLowerCase();return o?[o]:[]}let n=ys(e);return n?Ss(n):[]}function pt(e){return e!==void 0&&bt.includes(e)}function ye(e,t){let n=e[t+1];return n&&!n.startsWith("--")?{value:n,next:t+1}:{next:t}}function Ie(e){let t,n,r,o,s;for(let i=0;i<e.length;i++){let a=e[i];if(a!==void 0){if(a==="--runner"){let c=ye(e,i);t=c.value,i=c.next;continue}if(a.startsWith("--runner=")){t=a.slice(9);continue}if(a==="--url"){let c=ye(e,i);c.value&&(r=c.value),i=c.next;continue}if(a.startsWith("--url=")){r=a.slice(6);continue}if(a==="--token"){let c=ye(e,i);c.value&&(o=c.value),i=c.next;continue}if(a.startsWith("--token=")){o=a.slice(8);continue}if(a==="--base-url"){let c=ye(e,i);c.value&&(s=c.value),i=c.next;continue}if(a.startsWith("--base-url=")){s=a.slice(11);continue}!a.startsWith("-")&&n===void 0&&(n=a)}}return{runner:pt(t)?t:void 0,event:n,collectorUrl:r,orgToken:o,baseUrl:s}}function ft(e){let t=e.collectorUrl?.trim(),n;if(t)n=t;else{let o=e.orgToken?.trim();o&&(n=le(o,e.baseUrl?.trim()??void 0))}if(!n)return;let r=Un(n);if(r){m(`WARN: ignoring --url/--token collector override: ${r}`);return}return bn(n)}function Dn(e,t){if(p(e,"conversation_id"))return!0;if(t==="")return!1;let n=t[0];return n?.toLowerCase()===n}function Is(){return!!(E("CURSOR_VERSION")??E("CURSOR_PROJECT_DIR"))}function mt(e,t,n){return e!=="claude"&&e!=="codex"?!1:Dn(t,n)?!0:Is()}function gt(e,t,n,r){if(Dn(e,t))return"cursor";if(pt(r))return r;let o=p(e,"conversation_id"),s=p(e,"turn_id"),i=p(e,"session_id"),a=t.toLowerCase(),c="unknown";return o||t===a&&t!==""?c="cursor":s?c="codex":(i||a==="sessionstart"||a==="sessionend"||a==="stop"||a==="stopfailure"||a==="pretooluse"||a==="posttooluse"||a==="posttoolusefailure"||a==="permissiondenied"||a==="subagentstart"||a==="subagentstop"||a==="userpromptexpansion")&&(c="claude"),pt(n)&&(c=n),c}function Re(e,t){let n=e.toLowerCase();return n==="sessionend"||n==="stopfailure"||n==="subagentstop"?!0:n==="stop"&&t==="codex"}function Rs(e){switch(e){case"sessionstart":return"session_start";case"stop":case"sessionend":case"stopfailure":return"session_end";case"pretooluse":case"posttooluse":case"posttoolusefailure":case"permissiondenied":case"beforemcpexecution":case"beforeshellexecution":case"afterfileedit":case"subagentstart":case"subagentstop":return"tool_invoked";case"beforesubmitprompt":case"userpromptexpansion":case"userpromptsubmit":return"skill_invoked";default:return""}}function Hn(e){let t=e.toLowerCase();return t==="posttooluse"?!0:t==="posttoolusefailure"||t==="permissiondenied"?!1:null}function Fn(e,t,n){let r=p(e,"session_id")||p(e,"conversation_id"),o=p(e,"prompt.id")||p(e,"prompt_id")||p(e,"generation_id")||p(e,"turn_id"),s=p(e,"hook_event_name")||p(e,"event"),i=p(e,"source"),a=gt(e,s,t,n);return{sessionId:r,turnId:o,runnerEvent:s,hookSource:i,runnerPlatform:a}}var Cs=["session_start","session_end","tool_invoked","skill_invoked"];function Ts(e){return Cs.includes(e)}function Bn(e,t){return e&&Ts(e)?e:Rs(t.toLowerCase())}function $n(e){let t=p(e,"tool_name")||p(e,"tool")||null,n=e.tool_input,o=(n&&typeof n=="object"?Q(n.skill)||Q(n.skill_name):"")||p(e,"skill_name")||null;return o??=Ln(e),{toolName:t,skillName:o}}var As=/^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;function Gn(e){for(let t of["subagent_type","agent_type"]){let n=p(e,t);if(n&&As.test(n))return n}return null}function Kn(e){let t=$(e,"duration_ms");if(typeof t=="number")return t;let n=$(e,"duration");return typeof n=="number"?n:null}var ks="error",Os="interrupted",xs="permission_denied",Us=/^[A-Za-z][A-Za-z0-9_.-]{0,63}$/;function _t(e){return Us.test(e)?e:null}function bs(e){for(let t of["failure_type","error_type"]){let n=_t(p(e,t));if(n)return n}return null}function jn(e,t){return $(e,"is_interrupt")===!0?Os:t.toLowerCase()==="permissiondenied"?xs:bs(e)??ks}function ws(e,t){let n=null;for(let r of t)r&&(e===r||e.startsWith(`${r}_`)||e.startsWith(`${r}-`))&&(n===null||r.length>n.length)&&(n=r);return n}function Vn(e,t=[]){if(!e)return{mcpServer:null,mcpTool:null};let n=/^mcp__(.+?)__(.+)$/i.exec(e);if(n?.[1]&&n[2])return{mcpServer:n[1],mcpTool:n[2]};if(/^MCP:/i.test(e)){let r=e.slice(4);if(!r)return{mcpServer:null,mcpTool:null};let o=r.indexOf(":");return o>0?{mcpServer:r.slice(0,o),mcpTool:r.slice(o+1)||null}:{mcpServer:ws(r,t),mcpTool:r}}return{mcpServer:null,mcpTool:null}}var ht="__post",Ce="__work";function Ms(e,t){let n=e.payload,r=n&&typeof n=="object"&&!Array.isArray(n)?Object.keys(n):[],o=e.correlation&&typeof e.correlation=="object"?Object.keys(e.correlation):[];return JSON.stringify({event:e.event,schema_version:e.schema_version,agent_hook_version:e.agent_hook_version,host_arch:e.host_arch,node_version:e.node_version,build_ms:e.build_ms,body_bytes:t,correlation_keys:o,payload_keys:r})}function Jn(e){switch(e){case"session_start":return At;case"session_end":return kt;case"tool_invoked":case"skill_invoked":return xe;default:return xe}}function Ls(e,t,n){return`${JSON.stringify({url:e,timeoutMs:t})}
13
+ ${n}`}function Yn(e,t=[],n=process.execPath,r=import.meta.url,o=zn){if(Ns(n)===ue)return{command:n,args:[e,...t]};let s=vs(r);return o(s)?{command:n,args:[s,e,...t]}:{command:n,args:[e,...t]}}function Ps(e=process.execPath,t=import.meta.url,n=zn){return Yn(ht,[],e,t,n)}function Ds(e){let t=e.indexOf(`
14
+ `);if(t<0)return null;let n;try{n=JSON.parse(e.slice(0,t))}catch{return null}return{meta:n,body:e.slice(t+1)}}async function Xn(e,t=fetch){let n=await e(),r=Ds(n);if(!r)return;let{meta:o,body:s}=r,i={"Content-Type":"application/json"};try{await t(o.url,{method:"POST",headers:i,body:s,signal:AbortSignal.timeout(Number(o.timeoutMs))})}catch{}}async function Hs(e,t,n){let r=Jn(e);m(`POST event=${e} url=${dt(n)} size=${t.length} platform=${process.platform}`);let o={"Content-Type":"application/json"},s=Date.now();try{let i=await fetch(n,{method:"POST",headers:o,body:t,signal:AbortSignal.timeout(r)}),a=Date.now()-s;if(i.ok)return m(`POST outcome=ok elapsed_ms=${a} http=${i.status}`),!0;let c=(await i.text()).slice(0,200).replace(/[\n\r]/g,"");return m(`POST outcome=fail elapsed_ms=${a} http=${i.status} body=${c}`),!1}catch(i){let a=Date.now()-s,c=i instanceof Error?i.message:String(i);return m(`POST outcome=fail elapsed_ms=${a} http=000 body=${c}`),!1}}async function Zn(e,t,n,r,o){try{let s=r(e,t,{detached:!0,stdio:["pipe","ignore","ignore"],windowsHide:!0});s.on("error",()=>{}),s.stdin.on("error",()=>{});let i=!1;return await new Promise(a=>{let c=setTimeout(()=>{if(!i){m(`WARN: ${o} stdin handoff timed out \u2014 continuing fail-open`);try{s.stdin.destroy()}catch{}}a()},Ot),l=()=>{i=!0,clearTimeout(c),a()};s.stdin.end(n,()=>l()),s.stdin.once("error",()=>l())}),s.unref(),s}catch(s){let i=s instanceof Error?s.message:String(s);return m(`WARN: ${o} spawn failed open: ${i}`),null}}async function Fs(e,t,n,r=Wn,o=Ps){let s=Jn(e),i=Ls(n,s,t),{command:a,args:c}=o();return Zn(a,c,i,r,"detached post")}async function Qn(e,t,n=Wn,r=Yn){let{command:o,args:s}=r(Ce,t);return Zn(o,s,e,n,"detached work")}async function X(e,t,n,r,o,s){if(!o)return m("WARN: collector URL missing \u2014 pass --url on the hook command or set collector_url in manifest"),!1;if(!Se(o))return m(`WARN: collector URL blocked (https required): ${dt(o)}`),!1;let i=r(e,t,n);s!==void 0&&(i.build_ms=Math.max(0,Date.now()-s));let a=`${JSON.stringify(i)}
15
+ `,c=E("EV_AI_HOOK_DEBUG");c==="full"?m(`DEBUG envelope=${JSON.stringify(i)}`):c==="1"&&m(`DEBUG summary=${Ms(i,Buffer.byteLength(a,"utf8"))}`);let l=process.argv.includes(Ce),u=E("EV_AI_HOOK_SYNC")==="1";return Re(n.runnerEvent,n.runnerPlatform)||l||u?Hs(e,a,o):(await Fs(e,a,o),!1)}import{relative as Bs,resolve as Et,sep as qn}from"node:path";var $s=["session_id","conversation_id","turn_id","generation_id","prompt.id","prompt_id","hook_event_name","event","source","status","stop_reason","reason","tool_name","tool","tool_use_id","skill_name","command_name","expansion_type","command_source","permission_mode","model","model_id","agent_id","agent_type","subagent_id","subagent_type","subagent_model","is_parallel_worker","effort","effort.level","duration_ms","duration","failure_type","is_interrupt"];function Gs(e){return e.capture_hook_input==="full"?!0:e.capture_hook_input==="allowlist"?!1:E("EV_AI_HOOK_CAPTURE_FULL_INPUT")==="1"}function Ks(e){let t={};for(let n of $s){let r=$(e,n);r!==void 0&&(t[n]=r)}return t}function js(e,t){if(typeof e!="string"||e.length===0||!t)return null;let n=Et(e),r=Et(t),o=Bs(r,n);return!o||o==="."?".":o.startsWith(`..${qn}`)||o===".."||Et(r,o)!==n?null:o.split(qn).join("/")}function er(e,t){let n=JSON.stringify(e),r=Buffer.byteLength(n,"utf8");if(r<=t)return e;let o=Object.entries(e).filter(([i,a])=>!i.startsWith("_")&&(typeof a=="string"||typeof a=="number"||typeof a=="boolean")).sort((i,a)=>Buffer.byteLength(JSON.stringify(i[1]),"utf8")-Buffer.byteLength(JSON.stringify(a[1]),"utf8")),s={_truncated:!0,_original_bytes:r};for(let[i,a]of o){let c={...s,[i]:a};if(Buffer.byteLength(JSON.stringify(c),"utf8")>t)break;s[i]=a}return s}function se(e,t,n={}){let r=n.gitRoot!==void 0?js(e.cwd,n.gitRoot):null;if(Gs(t)){let s={...e};return delete s.cwd,delete s.transcript_path,r!==null&&(s.cwd_relative=r),er(s,Ut)}let o=Ks(e);return r!==null&&(o.cwd_relative=r),er(o,xt)}import{createReadStream as Vs}from"node:fs";import{stat as zs}from"node:fs/promises";import{basename as Ws,resolve as Js}from"node:path";import{createInterface as Ys}from"node:readline";var Xs=1024*1024;function Zs(e){let t=e.replace(/\\/g,"/");return t.includes("/.claude/projects/")&&Ws(t).endsWith(".jsonl")}async function tr(e){if(!e||!Zs(e))return null;try{let t=Js(e),n=await zs(t);if(!n.isFile())return null;let r=Math.max(0,n.size-Xs),o=[],s=Ys({input:Vs(t,{encoding:"utf8",start:r}),crlfDelay:1/0});for await(let i of s)i.length!==0&&o.push(i);r>0&&o.length>0&&o.shift();for(let i=o.length-1;i>=0;i--){let a=o[i];if(a)try{let c=JSON.parse(a);if(c.type!=="assistant")continue;let l=c.message;if(!l||typeof l!="object")continue;let u=l.model;if(typeof u=="string"&&u.length>0)return u}catch{continue}}return null}catch{return null}}function ae(e){return{sessionId:e.sessionId,turnId:e.turnId,installationId:e.manifest.installationId,runnerPlatform:e.runnerPlatform,platformAgentId:e.platformAgentId,runnerEvent:e.runnerEvent}}function Qs(...e){for(let t of e)if(t)return t;return null}function N(e,t,n){if(e.status==="fulfilled")return e.value;let r=e.reason instanceof Error?e.reason.message:String(e.reason);return m(`WARN: ${n} failed open: ${r}`),t}function qs(e){let t={present:!1,size:0},n={hash:"",count:0};return{config:{runner_platform:e,config_scope:"user",cli_version:null,claude_version:null,model:null,permission_keys:[],user_scope:{skills:n,subagents:n,commands:n,rules:n,memory:t,settings:t,mcp:t},local_settings:t},commit:()=>{}}}function ei(e,t){return{runner_platform:e,config_scope:"user",...t?{operator:t}:{}}}var V=new Set,ie=null;async function nr(e){if(lt())return;let t=e.manifest.installationId,n=e.manifest.installationStorePath;if(V.has(t))return;if(!Xe(n)){V.add(t);return}let r=Fe();if(cn(r)){if(ie){await ie;return}ie=(async()=>{if(V.has(t)||!Xe(n)){V.add(t);return}if(!Zt(n)){V.add(t);return}let o=!1;try{let s=Date.now(),{gitRoot:i}=e.manifest,a=String(e.runnerPlatform),[c,l,u,d,g]=await Promise.allSettled([ne(i),Be(),Ke(r),$e(),ge({gitRoot:i,installationStorePath:n,forceResend:!1})]),f=N(c,null,"gitSnapshot"),h=N(l,"","detectVirt"),x=N(u,null,"probeCloud"),v=N(d,{},"hostEnv"),C=N(g,{commit:()=>{}},"resolveOperatorForSend");await ce(e,i,f);let U={identity:{host:Ge(),context:r,virt:h||null,cloud:x,git:f},host_env:v,env_vars:We(),self_config:ei(a,C.operator),run_meta:{trigger:"cloud_identity_bootstrap"}};o=!!await X("session_start",U,ae(e),Y,e.manifest.collectorUrl,s),o&&(C.commit(),V.add(t))}finally{Qt(n)}})().finally(()=>{ie=null}),await ie}}async function ce(e,t,n){try{let r=n===void 0?await ne(t):n;e.platformAgentId=await rn(e.manifest.manifest,e.platformAgentId,String(e.runnerPlatform),t,r,e.manifest.installationStorePath,e.manifest.repoKey)}catch(r){let o=r instanceof Error?r.message:String(r);m(`WARN: derivePlatformAgentId failed open: ${o}`)}}async function ti(e){let t=Date.now(),{gitRoot:n}=e.manifest,r=Fe(),o=String(e.runnerPlatform),[s,i,a,c,l,u]=await Promise.allSettled([ne(n),Be(),Ke(r),$e(),ze(e.manifest.manifest,n,o),kn(o,n,void 0,{installationStorePath:e.manifest.installationStorePath,gitRoot:n})]),d=N(s,null,"gitSnapshot"),g=N(i,"","detectVirt"),f=N(a,null,"probeCloud"),h=N(c,{},"hostEnv"),x=N(l,[],"mcpDeclared"),v=N(u,qs(o),"selfConfig"),C=v.config;await ce(e,n,d);let U=p(e.hookInput,"model");U&&(C.model=U);let F={identity:{host:Ge(),context:r,virt:g||null,cloud:f,git:d},host_env:h,env_vars:We(),mcp:{declared:x},self_config:C,run_meta:{trigger:e.hookSource||"startup"},hook_input:se(e.hookInput,e.manifest.manifest,{gitRoot:n})};await X("session_start",F,ae(e),Y,e.manifest.collectorUrl,t)&&(v.commit(),V.add(e.manifest.installationId))}async function ni(e){let t=Date.now(),{gitRoot:n}=e.manifest;await ce(e,n);let r=Qs(p(e.hookInput,"status"),p(e.hookInput,"stop_reason"),p(e.hookInput,"reason"),_t(p(e.hookInput,"error"))),o=e.runnerPlatform==="claude"?await tr(p(e.hookInput,"transcript_path")):null,s=se(e.hookInput,e.manifest.manifest,{gitRoot:n});o&&(s.model=o),await X("session_end",{status:r,...o?{model:o}:{},hook_input:s},ae(e),Y,e.manifest.collectorUrl,t)}async function ri(e){let t=Date.now(),n=Pn(e.hookInput);if(n.length===0)return;await nr(e);let{gitRoot:r}=e.manifest;await ce(e,r);let o=se(e.hookInput,e.manifest.manifest,{gitRoot:r}),s=ae(e);await Promise.all(n.map(i=>X("tool_invoked",{tool_name:"Skill",skill_name:i,success:null,duration_ms:null,hook_input:o},s,Y,e.manifest.collectorUrl,t)))}async function oi(e){let t=Date.now();await nr(e);let{gitRoot:n}=e.manifest;await ce(e,n);let{toolName:r,skillName:o}=$n(e.hookInput),s=Kn(e.hookInput),i=Hn(e.runnerEvent),a=i===!1?jn(e.hookInput,e.runnerEvent):null,c=await ze(e.manifest.manifest,e.manifest.gitRoot,String(e.runnerPlatform)).catch(()=>[]),{mcpServer:l,mcpTool:u}=Vn(r,c.map(g=>g.name)),d=Gn(e.hookInput);await X("tool_invoked",{tool_name:r,skill_name:o,success:i,duration_ms:s,...a?{failure_reason:a}:{},...l?{mcp_server:l}:{},...u?{mcp_tool:u}:{},...d?{subagent_type:d}:{},hook_input:se(e.hookInput,e.manifest.manifest,{gitRoot:n})},ae(e),Y,e.manifest.collectorUrl,t)}async function rr(e){switch(e.internalEvent){case"session_start":await ti(e);return;case"session_end":await ni(e);return;case"skill_invoked":await ri(e);return;case"tool_invoked":await oi(e);return;default:return}}function or(e){return e!=="session_start"&&e!=="session_end"&&e!=="tool_invoked"&&e!=="skill_invoked"&&e!==""}import{existsSync as St,readFileSync as si}from"node:fs";import{dirname as ii,join as sr,relative as ai}from"node:path";var ir=[Tt,".cursor/ev-ai-runtime-report.json",".codex/ev-ai-runtime-report.json"];async function ci(e=process.cwd(),t){let n=E("EV_AI_HOOK_MANIFEST");if(n&&St(n))return n;let r=t??await pe(e);for(let o of ir){let s=sr(r,o);if(St(s))return s}for(let o of ir){let s=sr(e,o);if(St(s))return s}}async function li(e,t){let n=t??await pe(ii(e)),r=ai(n,e),o=await L("git",["ls-files","--error-unmatch",r],2e3,{cwd:n});return o.ok?!0:o.code===1?!1:(m(`WARN: git ls-files failed for manifest ${e} (code=${String(o.code)}); treating as tracked`),!0)}function ui(e){let t=si(e,"utf8");return O(t,{})}function di(){return{schema_version:2,mcp_servers:[]}}async function ar(e=process.cwd()){let t=await pe(e),n=await ci(e,t),r=n?ui(n):di();delete r.installation_id;let o=n?await li(n,t):!1;r.capture_hook_input==="full"&&n&&o&&(m(`WARN: ignoring capture_hook_input=full in git-tracked manifest ${n}; use EV_AI_HOOK_CAPTURE_FULL_INPUT=1 or an untracked operator manifest`),delete r.capture_hook_input);let{installationId:s,storePath:i,repoKey:a}=await nn(t);return{manifestPath:n??i,manifest:r,installationId:s,installationStorePath:i,repoKey:a,collectorUrl:wn(r),platformAgentId:r.platform_agent_id??"",gitRoot:t}}async function cr(e,t,n,r){let o=t??await ve(Ue),s=O(o,{}),i=await ar();if(!i)return;r&&(i.collectorUrl=r);let a=Fn(s,i.manifest.platform,n),c=Bn(e,a.runnerEvent);if(!c){m(`WARN: unknown hook event '${a.runnerEvent}'; skipping telemetry`);return}let l={hookInput:s,sessionId:a.sessionId,turnId:a.turnId,runnerEvent:a.runnerEvent,runnerPlatform:a.runnerPlatform,hookSource:a.hookSource,internalEvent:c,manifest:i,platformAgentId:i.platformAgentId};if(or(c)){m(`WARN: unsupported internal event '${c}'`);return}await rr(l)}function pi(e,t){if(E("EV_AI_HOOK_SYNC")==="1")return!0;let n=Ie(e),r=O(t,{}),o=n.event??(p(r,"hook_event_name")||p(r,"event")),s=gt(r,o,void 0,n.runner);return Re(o,s)}async function lr(e=process.argv.slice(2)){if(e[0]===ht){try{await Xn(Ne)}catch{}return 0}if(e[0]===Ce){try{let t=Ie(e.slice(1)),n=await Ne(),r=O(n,{}),o=t.event??(p(r,"hook_event_name")||p(r,"event"));if(mt(t.runner,r,o))return 0;await cr(t.event,n,t.runner,ft(t))}catch(t){let n=t instanceof Error?t.message:String(t);m(`WARN: detached work failed open: ${n}`)}return 0}try{let t=await ve(Ue),n=Ie(e),r=ft(n),o=O(t,{}),s=n.event??(p(o,"hook_event_name")||p(o,"event"));if(mt(n.runner,o,s))return 0;pi(e,t)?await cr(n.event,t,n.runner,r):await Qn(t,e)}catch(t){let n=t instanceof Error?t.message:String(t);m(`WARN: hook failed open: ${n}`)}finally{Dt()}return 0}lr().then(e=>{process.exit(e)}).catch(e=>{let t=e instanceof Error?e.message:String(e);process.stderr.write(`[ev-ai-agent-hook] ${t}
12
16
  `),process.exit(1)});
@@ -3,15 +3,15 @@ import { mkdirSync, writeFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
 
5
5
  // src/constants.ts
6
- var HOOK_BINARY_NAME = "evalon-agent-hook";
6
+ var HOOK_BINARY_NAME = "ev-ai-agent-hook";
7
7
  var GLOBAL_HOOK_BINARY_RELATIVE = `current/${HOOK_BINARY_NAME}`;
8
- var PROJECT_HOOK_BINARY_RELATIVE = `.evalon/agent-hook/${HOOK_BINARY_NAME}`;
8
+ var PROJECT_HOOK_BINARY_RELATIVE = `.ev-ai/agent-hook/${HOOK_BINARY_NAME}`;
9
9
  var HOOK_INPUT_ALLOWLIST_MAX_BYTES = 4 * 1024;
10
10
  var HOOK_INPUT_FULL_MAX_BYTES = 32 * 1024;
11
11
  var HOOK_INPUT_MCP_MAX_BYTES = 4 * 1024;
12
- var PACKAGE_VERSION = "1.0.6";
13
- var NPX_PACKAGE_SPEC = `@evalon-ai/agent-hook@${PACKAGE_VERSION}`;
14
- var EVALON_HOOK_STATUS_MESSAGE = "Evalon runtime report";
12
+ var PACKAGE_VERSION = "1.0.7";
13
+ var NPX_PACKAGE_SPEC = `@ev-ai/agent-hook@${PACKAGE_VERSION}`;
14
+ var HOOK_STATUS_MESSAGE = "ev-ai runtime report";
15
15
 
16
16
  // src/install.ts
17
17
  function npxHookCommand(packageSpec = NPX_PACKAGE_SPEC) {
@@ -47,7 +47,7 @@ function desiredCodexHookGroups(command) {
47
47
  const entry = {
48
48
  type: "command",
49
49
  command,
50
- statusMessage: EVALON_HOOK_STATUS_MESSAGE
50
+ statusMessage: HOOK_STATUS_MESSAGE
51
51
  };
52
52
  const commandHook = () => ({ hooks: [entry] });
53
53
  return {
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@ev-ai/agent-hook",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Cross-runner runtime telemetry hook for Claude Code, Cursor, and Codex",
5
5
  "type": "module",
6
6
  "bin": {
7
- "evalon-agent-hook": "dist/cli.mjs"
7
+ "ev-ai-agent-hook": "dist/cli.mjs"
8
8
  },
9
9
  "files": [
10
10
  "dist",
@@ -12,32 +12,10 @@
12
12
  "COLLECTED-DATA.md"
13
13
  ],
14
14
  "publishConfig": {
15
- "registry": "https://npm.pkg.github.com"
16
- },
17
- "scripts": {
18
- "build": "node scripts/build.mjs",
19
- "build:hook-binary": "node scripts/compile-hook.mjs",
20
- "build:hook-binary:host": "node scripts/compile-hook.mjs --host",
21
- "ensure:project-binary": "sh -c 'test -x \"$(git rev-parse --show-toplevel)/.evalon/agent-hook/evalon-agent-hook\" || (yarn build && yarn build:hook-binary:host && node dist/cli.mjs update)'",
22
- "update:local": "yarn build && yarn build:hook-binary:host && node dist/cli.mjs update",
23
- "clean": "rm -rf dist compile-out",
24
- "lint": "eslint src",
25
- "lint:fix": "eslint --fix src",
26
- "test": "vitest run --config vitest.config.unit.ts",
27
- "sync:hooks": "node scripts/sync-hook-events.mjs",
28
- "pin:hooks": "node scripts/pin-version.mjs",
29
- "pin:local": "node scripts/pin-version.mjs --local",
30
- "publish:gh": "node scripts/publish-gh.mjs"
15
+ "registry": "https://registry.npmjs.org",
16
+ "access": "public"
31
17
  },
32
18
  "engines": {
33
19
  "node": ">=18"
34
- },
35
- "devDependencies": {
36
- "@types/node": "~24.10.13",
37
- "esbuild": "~0.27.3",
38
- "eslint": "~9.39.1",
39
- "eslint-config-prettier": "~10.1.0",
40
- "typescript": "~5.9.3",
41
- "vitest": "~4.1.0"
42
20
  }
43
21
  }