-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathagents.ts
More file actions
121 lines (109 loc) · 4.23 KB
/
Copy pathagents.ts
File metadata and controls
121 lines (109 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Note to AI Agents: Check @AGENTS.md for instructions on how to self-verify.
import { env, process } from "./env.ts";
/**
* Represents the name of an AI coding agent.
*/
export type AgentName =
| (string & {})
| "cursor"
| "claude"
| "devin"
| "replit"
| "gemini"
| "codex"
| "auggie"
| "opencode"
| "kiro"
| "goose"
| "pi"
| "junie";
type EnvCheck = string | (() => boolean);
type InternalAgent = [agentName: AgentName, envChecks: EnvCheck[]];
const agents: InternalAgent[] = [
// ✅ Verified by claude (can be detected using CLAUDECODE, CLAUDE_CODE, CLAUDE_AGENT_SDK_VERSION)
["claude", ["CLAUDECODE", "CLAUDE_CODE"]],
// ✅ Manually verified by @pi0
["replit", ["REPL_ID"]],
// ✅ Verified by gemini (can be detected using GEMINI_CLI, GEMINI_CLI_NO_RELAUNCH)
["gemini", ["GEMINI_CLI"]],
// ✅ Verified by codex (can be detected using CODEX_THREAD_ID)
["codex", ["CODEX_SANDBOX", "CODEX_THREAD_ID"]],
// ✅ Verified by opencode (can be detected using OPENCODE, OPENCODE_CALLER or OPENCODE_CLIENT?)
["opencode", ["OPENCODE"]],
// ✅ Verified by pi (can be detected using PATH containing .pi/agent/bin)
["pi", [/* #__PURE__ */ envMatcher("PATH", /\.pi[\\/]agent/)]],
// ❓ not tested
["auggie", ["AUGMENT_AGENT"]],
// ❓ not tested
["goose", ["GOOSE_PROVIDER"]],
// ✅ Verified by junie (can be detected using JUNIE_DATA, JUNIE_SHIM_PATH)
["junie", ["JUNIE_DATA", "JUNIE_SHIM_PATH"]],
// -- IDEs (checked last — agents running inside these should be detected first) --
// ✅ Verified by devin (can be detected using EDITOR, BROWSER, PATH)
["devin", [/* #__PURE__ */ envMatcher("EDITOR", /devin/)]],
// ✅ Verified by cursor (can be detected using CURSOR_AGENT, CURSOR_TRACE_ID, CURSOR_SANDBOX)
["cursor", ["CURSOR_AGENT"]],
// ✅ Verified by kiro (can be detected using TERM_PROGRAM)
// `TERM_PROGRAM=kiro` is set by both the Kiro IDE integrated terminal (interactive,
// has a TTY) and the Kiro CLI agent (non-interactive, no TTY). Gate on `noTTY` so a
// human typing in the IDE terminal is not mis-detected as an agent. See #185.
["kiro", [/* #__PURE__ */ envMatcher("TERM_PROGRAM", /kiro/, { noTTY: true })]],
];
function envMatcher(envKey: string, regex: RegExp, opts?: { noTTY?: boolean }) {
return () => {
// When `noTTY` is set, only match in a non-interactive (agent) context. A TTY
// means a human is at an integrated terminal, not an agent-spawned subprocess.
if (opts?.noTTY && process.stdout?.isTTY) {
return false;
}
const value = env[envKey];
return value ? regex.test(value) : false;
};
}
/**
* Provides information about an AI coding agent.
*/
export type AgentInfo = {
/**
* The name of the AI coding agent. See {@link AgentName} for possible values.
*/
name?: AgentName;
};
/**
* Detects the current AI coding agent from environment variables.
*
* Supported agents: `cursor`, `claude`, `devin`, `replit`, `gemini`, `codex`, `auggie`, `opencode`, `kiro`, `goose`, `pi`, `junie`
*
* You can also set the `AI_AGENT` environment variable to explicitly specify the agent name.
*/
export function detectAgent(): AgentInfo {
const aiAgent = env.AI_AGENT;
if (aiAgent) {
return { name: aiAgent.toLowerCase() };
}
for (const [name, checks] of agents) {
for (const check of checks) {
if (typeof check === "string" ? env[check] : check()) {
return { name };
}
}
}
return {};
}
/**
* The detected agent information for the current execution context.
* This value is evaluated once at module initialisation.
*/
export const agentInfo: AgentInfo = /* #__PURE__ */ detectAgent();
/**
* Name of the detected agent.
*/
// Wrapped in a `#__PURE__` IIFE (not a bare `agentInfo.name`) so bundlers can
// tree-shake `agentInfo` — and the whole agent-detection table — away when a
// consumer imports only `provider`/`isCI`/etc. A property access can't be marked
// pure, so it would otherwise pin the singleton. See AGENTS.md "Build & Tree-shaking".
export const agent: AgentName | undefined = /* #__PURE__ */ (() => agentInfo.name)();
/**
* A boolean flag indicating whether the current environment is running inside an AI coding agent.
*/
export const isAgent: boolean = /* #__PURE__ */ (() => !!agentInfo.name)();