next.js/packages/next/src/telemetry/detect-agent.ts
detect-agent.ts84 lines1.7 KB
// NOTE: This file duplicates the detection helper added in
// https://github.com/vercel/next.js/pull/91854 (branch: imm/agent-telemetry).
// When that PR lands, whichever branch merges second should collapse the
// duplicate — the contents are intentionally identical so the merge is a
// no-op. The env variable checks mirror the same functionality in the
// `vercel` CLI.

export type AgentName =
  | 'cursor'
  | 'cursor-cli'
  | 'claude'
  | 'cowork'
  | 'devin'
  | 'replit'
  | 'gemini'
  | 'codex'
  | 'antigravity'
  | 'augment-cli'
  | 'opencode'
  | 'github-copilot'

export function detectAgent(): AgentName | null {
  if (process.env.AI_AGENT) {
    const name = process.env.AI_AGENT.trim()
    if (name) {
      const normalized = name === 'github-copilot-cli' ? 'github-copilot' : name
      return normalized as AgentName
    }
  }

  if (process.env.CURSOR_TRACE_ID) {
    return 'cursor'
  }

  if (process.env.CURSOR_AGENT) {
    return 'cursor-cli'
  }

  if (process.env.GEMINI_CLI) {
    return 'gemini'
  }

  if (
    process.env.CODEX_SANDBOX ||
    process.env.CODEX_CI ||
    process.env.CODEX_THREAD_ID
  ) {
    return 'codex'
  }

  if (process.env.ANTIGRAVITY_AGENT) {
    return 'antigravity'
  }

  if (process.env.AUGMENT_AGENT) {
    return 'augment-cli'
  }

  if (process.env.OPENCODE_CLIENT) {
    return 'opencode'
  }

  if (process.env.CLAUDECODE || process.env.CLAUDE_CODE) {
    if (process.env.CLAUDE_CODE_IS_COWORK) {
      return 'cowork'
    }
    return 'claude'
  }

  if (process.env.REPL_ID) {
    return 'replit'
  }

  if (
    process.env.COPILOT_MODEL ||
    process.env.COPILOT_ALLOW_ALL ||
    process.env.COPILOT_GITHUB_TOKEN
  ) {
    return 'github-copilot'
  }

  return null
}
Quest for Codev2.0.0
/
SIGN IN