am-i-vibing
Version:
Detect agentic coding environments and AI assistant tools
251 lines (248 loc) • 6.01 kB
JavaScript
import { getProcessAncestry } from "process-ancestry";
//#region src/providers.ts
/**
* Provider configurations for major AI coding tools
*/
const providers = [
{
id: "sst-opencode",
name: "SST OpenCode",
type: "agent",
envVars: [{ any: [
"OPENCODE_BIN_PATH",
"OPENCODE_SERVER",
"OPENCODE_APP_INFO",
"OPENCODE_MODES"
] }]
},
{
id: "jules",
name: "Jules",
type: "agent",
envVars: [{ all: [["HOME", "/home/jules"], ["USER", "swebot"]] }]
},
{
id: "claude-code",
name: "Claude Code",
type: "agent",
envVars: ["CLAUDECODE"]
},
{
id: "cursor-agent",
name: "Cursor Agent",
type: "agent",
envVars: [{ all: ["CURSOR_TRACE_ID", ["PAGER", "head -n 10000 | cat"]] }]
},
{
id: "cursor",
name: "Cursor",
type: "interactive",
envVars: ["CURSOR_TRACE_ID"]
},
{
id: "gemini-agent",
name: "Gemini Agent",
type: "agent",
processChecks: ["gemini"]
},
{
id: "codex",
name: "OpenAI Codex",
type: "agent",
processChecks: ["codex"]
},
{
id: "replit",
name: "Replit",
type: "agent",
envVars: ["REPL_ID"]
},
{
id: "aider",
name: "Aider",
type: "agent",
envVars: ["AIDER_API_KEY"],
processChecks: ["aider"]
},
{
id: "bolt-agent",
name: "Bolt.new Agent",
type: "agent",
envVars: [{ all: [["SHELL", "/bin/jsh"], "npm_config_yes"] }]
},
{
id: "bolt",
name: "Bolt.new",
type: "interactive",
envVars: [{
all: [["SHELL", "/bin/jsh"]],
none: ["npm_config_yes"]
}]
},
{
id: "zed-agent",
name: "Zed Agent",
type: "agent",
envVars: [{ all: [["TERM_PROGRAM", "zed"], ["PAGER", "cat"]] }]
},
{
id: "zed",
name: "Zed",
type: "interactive",
envVars: [{
all: [["TERM_PROGRAM", "zed"]],
none: [["PAGER", "cat"]]
}]
},
{
id: "replit-assistant",
name: "Replit Assistant",
type: "agent",
envVars: [{ all: ["REPL_ID", ["REPLIT_MODE", "assistant"]] }]
},
{
id: "replit",
name: "Replit",
type: "interactive",
envVars: [{
all: ["REPL_ID"],
none: [["REPLIT_MODE", "assistant"]]
}]
},
{
id: "windsurf",
name: "Windsurf",
type: "agent",
envVars: ["CODEIUM_EDITOR_APP_ROOT"]
},
{
id: "crush",
name: "Crush",
type: "agent",
processChecks: ["crush"]
},
{
id: "vscode-copilot-agent",
name: "GitHub Copilot in VS Code",
type: "agent",
envVars: [{ all: [["TERM_PROGRAM", "vscode"], ["GIT_PAGER", "cat"]] }]
},
{
id: "warp",
name: "Warp Terminal",
type: "hybrid",
envVars: [{ all: [["TERM_PROGRAM", "WarpTerminal"]] }]
},
{
id: "octofriend",
name: "Octofriend",
type: "agent",
processChecks: ["octofriend"]
}
];
/**
* Get provider configuration by name
*/
function getProvider(name) {
return providers.find((p) => p.name === name);
}
/**
* Get all providers of a specific type
*/
function getProvidersByType(type) {
return providers.filter((p) => p.type === type);
}
//#endregion
//#region src/detector.ts
/**
* Check if a specific environment variable exists (handles both strings and tuples)
*/
function checkEnvVar(envVarDef, env = process.env) {
const [envVar, expectedValue] = typeof envVarDef === "string" ? [envVarDef, void 0] : envVarDef;
const actualValue = env[envVar];
return Boolean(actualValue && (!expectedValue || actualValue === expectedValue));
}
/**
* Check if a process is running in the process tree
*/
function checkProcess(processName, processAncestry) {
try {
const ancestry = processAncestry ?? getProcessAncestry();
for (const ancestorProcess of ancestry) if (ancestorProcess.command?.includes(processName)) return true;
} catch (error) {}
return false;
}
/**
* Check if an environment variable group matches based on its properties
*/
function checkEnvVars(definition, env = process.env) {
if (typeof definition === "string" || Array.isArray(definition)) return checkEnvVar(definition, env);
const { any, all, none } = definition;
const anyResult = !any?.length || any.some((envVar) => checkEnvVar(envVar, env));
const allResult = !all?.length || all.every((envVar) => checkEnvVar(envVar, env));
const noneResult = !none?.length || !none.some((envVar) => checkEnvVar(envVar, env));
return anyResult && allResult && noneResult;
}
/**
* Run custom detectors for a provider
*/
function runCustomDetectors(provider) {
return provider.customDetectors?.some((detector) => {
try {
return detector();
} catch {
return false;
}
}) ?? false;
}
/**
* Create a positive detection result
*/
function createDetectedResult(provider) {
return {
isAgentic: true,
id: provider.id,
name: provider.name,
type: provider.type
};
}
/**
* Detect agentic coding environment
*/
function detectAgenticEnvironment(env = process.env, processAncestry) {
for (const provider of providers) {
if (provider.envVars?.some((group) => checkEnvVars(group, env))) return createDetectedResult(provider);
if (provider.processChecks?.some((processName) => checkProcess(processName, processAncestry))) return createDetectedResult(provider);
if (runCustomDetectors(provider)) return createDetectedResult(provider);
}
return {
isAgentic: false,
id: null,
name: null,
type: null
};
}
/**
* Check if currently running in any agent environment
*/
function isAgent(env = process.env, processAncestry) {
const result = detectAgenticEnvironment(env, processAncestry);
return result.type === "agent" || result.type === "hybrid";
}
/**
* Check if currently running in any interactive AI environment
*/
function isInteractive(env = process.env, processAncestry) {
const result = detectAgenticEnvironment(env, processAncestry);
return result.type === "interactive" || result.type === "hybrid";
}
/**
* Check if currently running in any hybrid AI environment
*/
function isHybrid(env = process.env, processAncestry) {
const result = detectAgenticEnvironment(env, processAncestry);
return result.type === "hybrid";
}
//#endregion
export { detectAgenticEnvironment, getProvider, getProvidersByType, isAgent, isHybrid, isInteractive, providers };
//# sourceMappingURL=detector-LEsE74_L.js.map