UNPKG

am-i-vibing

Version:

Detect agentic coding environments and AI assistant tools

1 lines 21.6 kB
{"version":3,"file":"detector-1yx2Hoe0.mjs","names":[],"sources":["../src/providers.ts","../src/detector.ts"],"sourcesContent":["import type { ProviderConfig } from \"./types.js\";\n\n/**\n * Provider configurations for major AI coding tools\n */\nexport const providers: ProviderConfig[] = [\n {\n id: \"opencode\",\n name: \"OpenCode\",\n type: \"agent\",\n envVars: [\n {\n any: [\n \"OPENCODE\",\n \"OPENCODE_BIN_PATH\",\n \"OPENCODE_SERVER\",\n \"OPENCODE_APP_INFO\",\n \"OPENCODE_MODES\",\n ],\n },\n ],\n },\n {\n id: \"jules\",\n name: \"Jules\",\n type: \"agent\",\n envVars: [\n {\n all: [\n [\"HOME\", \"/home/jules\"],\n [\"USER\", \"swebot\"],\n ],\n },\n ],\n },\n {\n id: \"claude-code\",\n name: \"Claude Code\",\n type: \"agent\",\n envVars: [\"CLAUDECODE\"],\n },\n {\n id: \"cursor-agent\",\n name: \"Cursor Agent\",\n type: \"agent\",\n envVars: [\n {\n all: [\"CURSOR_TRACE_ID\", [\"PAGER\", \"head -n 10000 | cat\"]],\n },\n ],\n },\n {\n id: \"cursor\",\n name: \"Cursor\",\n type: \"interactive\",\n envVars: [\"CURSOR_TRACE_ID\"],\n },\n {\n id: \"antigravity\",\n name: \"Antigravity\",\n type: \"agent\",\n envVars: [\n {\n any: [\"ANTIGRAVITY_AGENT\", \"ANTIGRAVITY_PROJECT_ID\"],\n },\n ],\n },\n {\n id: \"gemini-agent\",\n name: \"Gemini CLI\",\n type: \"agent\",\n // Gemini CLI sets GEMINI_CLI=1 on every shell command and MCP server it spawns.\n // See: https://github.com/google-gemini/gemini-cli/blob/main/packages/core/src/services/shellExecutionService.ts\n envVars: [[\"GEMINI_CLI\", \"1\"]],\n processChecks: [\"gemini\"],\n },\n {\n id: \"codex\",\n name: \"OpenAI Codex\",\n type: \"agent\",\n // Codex injects CODEX_THREAD_ID (the session conversation id) into every shell command it runs.\n // See: https://github.com/openai/codex/blob/main/codex-rs/protocol/src/shell_environment.rs\n envVars: [\"CODEX_THREAD_ID\"],\n processChecks: [\"codex\"],\n },\n {\n id: \"replit\",\n name: \"Replit\",\n type: \"agent\",\n envVars: [\"REPL_ID\"],\n },\n {\n id: \"aider\",\n name: \"Aider\",\n type: \"agent\",\n envVars: [\"AIDER_API_KEY\"],\n processChecks: [\"aider\"],\n },\n {\n id: \"bolt-agent\",\n name: \"Bolt.new Agent\",\n type: \"agent\",\n envVars: [\n {\n all: [[\"SHELL\", \"/bin/jsh\"], \"npm_config_yes\"],\n },\n ],\n },\n {\n id: \"bolt\",\n name: \"Bolt.new\",\n type: \"interactive\",\n envVars: [\n {\n all: [[\"SHELL\", \"/bin/jsh\"]],\n none: [\"npm_config_yes\"],\n },\n ],\n },\n {\n id: \"zed-agent\",\n name: \"Zed Agent\",\n type: \"agent\",\n envVars: [\n {\n all: [\n [\"TERM_PROGRAM\", \"zed\"],\n [\"PAGER\", \"cat\"],\n ],\n },\n ],\n },\n {\n id: \"zed\",\n name: \"Zed\",\n type: \"interactive\",\n envVars: [\n {\n all: [[\"TERM_PROGRAM\", \"zed\"]],\n none: [[\"PAGER\", \"cat\"]],\n },\n ],\n },\n {\n id: \"replit-assistant\",\n name: \"Replit Assistant\",\n type: \"agent\",\n envVars: [\n {\n all: [\"REPL_ID\", [\"REPLIT_MODE\", \"assistant\"]],\n },\n ],\n },\n {\n id: \"replit\",\n name: \"Replit\",\n type: \"interactive\",\n envVars: [\n {\n all: [\"REPL_ID\"],\n none: [[\"REPLIT_MODE\", \"assistant\"]],\n },\n ],\n },\n {\n id: \"windsurf\",\n name: \"Windsurf\",\n type: \"agent\",\n envVars: [\"CODEIUM_EDITOR_APP_ROOT\"],\n },\n {\n id: \"crush\",\n name: \"Crush\",\n type: \"agent\",\n // Crush sets CRUSH=1 (and AGENT=crush, AI_AGENT=crush) on every shell exec.\n // See: https://github.com/charmbracelet/crush/blob/main/internal/shell/shell.go\n envVars: [\n {\n any: [\n [\"CRUSH\", \"1\"],\n [\"AGENT\", \"crush\"],\n [\"AI_AGENT\", \"crush\"],\n ],\n },\n ],\n processChecks: [\"crush\"],\n },\n {\n id: \"amp\",\n name: \"Amp\",\n type: \"agent\",\n // Sourcegraph Amp injects AGENT=amp, AGENT_THREAD_ID, and AMP_CURRENT_THREAD_ID\n // into every shell tool execution.\n // See: https://www.npmjs.com/package/@sourcegraph/amp\n envVars: [\n {\n any: [\"AMP_CURRENT_THREAD_ID\", [\"AGENT\", \"amp\"]],\n },\n ],\n },\n {\n id: \"auggie\",\n name: \"Auggie\",\n type: \"agent\",\n // Augment Code's Auggie CLI sets AUGMENT_AGENT=1 in the shell tool's env on\n // every command execution.\n // See: https://www.npmjs.com/package/@augmentcode/auggie\n envVars: [[\"AUGMENT_AGENT\", \"1\"]],\n },\n {\n id: \"qwen-code\",\n name: \"Qwen Code\",\n type: \"agent\",\n // Qwen Code (Alibaba's gemini-cli fork) sets QWEN_CODE=1 on every shell exec.\n // See: https://www.npmjs.com/package/@qwen-code/qwen-code\n envVars: [[\"QWEN_CODE\", \"1\"]],\n },\n {\n id: \"vscode-copilot-agent\",\n name: \"GitHub Copilot in VS Code\",\n type: \"agent\",\n envVars: [\n {\n all: [\n [\"TERM_PROGRAM\", \"vscode\"],\n [\"GIT_PAGER\", \"cat\"],\n ],\n },\n ],\n },\n {\n id: \"warp\",\n name: \"Warp Terminal\",\n type: \"hybrid\",\n envVars: [\n {\n all: [[\"TERM_PROGRAM\", \"WarpTerminal\"]],\n },\n ],\n },\n {\n id: \"octofriend\",\n name: \"Octofriend\",\n type: \"agent\",\n // Octofriend does not currently expose an environment variable signal, so it\n // can only be detected via process ancestry (opt-in).\n processChecks: [\"octofriend\"],\n },\n {\n id: \"devin\",\n name: \"Devin\",\n type: \"agent\",\n // Devin for Terminal does not inject any DEVIN_* env var into shell tool\n // executions (DEVIN_PROJECT_DIR is only set inside hook commands, and\n // DEVIN_SESSION_ID/DEVIN_WRAPPER_ACTIVE only exist in the opt-in `devin shell`\n // integration where the user runs commands themselves). Process ancestry is\n // the only available signal, so detection is opt-in via processAncestry.\n processChecks: [\"devin\"],\n },\n {\n id: \"droid\",\n name: \"Factory Droid\",\n type: \"agent\",\n // Factory's Droid CLI sets DROID_PROJECT_DIR / FACTORY_PROJECT_DIR only inside\n // hook command invocations, not on regular shell tool exec. Process ancestry\n // is the only reliable signal, so detection is opt-in via processAncestry.\n processChecks: [\"droid\"],\n },\n {\n id: \"pi\",\n name: \"Pi\",\n type: \"agent\",\n // Pi's CLI entry point sets PI_CODING_AGENT=true on startup, and its bash tool\n // passes the process env through to every command it runs (getShellEnv spreads\n // ...process.env), so the variable is inherited by spawned shells.\n // See: https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/cli.ts\n envVars: [[\"PI_CODING_AGENT\", \"true\"]],\n },\n];\n\n/**\n * Get provider configuration by name\n */\nexport function getProvider(name: string): ProviderConfig | undefined {\n return providers.find((p) => p.name === name);\n}\n\n/**\n * Get all providers of a specific type\n */\nexport function getProvidersByType(\n type: \"agent\" | \"interactive\" | \"hybrid\",\n): ProviderConfig[] {\n return providers.filter((p) => p.type === type);\n}\n","import type {\n DetectionResult,\n DetectOptions,\n ProviderConfig,\n EnvVarDefinition,\n EnvVarGroup,\n} from \"./types.js\";\nimport { providers } from \"./providers.js\";\nimport { getProcessAncestry } from \"process-ancestry\";\n\n/**\n * Check if a specific environment variable exists (handles both strings and tuples)\n */\nfunction checkEnvVar(\n envVarDef: EnvVarDefinition,\n env: Record<string, string | undefined> = process.env,\n): boolean {\n const [envVar, expectedValue] =\n typeof envVarDef === \"string\" ? [envVarDef, undefined] : envVarDef;\n\n const actualValue = env[envVar];\n return Boolean(\n actualValue && (!expectedValue || actualValue === expectedValue),\n );\n}\n\n/**\n * Check if a process is running in the process tree\n */\nfunction checkProcess(\n processName: string,\n processAncestry: Array<{ command?: string }>,\n): boolean {\n for (const ancestorProcess of processAncestry) {\n if (ancestorProcess.command?.includes(processName)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an environment variable group matches based on its properties\n */\nfunction checkEnvVars(\n definition: EnvVarGroup | EnvVarDefinition,\n env: Record<string, string | undefined> = process.env,\n): boolean {\n if (typeof definition === \"string\" || Array.isArray(definition)) {\n return checkEnvVar(definition, env);\n }\n\n const { any, all, none } = definition;\n\n // Check ANY conditions (OR logic) - at least one must pass\n const anyResult =\n !any?.length || any.some((envVar) => checkEnvVar(envVar, env));\n\n // Check ALL conditions (AND logic) - all must pass\n const allResult =\n !all?.length || all.every((envVar) => checkEnvVar(envVar, env));\n\n // Check NONE conditions (NOT logic) - none should pass\n const noneResult =\n !none?.length || !none.some((envVar) => checkEnvVar(envVar, env));\n\n return anyResult && allResult && noneResult;\n}\n\n/**\n * Run custom detectors for a provider\n */\nfunction runCustomDetectors(provider: ProviderConfig): boolean {\n return (\n provider.customDetectors?.some((detector) => {\n try {\n return detector();\n } catch {\n return false;\n }\n }) ?? false\n );\n}\n\n/**\n * Create a positive detection result\n */\nfunction createDetectedResult(provider: ProviderConfig): DetectionResult {\n return {\n isAgentic: true,\n id: provider.id,\n name: provider.name,\n type: provider.type,\n };\n}\n\n/**\n * Normalize the various supported argument shapes into a DetectOptions object.\n *\n * Supported shapes:\n * - detectAgenticEnvironment()\n * - detectAgenticEnvironment(options)\n * - detectAgenticEnvironment(env) // legacy\n * - detectAgenticEnvironment(env, processAncestry) // legacy\n */\nfunction normalizeOptions(\n envOrOptions?: Record<string, string | undefined> | DetectOptions,\n legacyAncestry?: Array<{ command?: string }>,\n): Required<Pick<DetectOptions, \"env\" | \"checkProcesses\">> & {\n processAncestry?: Array<{ command?: string }>;\n} {\n // Distinguish a DetectOptions object from a raw env record. DetectOptions\n // has at least one of the known keys; an env record is a flat string map.\n const looksLikeOptions =\n envOrOptions != null &&\n typeof envOrOptions === \"object\" &&\n (\"env\" in envOrOptions ||\n \"processAncestry\" in envOrOptions ||\n \"checkProcesses\" in envOrOptions);\n\n if (looksLikeOptions) {\n const opts = envOrOptions as DetectOptions;\n return {\n env: opts.env ?? process.env,\n processAncestry: opts.processAncestry,\n // If the caller pre-supplied an ancestry, default checkProcesses to true\n // unless they explicitly opted out.\n checkProcesses:\n opts.checkProcesses ?? opts.processAncestry !== undefined,\n };\n }\n\n return {\n env:\n (envOrOptions as Record<string, string | undefined> | undefined) ??\n process.env,\n processAncestry: legacyAncestry,\n // Legacy callers that explicitly passed an ancestry are presumed to want\n // process checks; otherwise default off.\n checkProcesses: legacyAncestry !== undefined,\n };\n}\n\n/**\n * Detect agentic coding environment\n */\nexport function detectAgenticEnvironment(\n options?: DetectOptions,\n): DetectionResult;\n/**\n * @deprecated Pass an options object instead. This signature is retained for\n * backwards compatibility and will be removed in a future major release.\n */\nexport function detectAgenticEnvironment(\n env: Record<string, string | undefined>,\n processAncestry?: Array<{ command?: string }>,\n): DetectionResult;\nexport function detectAgenticEnvironment(\n envOrOptions?: Record<string, string | undefined> | DetectOptions,\n legacyAncestry?: Array<{ command?: string }>,\n): DetectionResult {\n const { env, processAncestry, checkProcesses } = normalizeOptions(\n envOrOptions,\n legacyAncestry,\n );\n\n // Fast path: check all environment variables first\n for (const provider of providers) {\n if (provider.envVars?.some((group) => checkEnvVars(group, env))) {\n return createDetectedResult(provider);\n }\n }\n\n // Custom detectors next (cheap, in-process)\n for (const provider of providers) {\n if (runCustomDetectors(provider)) {\n return createDetectedResult(provider);\n }\n }\n\n // Slow path: process ancestry checks. Opt-in only because reading the process\n // tree spawns a subprocess (notably slow on Windows).\n if (checkProcesses) {\n let cachedAncestry = processAncestry;\n const getAncestry = () => {\n if (cachedAncestry === undefined) {\n try {\n cachedAncestry = getProcessAncestry();\n } catch {\n cachedAncestry = [];\n }\n }\n return cachedAncestry;\n };\n\n for (const provider of providers) {\n if (\n provider.processChecks?.some((processName) =>\n checkProcess(processName, getAncestry()),\n )\n ) {\n return createDetectedResult(provider);\n }\n }\n }\n\n // No provider detected\n return {\n isAgentic: false,\n id: null,\n name: null,\n type: null,\n };\n}\n\n/**\n * Check if currently running in a specific provider\n */\nexport function isProvider(\n providerName: string,\n options?: DetectOptions,\n): boolean;\n/**\n * @deprecated Pass an options object instead.\n */\nexport function isProvider(\n providerName: string,\n env: Record<string, string | undefined>,\n processAncestry?: Array<{ command?: string }>,\n): boolean;\nexport function isProvider(\n providerName: string,\n envOrOptions?: Record<string, string | undefined> | DetectOptions,\n legacyAncestry?: Array<{ command?: string }>,\n): boolean {\n const result = detectAgenticEnvironment(\n envOrOptions as DetectOptions,\n legacyAncestry as Array<{ command?: string }> | undefined,\n );\n return result.name === providerName;\n}\n\n/**\n * Check if currently running in any agent environment\n */\nexport function isAgent(options?: DetectOptions): boolean;\n/**\n * @deprecated Pass an options object instead.\n */\nexport function isAgent(\n env: Record<string, string | undefined>,\n processAncestry?: Array<{ command?: string }>,\n): boolean;\nexport function isAgent(\n envOrOptions?: Record<string, string | undefined> | DetectOptions,\n legacyAncestry?: Array<{ command?: string }>,\n): boolean {\n const result = detectAgenticEnvironment(\n envOrOptions as DetectOptions,\n legacyAncestry as Array<{ command?: string }> | undefined,\n );\n return result.type === \"agent\" || result.type === \"hybrid\";\n}\n\n/**\n * Check if currently running in any interactive AI environment\n */\nexport function isInteractive(options?: DetectOptions): boolean;\n/**\n * @deprecated Pass an options object instead.\n */\nexport function isInteractive(\n env: Record<string, string | undefined>,\n processAncestry?: Array<{ command?: string }>,\n): boolean;\nexport function isInteractive(\n envOrOptions?: Record<string, string | undefined> | DetectOptions,\n legacyAncestry?: Array<{ command?: string }>,\n): boolean {\n const result = detectAgenticEnvironment(\n envOrOptions as DetectOptions,\n legacyAncestry as Array<{ command?: string }> | undefined,\n );\n return result.type === \"interactive\" || result.type === \"hybrid\";\n}\n\n/**\n * Check if currently running in any hybrid AI environment\n */\nexport function isHybrid(options?: DetectOptions): boolean;\n/**\n * @deprecated Pass an options object instead.\n */\nexport function isHybrid(\n env: Record<string, string | undefined>,\n processAncestry?: Array<{ command?: string }>,\n): boolean;\nexport function isHybrid(\n envOrOptions?: Record<string, string | undefined> | DetectOptions,\n legacyAncestry?: Array<{ command?: string }>,\n): boolean {\n const result = detectAgenticEnvironment(\n envOrOptions as DetectOptions,\n legacyAncestry as Array<{ command?: string }> | undefined,\n );\n return result.type === \"hybrid\";\n}\n"],"mappings":"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"}