@poppinss/utils 7.0.0-next.5 → 7.0.0-next.6

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.
package/README.md CHANGED
@@ -627,6 +627,52 @@ const rawValue = secret.release()
627
627
  rawValue === opaque_raw_token // true
628
628
  ```
629
629
 
630
+ ## AI Agent Detection
631
+
632
+ Detect if your code is running inside an AI coding assistant. This is useful for adjusting application behavior when running under AI agents (e.g., disabling prompts, adjusting logging, or enabling special debugging modes).
633
+
634
+ ### detectAIAgent
635
+
636
+ Returns the name of the detected AI agent or `null` if none is detected.
637
+
638
+ ```ts
639
+ import { detectAIAgent } from '@poppinss/utils'
640
+
641
+ const agent = detectAIAgent()
642
+
643
+ if (agent === 'claude') {
644
+ console.log('Running in Claude Code')
645
+ } else if (agent === 'copilot') {
646
+ console.log('Running in GitHub Copilot')
647
+ }
648
+ ```
649
+
650
+ **Supported agents:**
651
+
652
+ | Agent | Environment Variable(s) | Return Value |
653
+ | --------------- | ------------------------------------------------------------ | ------------ |
654
+ | Claude Code | `CLAUDECODE='1'` | `'claude'` |
655
+ | Gemini | `GEMINI_CLI='1'` | `'gemini'` |
656
+ | GitHub Copilot | `GITHUB_COPILOT_CLI_MODE='1'` | `'copilot'` |
657
+ | Windsurf | `WINDSURF_SESSION='1'` or `TERM_PROGRAM='windsurf'` | `'windsurf'` |
658
+ | Codex | `CODEX_CLI='1'` or `CODEX_SANDBOX='1'` | `'codex'` |
659
+ | OpenCode | `OPENCODE='1'` | `'opencode'` |
660
+ | Cursor | `CURSOR_AGENT='1'` | `'cursor'` |
661
+
662
+ ### isRunningInAIAgent
663
+
664
+ Returns `true` if the code is running inside any AI coding agent.
665
+
666
+ ```ts
667
+ import { isRunningInAIAgent } from '@poppinss/utils'
668
+
669
+ if (isRunningInAIAgent()) {
670
+ // Disable interactive prompts
671
+ // Enable verbose logging
672
+ // Skip waiting for user input
673
+ }
674
+ ```
675
+
630
676
  ## ImportsBag
631
677
 
632
678
  The `ImportsBag` class helps you manage and deduplicate import statements when generating code. It automatically merges imports from the same source and generates properly formatted import statements.
package/build/index.d.ts CHANGED
@@ -8,3 +8,4 @@ export { importDefault } from './src/import_default.js';
8
8
  export { MessageBuilder } from './src/message_builder.js';
9
9
  export { ImportsBag, type ImportInfo } from './src/imports_bag.js';
10
10
  export { defineStaticProperty } from './src/define_static_property.js';
11
+ export { detectAIAgent, isRunningInAIAgent } from './src/detect_ai_agent.js';
package/build/index.js CHANGED
@@ -95,13 +95,19 @@ var ImportsBag = class {
95
95
  if (imp.namedImports && imp.namedImports.length > 0) importParts.push(`{ ${imp.namedImports.join(", ")} }`);
96
96
  parts.push(`import ${importParts.join(", ")} from '${imp.source}'`);
97
97
  }
98
- if (imp.typeImports && imp.typeImports.length > 0) parts.push(`import type { ${imp.typeImports.join(", ")} } from '${imp.source}'`);
98
+ if (imp.defaultTypeImport || imp.typeImports && imp.typeImports.length > 0) {
99
+ const typeImportParts = [];
100
+ if (imp.defaultTypeImport) typeImportParts.push(imp.defaultTypeImport);
101
+ if (imp.typeImports && imp.typeImports.length > 0) typeImportParts.push(`{ ${imp.typeImports.join(", ")} }`);
102
+ parts.push(`import type ${typeImportParts.join(", ")} from '${imp.source}'`);
103
+ }
99
104
  return parts.join("\n");
100
105
  }
101
106
  add(importInfo) {
102
107
  const existing = this.#imports.get(importInfo.source);
103
108
  if (existing) {
104
109
  if (importInfo.defaultImport) existing.defaultImport = importInfo.defaultImport;
110
+ if (importInfo.defaultTypeImport) existing.defaultTypeImport = importInfo.defaultTypeImport;
105
111
  if (importInfo.namedImports) {
106
112
  if (!existing.namedImports) existing.namedImports = [];
107
113
  existing.namedImports.push(...importInfo.namedImports);
@@ -113,6 +119,7 @@ var ImportsBag = class {
113
119
  } else this.#imports.set(importInfo.source, {
114
120
  source: importInfo.source,
115
121
  defaultImport: importInfo.defaultImport,
122
+ defaultTypeImport: importInfo.defaultTypeImport,
116
123
  namedImports: importInfo.namedImports ? [...importInfo.namedImports] : void 0,
117
124
  typeImports: importInfo.typeImports ? [...importInfo.typeImports] : void 0
118
125
  });
@@ -122,6 +129,7 @@ var ImportsBag = class {
122
129
  return Array.from(this.#imports.values()).map((imp) => ({
123
130
  source: imp.source,
124
131
  defaultImport: imp.defaultImport,
132
+ defaultTypeImport: imp.defaultTypeImport,
125
133
  namedImports: imp.namedImports ? [...new Set(imp.namedImports)] : void 0,
126
134
  typeImports: imp.typeImports ? [...new Set(imp.typeImports)] : void 0
127
135
  }));
@@ -151,4 +159,17 @@ function defineStaticProperty(self, propertyName, { initialValue, strategy }) {
151
159
  });
152
160
  }
153
161
  }
154
- export { ImportsBag, MessageBuilder, Secret, compose, defineStaticProperty, flatten, importDefault, isScriptFile, naturalSort, safeEqual };
162
+ function detectAIAgent() {
163
+ if (process.env.CLAUDECODE === "1") return "claude";
164
+ if (process.env.GEMINI_CLI === "1") return "gemini";
165
+ if (process.env.GITHUB_COPILOT_CLI_MODE === "1") return "copilot";
166
+ if (process.env.WINDSURF_SESSION === "1" || process.env.TERM_PROGRAM === "windsurf") return "windsurf";
167
+ if (process.env.CODEX_CLI === "1" || process.env.CODEX_SANDBOX === "1") return "codex";
168
+ if (process.env.OPENCODE === "1") return "opencode";
169
+ if (process.env.CURSOR_AGENT === "1") return "cursor";
170
+ return null;
171
+ }
172
+ function isRunningInAIAgent() {
173
+ return detectAIAgent() !== null;
174
+ }
175
+ export { ImportsBag, MessageBuilder, Secret, compose, defineStaticProperty, detectAIAgent, flatten, importDefault, isRunningInAIAgent, isScriptFile, naturalSort, safeEqual };
@@ -0,0 +1,18 @@
1
+ type AIAgent = 'claude' | 'cursor' | 'opencode' | 'gemini' | 'copilot' | 'windsurf' | 'codex';
2
+ /**
3
+ * Detects which AI coding agent the code is running under.
4
+ * Checks for environment variables set by different AI coding assistants:
5
+ * - CLAUDECODE='1' for Claude Code
6
+ * - GEMINI_CLI='1' for Gemini
7
+ * - GITHUB_COPILOT_CLI_MODE='1' for GitHub Copilot
8
+ * - WINDSURF_SESSION='1' or TERM_PROGRAM='windsurf' for Windsurf
9
+ * - CODEX_CLI='1' or CODEX_SANDBOX='1' for Codex
10
+ * - OPENCODE='1' for OpenCode
11
+ * - CURSOR_AGENT='1' for Cursor
12
+ */
13
+ export declare function detectAIAgent(): AIAgent | null;
14
+ /**
15
+ * Returns true if the code is running within any AI coding agent.
16
+ */
17
+ export declare function isRunningInAIAgent(): boolean;
18
+ export {};
@@ -1,6 +1,7 @@
1
1
  export type ImportInfo = {
2
2
  source: string;
3
3
  defaultImport?: string;
4
+ defaultTypeImport?: string;
4
5
  namedImports?: string[];
5
6
  typeImports?: string[];
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poppinss/utils",
3
- "version": "7.0.0-next.5",
3
+ "version": "7.0.0-next.6",
4
4
  "description": "Handy utilities for repetitive work",
5
5
  "main": "build/index.js",
6
6
  "type": "module",