hydra-nano 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,9 @@
1
1
  // Local telemetry: one JSON line per Hydra call or hook decision in ~/.hydra/ledger.jsonl.
2
2
  // Nothing leaves the machine. HYDRA_TELEMETRY=0 turns recording off.
3
3
  // kind 'call' (or no kind, rows written before telemetry v2): a head answered; raw/returned token estimates.
4
- // kind 'hook': the PreToolUse hook turned a command back ('deny'), let HYDRA_RAW=1 through ('raw') or
5
- // passed it ('pass', recorded without the command). hookMs is the hook process's whole lifetime.
4
+ // kind 'hook': the PreToolUse hook turned a command back ('deny'), let HYDRA_RAW=1 through ('raw'), let a
5
+ // run through that its own pipeline already cuts to a few lines ('trimmed') or passed it ('pass', recorded
6
+ // without the command). hookMs is the hook process's whole lifetime.
6
7
  // kind 'error': a command failed (model unavailable, crash).
7
8
  import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
8
9
  import os from 'node:os';
@@ -20,10 +21,12 @@ export const enabled = () => process.env.HYDRA_TELEMETRY !== '0';
20
21
  * AI_AGENT differs inside hooks (claude-code_<version>_harness) and the agent's shell (..._agent),
21
22
  * so `agent` keeps only the family and `agentDetail` the full value. */
22
23
  export function caller(session = process.env.CLAUDE_CODE_SESSION_ID) {
24
+ // Antigravity sets no agent variable; macOS passes the launching app's bundle id to every child process.
25
+ const app = /^com\.google\.antigravity(?:-ide)?$/.test(process.env.__CFBundleIdentifier ?? '') ? process.env.__CFBundleIdentifier : undefined;
23
26
  // HYDRA_AGENT is the MCP client's own name (codex-mcp-client, gemini-cli, opencode, ...), set by mcp.mjs.
24
- const detail = process.env.HYDRA_AGENT || process.env.AI_AGENT;
27
+ const detail = process.env.HYDRA_AGENT || process.env.AI_AGENT || (process.env.CLAUDECODE ? undefined : app);
25
28
  const agent = process.env.HYDRA_AGENT ? detail.toLowerCase().replace(/[-_ ]?mcp[-_ ]?client$/, '')
26
- : detail ? detail.split('_')[0] : process.env.CLAUDECODE ? 'claude-code' : 'shell';
29
+ : process.env.AI_AGENT ? detail.split('_')[0] : process.env.CLAUDECODE ? 'claude-code' : app ? 'antigravity' : 'shell';
27
30
  return { agent, ...(detail ? { agentDetail: detail } : {}), ...(process.env.HYDRA_VIA ? { via: process.env.HYDRA_VIA } : {}),
28
31
  ...(session ? { session } : {}) };
29
32
  }
@@ -126,6 +129,7 @@ export function findings(all = rows(), { since } = {}) {
126
129
  since: since ?? recent[0]?.ts ?? null, calls: calls.length, perHead, agents,
127
130
  hooks: { decisions: hooks.length, p50Ms: percentile(hookMs, 0.5), p90Ms: percentile(hookMs, 0.9),
128
131
  denials: denials.length, followedByHydra: followed.length,
132
+ trimmed: hooks.filter(row => row.decision === 'trimmed').length,
129
133
  rawBypasses: hooks.filter(row => row.decision === 'raw').map(row => row.command).slice(-5) },
130
134
  errors: recent.filter(row => row.kind === 'error').slice(-5).map(row => ({ ts: row.ts, command: row.command, error: row.error })),
131
135
  sessions: { seen: sessions.size, usingHydra: sessionsUsing.size },