@agentuity/cli 1.0.0 → 1.0.2
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/AGENTS.md +40 -24
- package/bin/cli.ts +47 -22
- package/dist/agent-detection.d.ts +23 -38
- package/dist/agent-detection.d.ts.map +1 -1
- package/dist/agent-detection.js +412 -153
- package/dist/agent-detection.js.map +1 -1
- package/dist/ai-help.d.ts +23 -0
- package/dist/ai-help.d.ts.map +1 -0
- package/dist/ai-help.js +328 -0
- package/dist/ai-help.js.map +1 -0
- package/dist/api.js +1 -1
- package/dist/api.js.map +1 -1
- package/dist/auth.d.ts +10 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +176 -16
- package/dist/auth.js.map +1 -1
- package/dist/banner.d.ts.map +1 -1
- package/dist/banner.js +5 -0
- package/dist/banner.js.map +1 -1
- package/dist/cache/agent-intro.d.ts +13 -0
- package/dist/cache/agent-intro.d.ts.map +1 -0
- package/dist/cache/agent-intro.js +54 -0
- package/dist/cache/agent-intro.js.map +1 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +1 -0
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/resource-region.d.ts +3 -2
- package/dist/cache/resource-region.d.ts.map +1 -1
- package/dist/cache/resource-region.js +13 -4
- package/dist/cache/resource-region.js.map +1 -1
- package/dist/catalyst.d.ts +7 -0
- package/dist/catalyst.d.ts.map +1 -0
- package/dist/catalyst.js +15 -0
- package/dist/catalyst.js.map +1 -0
- package/dist/cli.d.ts +12 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +290 -67
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/detect.d.ts +3 -0
- package/dist/cmd/ai/detect.d.ts.map +1 -0
- package/dist/cmd/ai/detect.js +49 -0
- package/dist/cmd/ai/detect.js.map +1 -0
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +11 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/ai/intro.d.ts +7 -0
- package/dist/cmd/ai/intro.d.ts.map +1 -0
- package/dist/cmd/ai/intro.js +141 -0
- package/dist/cmd/ai/intro.js.map +1 -0
- package/dist/cmd/ai/opencode/run.d.ts.map +1 -1
- package/dist/cmd/ai/opencode/run.js +5 -0
- package/dist/cmd/ai/opencode/run.js.map +1 -1
- package/dist/cmd/build/ast.d.ts.map +1 -1
- package/dist/cmd/build/ast.js +79 -0
- package/dist/cmd/build/ast.js.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.d.ts.map +1 -1
- package/dist/cmd/build/vite/bun-dev-server.js +2 -0
- package/dist/cmd/build/vite/bun-dev-server.js.map +1 -1
- package/dist/cmd/build/vite/docs-generator.d.ts.map +1 -1
- package/dist/cmd/build/vite/docs-generator.js +15 -1
- package/dist/cmd/build/vite/docs-generator.js.map +1 -1
- package/dist/cmd/build/vite/env-types-generator.d.ts +26 -0
- package/dist/cmd/build/vite/env-types-generator.d.ts.map +1 -0
- package/dist/cmd/build/vite/env-types-generator.js +110 -0
- package/dist/cmd/build/vite/env-types-generator.js.map +1 -0
- package/dist/cmd/build/vite/index.d.ts +2 -0
- package/dist/cmd/build/vite/index.d.ts.map +1 -1
- package/dist/cmd/build/vite/index.js +12 -1
- package/dist/cmd/build/vite/index.js.map +1 -1
- package/dist/cmd/build/vite/public-asset-path-plugin.d.ts.map +1 -1
- package/dist/cmd/build/vite/public-asset-path-plugin.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts +2 -0
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +10 -1
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/cloud/db/create.js.map +1 -1
- package/dist/cmd/cloud/db/delete.js.map +1 -1
- package/dist/cmd/cloud/db/get.d.ts.map +1 -1
- package/dist/cmd/cloud/db/get.js +27 -12
- package/dist/cmd/cloud/db/get.js.map +1 -1
- package/dist/cmd/cloud/deploy-fork.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy-fork.js +2 -0
- package/dist/cmd/cloud/deploy-fork.js.map +1 -1
- package/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +17 -0
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/env/push.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.js +3 -3
- package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
- package/dist/cmd/cloud/machine/list.js +3 -3
- package/dist/cmd/cloud/machine/list.js.map +1 -1
- package/dist/cmd/cloud/region/index.js.map +1 -1
- package/dist/cmd/cloud/region-lookup.d.ts +7 -4
- package/dist/cmd/cloud/region-lookup.d.ts.map +1 -1
- package/dist/cmd/cloud/region-lookup.js +59 -14
- package/dist/cmd/cloud/region-lookup.js.map +1 -1
- package/dist/cmd/cloud/sandbox/cp.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/cp.js +7 -5
- package/dist/cmd/cloud/sandbox/cp.js.map +1 -1
- package/dist/cmd/cloud/sandbox/create.js +1 -1
- package/dist/cmd/cloud/sandbox/create.js.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/delete.js +8 -7
- package/dist/cmd/cloud/sandbox/delete.js.map +1 -1
- package/dist/cmd/cloud/sandbox/download.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/download.js +7 -5
- package/dist/cmd/cloud/sandbox/download.js.map +1 -1
- package/dist/cmd/cloud/sandbox/env.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/env.js +7 -5
- package/dist/cmd/cloud/sandbox/env.js.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/exec.js +7 -5
- package/dist/cmd/cloud/sandbox/exec.js.map +1 -1
- package/dist/cmd/cloud/sandbox/get.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/get.js +12 -7
- package/dist/cmd/cloud/sandbox/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/list.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/list.js +40 -63
- package/dist/cmd/cloud/sandbox/list.js.map +1 -1
- package/dist/cmd/cloud/sandbox/ls.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/ls.js +7 -5
- package/dist/cmd/cloud/sandbox/ls.js.map +1 -1
- package/dist/cmd/cloud/sandbox/mkdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/mkdir.js +7 -5
- package/dist/cmd/cloud/sandbox/mkdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/rm.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/rm.js +7 -5
- package/dist/cmd/cloud/sandbox/rm.js.map +1 -1
- package/dist/cmd/cloud/sandbox/rmdir.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/rmdir.js +7 -5
- package/dist/cmd/cloud/sandbox/rmdir.js.map +1 -1
- package/dist/cmd/cloud/sandbox/run.js +1 -1
- package/dist/cmd/cloud/sandbox/run.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/build.js.map +1 -1
- package/dist/cmd/cloud/sandbox/snapshot/get.js.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/upload.js +7 -5
- package/dist/cmd/cloud/sandbox/upload.js.map +1 -1
- package/dist/cmd/cloud/sandbox/util.d.ts +2 -2
- package/dist/cmd/cloud/sandbox/util.d.ts.map +1 -1
- package/dist/cmd/cloud/sandbox/util.js +14 -13
- package/dist/cmd/cloud/sandbox/util.js.map +1 -1
- package/dist/cmd/cloud/ssh.d.ts.map +1 -1
- package/dist/cmd/cloud/ssh.js +3 -3
- package/dist/cmd/cloud/ssh.js.map +1 -1
- package/dist/cmd/cloud/storage/create.js.map +1 -1
- package/dist/cmd/cloud/storage/delete.js.map +1 -1
- package/dist/cmd/cloud/storage/get.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/get.js +5 -11
- package/dist/cmd/cloud/storage/get.js.map +1 -1
- package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/list.js +6 -6
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/cloud/stream/create.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/create.js +7 -4
- package/dist/cmd/cloud/stream/create.js.map +1 -1
- package/dist/cmd/cloud/stream/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/delete.js +25 -4
- package/dist/cmd/cloud/stream/delete.js.map +1 -1
- package/dist/cmd/cloud/stream/get.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/get.js +91 -62
- package/dist/cmd/cloud/stream/get.js.map +1 -1
- package/dist/cmd/cloud/stream/list.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/list.js +66 -38
- package/dist/cmd/cloud/stream/list.js.map +1 -1
- package/dist/cmd/cloud/stream/util.d.ts +20 -0
- package/dist/cmd/cloud/stream/util.d.ts.map +1 -1
- package/dist/cmd/cloud/stream/util.js +27 -3
- package/dist/cmd/cloud/stream/util.js.map +1 -1
- package/dist/cmd/cloud/vector/util.d.ts.map +1 -1
- package/dist/cmd/cloud/vector/util.js +3 -3
- package/dist/cmd/cloud/vector/util.js.map +1 -1
- package/dist/cmd/dev/index.js.map +1 -1
- package/dist/cmd/git/account/add.js.map +1 -1
- package/dist/cmd/git/list.js.map +1 -1
- package/dist/cmd/project/add/database.d.ts +2 -0
- package/dist/cmd/project/add/database.d.ts.map +1 -0
- package/dist/cmd/project/add/database.js +123 -0
- package/dist/cmd/project/add/database.js.map +1 -0
- package/dist/cmd/project/add/domain.d.ts +2 -0
- package/dist/cmd/project/add/domain.d.ts.map +1 -0
- package/dist/cmd/project/add/domain.js +152 -0
- package/dist/cmd/project/add/domain.js.map +1 -0
- package/dist/cmd/project/add/index.d.ts +2 -0
- package/dist/cmd/project/add/index.d.ts.map +1 -0
- package/dist/cmd/project/add/index.js +35 -0
- package/dist/cmd/project/add/index.js.map +1 -0
- package/dist/cmd/project/add/storage.d.ts +2 -0
- package/dist/cmd/project/add/storage.d.ts.map +1 -0
- package/dist/cmd/project/add/storage.js +123 -0
- package/dist/cmd/project/add/storage.js.map +1 -0
- package/dist/cmd/project/auth/init.js.map +1 -1
- package/dist/cmd/project/index.d.ts.map +1 -1
- package/dist/cmd/project/index.js +7 -0
- package/dist/cmd/project/index.js.map +1 -1
- package/dist/cmd/project/reconcile.d.ts.map +1 -1
- package/dist/cmd/project/reconcile.js +32 -0
- package/dist/cmd/project/reconcile.js.map +1 -1
- package/dist/cmd/support/report.js.map +1 -1
- package/dist/cmd/support/system.js +2 -2
- package/dist/cmd/support/system.js.map +1 -1
- package/dist/config.d.ts +6 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +31 -7
- package/dist/config.js.map +1 -1
- package/dist/errors.d.ts +2 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/repl.js +2 -1
- package/dist/repl.js.map +1 -1
- package/dist/tui/box.d.ts +3 -1
- package/dist/tui/box.d.ts.map +1 -1
- package/dist/tui/box.js +22 -7
- package/dist/tui/box.js.map +1 -1
- package/dist/tui/colors.d.ts +0 -3
- package/dist/tui/colors.d.ts.map +1 -1
- package/dist/tui/colors.js +76 -23
- package/dist/tui/colors.js.map +1 -1
- package/dist/tui/prompt.d.ts +2 -0
- package/dist/tui/prompt.d.ts.map +1 -1
- package/dist/tui/prompt.js +44 -3
- package/dist/tui/prompt.js.map +1 -1
- package/dist/tui/symbols.d.ts +0 -4
- package/dist/tui/symbols.d.ts.map +1 -1
- package/dist/tui/symbols.js +5 -0
- package/dist/tui/symbols.js.map +1 -1
- package/dist/tui.d.ts +8 -0
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +54 -9
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +37 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/version-check.d.ts.map +1 -1
- package/dist/version-check.js +5 -0
- package/dist/version-check.js.map +1 -1
- package/package.json +6 -6
- package/src/agent-detection.ts +457 -160
- package/src/ai-help.ts +391 -0
- package/src/api.ts +1 -1
- package/src/auth.ts +226 -17
- package/src/banner.ts +5 -0
- package/src/cache/agent-intro.ts +61 -0
- package/src/cache/index.ts +2 -0
- package/src/cache/resource-region.ts +28 -7
- package/src/catalyst.ts +16 -0
- package/src/cli.ts +375 -93
- package/src/cmd/ai/detect.ts +52 -0
- package/src/cmd/ai/index.ts +11 -1
- package/src/cmd/ai/intro.ts +154 -0
- package/src/cmd/ai/opencode/run.ts +5 -0
- package/src/cmd/build/ast.ts +97 -0
- package/src/cmd/build/vite/bun-dev-server.ts +2 -0
- package/src/cmd/build/vite/docs-generator.ts +15 -1
- package/src/cmd/build/vite/env-types-generator.ts +145 -0
- package/src/cmd/build/vite/index.ts +15 -0
- package/src/cmd/build/vite/public-asset-path-plugin.ts +8 -2
- package/src/cmd/build/vite/vite-builder.ts +31 -11
- package/src/cmd/cloud/db/create.ts +16 -16
- package/src/cmd/cloud/db/delete.ts +19 -19
- package/src/cmd/cloud/db/get.ts +32 -17
- package/src/cmd/cloud/deploy-fork.ts +2 -0
- package/src/cmd/cloud/deploy.ts +17 -0
- package/src/cmd/cloud/env/import.ts +6 -6
- package/src/cmd/cloud/env/list.ts +11 -11
- package/src/cmd/cloud/env/push.ts +6 -6
- package/src/cmd/cloud/keyvalue/util.ts +3 -3
- package/src/cmd/cloud/machine/list.ts +3 -3
- package/src/cmd/cloud/region/index.ts +3 -3
- package/src/cmd/cloud/region-lookup.ts +82 -22
- package/src/cmd/cloud/sandbox/cp.ts +9 -4
- package/src/cmd/cloud/sandbox/create.ts +1 -1
- package/src/cmd/cloud/sandbox/delete.ts +10 -7
- package/src/cmd/cloud/sandbox/download.ts +8 -5
- package/src/cmd/cloud/sandbox/env.ts +8 -5
- package/src/cmd/cloud/sandbox/exec.ts +10 -5
- package/src/cmd/cloud/sandbox/get.ts +13 -7
- package/src/cmd/cloud/sandbox/list.ts +47 -73
- package/src/cmd/cloud/sandbox/ls.ts +9 -5
- package/src/cmd/cloud/sandbox/mkdir.ts +9 -5
- package/src/cmd/cloud/sandbox/rm.ts +9 -5
- package/src/cmd/cloud/sandbox/rmdir.ts +9 -5
- package/src/cmd/cloud/sandbox/run.ts +1 -1
- package/src/cmd/cloud/sandbox/snapshot/build.ts +31 -31
- package/src/cmd/cloud/sandbox/snapshot/get.ts +17 -17
- package/src/cmd/cloud/sandbox/upload.ts +8 -5
- package/src/cmd/cloud/sandbox/util.ts +15 -14
- package/src/cmd/cloud/ssh.ts +2 -4
- package/src/cmd/cloud/storage/create.ts +16 -16
- package/src/cmd/cloud/storage/delete.ts +19 -19
- package/src/cmd/cloud/storage/get.ts +5 -16
- package/src/cmd/cloud/storage/list.ts +12 -6
- package/src/cmd/cloud/stream/create.ts +8 -4
- package/src/cmd/cloud/stream/delete.ts +28 -4
- package/src/cmd/cloud/stream/get.ts +102 -64
- package/src/cmd/cloud/stream/list.ts +76 -44
- package/src/cmd/cloud/stream/util.ts +39 -3
- package/src/cmd/cloud/vector/util.ts +3 -3
- package/src/cmd/dev/index.ts +4 -4
- package/src/cmd/git/account/add.ts +5 -5
- package/src/cmd/git/list.ts +7 -7
- package/src/cmd/project/add/database.ts +145 -0
- package/src/cmd/project/add/domain.ts +181 -0
- package/src/cmd/project/add/index.ts +35 -0
- package/src/cmd/project/add/storage.ts +147 -0
- package/src/cmd/project/auth/init.ts +6 -6
- package/src/cmd/project/index.ts +7 -0
- package/src/cmd/project/reconcile.ts +40 -0
- package/src/cmd/support/report.ts +5 -5
- package/src/cmd/support/system.ts +2 -2
- package/src/config.ts +40 -12
- package/src/errors.ts +7 -0
- package/src/index.ts +11 -0
- package/src/repl.ts +4 -1
- package/src/tui/box.ts +24 -9
- package/src/tui/colors.ts +83 -26
- package/src/tui/prompt.ts +55 -3
- package/src/tui/symbols.ts +6 -0
- package/src/tui.ts +55 -9
- package/src/types.ts +46 -2
- package/src/version-check.ts +6 -0
package/dist/agent-detection.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { dlopen, FFIType, ptr } from 'bun:ffi';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
2
3
|
/**
|
|
3
4
|
* Map of process names to internal agent short names.
|
|
4
|
-
* The key is the process name (or substring) that appears in the parent process command line.
|
|
5
|
+
* The key is the process name (or substring) that appears in the parent process path or command line.
|
|
5
6
|
* The value is the internal short name used to identify the agent.
|
|
6
7
|
*
|
|
7
8
|
* Process names verified via `agentuity cloud sandbox run --runtime <agent>:latest`:
|
|
@@ -29,212 +30,470 @@ export const KNOWN_AGENTS = [
|
|
|
29
30
|
['windsurf', 'windsurf'],
|
|
30
31
|
['zed', 'zed'],
|
|
31
32
|
['amp', 'amp'],
|
|
33
|
+
['warp', 'warp'],
|
|
32
34
|
// TODO: VSCode Agent Mode detection - need to find a reliable way to detect
|
|
33
35
|
// when VSCode's built-in agent (Copilot Chat) is running commands vs just
|
|
34
36
|
// running in VSCode's integrated terminal. May need env var detection.
|
|
35
37
|
];
|
|
36
38
|
/**
|
|
37
|
-
*
|
|
39
|
+
* Display names for known agents (human-friendly names)
|
|
38
40
|
*/
|
|
39
|
-
|
|
41
|
+
export const AGENT_DISPLAY_NAMES = {
|
|
42
|
+
opencode: 'Open Code',
|
|
43
|
+
codex: 'OpenAI Codex',
|
|
44
|
+
cursor: 'Cursor',
|
|
45
|
+
'claude-code': 'Claude Code',
|
|
46
|
+
copilot: 'GitHub Copilot',
|
|
47
|
+
gemini: 'Gemini',
|
|
48
|
+
cline: 'Cline',
|
|
49
|
+
roo: 'Roo Code',
|
|
50
|
+
windsurf: 'Windsurf',
|
|
51
|
+
zed: 'Zed',
|
|
52
|
+
amp: 'Amp',
|
|
53
|
+
warp: 'Warp',
|
|
54
|
+
};
|
|
40
55
|
/**
|
|
41
|
-
*
|
|
56
|
+
* Get the display name for an agent ID
|
|
42
57
|
*/
|
|
43
|
-
|
|
58
|
+
export function getAgentDisplayName(agentId) {
|
|
59
|
+
return AGENT_DISPLAY_NAMES[agentId] || agentId;
|
|
60
|
+
}
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// FFI-based Fast Process Path Resolution
|
|
63
|
+
// ============================================================================
|
|
64
|
+
const PATH_MAX = 4096; // Linux PATH_MAX, also sufficient for macOS
|
|
65
|
+
const ARG_MAX = 65536; // Maximum command line length
|
|
44
66
|
/**
|
|
45
|
-
*
|
|
67
|
+
* Stub FFI functions for unsupported platforms or when FFI fails to load.
|
|
46
68
|
*/
|
|
47
|
-
const
|
|
69
|
+
const unsupportedFFI = {
|
|
70
|
+
getProcessPath: () => null,
|
|
71
|
+
getParentPid: () => null,
|
|
72
|
+
getProcessCmdline: () => null,
|
|
73
|
+
};
|
|
48
74
|
/**
|
|
49
|
-
*
|
|
75
|
+
* Initialize FFI functions for the current platform.
|
|
76
|
+
* Returns null functions for unsupported platforms or if FFI initialization fails.
|
|
50
77
|
*/
|
|
51
|
-
function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
output += data.toString();
|
|
59
|
-
});
|
|
60
|
-
ps.on('close', () => {
|
|
61
|
-
const trimmed = output.trim();
|
|
62
|
-
if (!trimmed) {
|
|
63
|
-
resolve(undefined);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
// Output format: " PPID COMMAND" (ppid is right-aligned, then space, then command)
|
|
67
|
-
const match = trimmed.match(/^\s*(\d+)\s+(.+)$/);
|
|
68
|
-
if (!match) {
|
|
69
|
-
resolve(undefined);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const ppidStr = match[1];
|
|
73
|
-
const commandStr = match[2];
|
|
74
|
-
if (!ppidStr || !commandStr) {
|
|
75
|
-
resolve(undefined);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const ppid = parseInt(ppidStr, 10);
|
|
79
|
-
const command = commandStr.toLowerCase();
|
|
80
|
-
if (isNaN(ppid) || ppid <= 1 || !command) {
|
|
81
|
-
resolve(undefined);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
resolve({ command, ppid });
|
|
85
|
-
});
|
|
86
|
-
ps.on('error', () => {
|
|
87
|
-
resolve(undefined);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Check if a command matches any known agent
|
|
93
|
-
*/
|
|
94
|
-
function matchAgent(command) {
|
|
95
|
-
for (const [processName, agentName] of KNOWN_AGENTS) {
|
|
96
|
-
if (command.includes(processName)) {
|
|
97
|
-
return agentName;
|
|
78
|
+
function initFFI() {
|
|
79
|
+
try {
|
|
80
|
+
if (process.platform === 'darwin') {
|
|
81
|
+
return initDarwinFFI();
|
|
82
|
+
}
|
|
83
|
+
else if (process.platform === 'linux') {
|
|
84
|
+
return initLinuxFFI();
|
|
98
85
|
}
|
|
99
86
|
}
|
|
100
|
-
|
|
87
|
+
catch (err) {
|
|
88
|
+
// FFI initialization failed (e.g., missing libc on musl/Alpine, dlopen error)
|
|
89
|
+
// Fall back to unsupported stub - agent detection will be skipped
|
|
90
|
+
if (process.env.AGENTUITY_DEBUG_AGENT_DETECTION === '1') {
|
|
91
|
+
console.error('[agent-detection] FFI initialization failed:', err instanceof Error ? err.message : err);
|
|
92
|
+
}
|
|
93
|
+
return unsupportedFFI;
|
|
94
|
+
}
|
|
95
|
+
// Unsupported platform (Windows, etc.)
|
|
96
|
+
return unsupportedFFI;
|
|
101
97
|
}
|
|
102
98
|
/**
|
|
103
|
-
*
|
|
104
|
-
*
|
|
99
|
+
* Initialize macOS FFI functions using libSystem.dylib
|
|
100
|
+
*
|
|
101
|
+
* NOTE: Shared mutable buffers (pathBuf, argBuf, kinfoBuffer) are safe only in
|
|
102
|
+
* single-threaded use. Detection is synchronous and single-threaded, but any
|
|
103
|
+
* future concurrent usage would corrupt these buffers.
|
|
105
104
|
*/
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
105
|
+
function initDarwinFFI() {
|
|
106
|
+
// Shared buffers - reused across calls (single-threaded assumption)
|
|
107
|
+
const pathBuf = new Uint8Array(PATH_MAX);
|
|
108
|
+
const argBuf = new Uint8Array(ARG_MAX);
|
|
109
|
+
// Size of kinfo_proc struct on macOS (arm64 and x86_64)
|
|
110
|
+
const KINFO_PROC_SIZE = 648;
|
|
111
|
+
const kinfoBuffer = new Uint8Array(KINFO_PROC_SIZE);
|
|
112
|
+
// Load libSystem for proc_pidpath and sysctl
|
|
113
|
+
const lib = dlopen('libSystem.dylib', {
|
|
114
|
+
proc_pidpath: {
|
|
115
|
+
args: [FFIType.i32, FFIType.ptr, FFIType.u32],
|
|
116
|
+
returns: FFIType.i32,
|
|
117
|
+
},
|
|
118
|
+
sysctl: {
|
|
119
|
+
args: [FFIType.ptr, FFIType.u32, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.u64],
|
|
120
|
+
returns: FFIType.i32,
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
const getProcessPath = (pid) => {
|
|
124
|
+
if (pid <= 0)
|
|
125
|
+
return null;
|
|
126
|
+
try {
|
|
127
|
+
const len = lib.symbols.proc_pidpath(pid, ptr(pathBuf), PATH_MAX);
|
|
128
|
+
if (len > 0) {
|
|
129
|
+
return new TextDecoder().decode(pathBuf.subarray(0, len)).replace(/\0.*/, '');
|
|
117
130
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
// Ignore errors (process may have died, permission denied, etc.)
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
// Get parent PID using sysctl KERN_PROC_PID
|
|
138
|
+
// CTL_KERN = 1, KERN_PROC = 14, KERN_PROC_PID = 1
|
|
139
|
+
const getParentPid = (pid) => {
|
|
140
|
+
if (pid <= 1)
|
|
141
|
+
return null;
|
|
142
|
+
try {
|
|
143
|
+
const mib = new Int32Array([1, 14, 1, pid]);
|
|
144
|
+
const sizePtr = new BigUint64Array([BigInt(KINFO_PROC_SIZE)]);
|
|
145
|
+
const result = lib.symbols.sysctl(ptr(mib), 4, ptr(kinfoBuffer), ptr(sizePtr), null, 0);
|
|
146
|
+
if (result === 0) {
|
|
147
|
+
// e_ppid offset in kinfo_proc on macOS arm64/x86_64:
|
|
148
|
+
// kp_eproc starts at 296, e_ppid is at offset 264 within kp_eproc
|
|
149
|
+
// Total offset: 560
|
|
150
|
+
const view = new DataView(kinfoBuffer.buffer);
|
|
151
|
+
const ppid = view.getInt32(560, true); // little-endian
|
|
152
|
+
return ppid > 1 ? ppid : null;
|
|
122
153
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
// Ignore errors
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
};
|
|
160
|
+
// Get command line using sysctl KERN_PROCARGS2
|
|
161
|
+
// CTL_KERN = 1, KERN_PROCARGS2 = 49
|
|
162
|
+
const getProcessCmdline = (pid) => {
|
|
163
|
+
if (pid <= 0)
|
|
164
|
+
return null;
|
|
165
|
+
try {
|
|
166
|
+
// MIB for KERN_PROCARGS2: [CTL_KERN, KERN_PROCARGS2, pid]
|
|
167
|
+
const mib = new Int32Array([1, 49, pid]);
|
|
168
|
+
const sizePtr = new BigUint64Array([BigInt(ARG_MAX)]);
|
|
169
|
+
const result = lib.symbols.sysctl(ptr(mib), 3, ptr(argBuf), ptr(sizePtr), null, 0);
|
|
170
|
+
if (result === 0) {
|
|
171
|
+
const size = Number(sizePtr[0]);
|
|
172
|
+
if (size > 0) {
|
|
173
|
+
// KERN_PROCARGS2 format:
|
|
174
|
+
// - 4 bytes: argc (number of arguments)
|
|
175
|
+
// - exec_path\0
|
|
176
|
+
// - padding (zeros until aligned)
|
|
177
|
+
// - arg0\0arg1\0arg2\0...
|
|
178
|
+
// We want to extract exactly argc args (not env vars that follow)
|
|
179
|
+
const data = argBuf.subarray(0, size);
|
|
180
|
+
// Read argc (first 4 bytes, little-endian)
|
|
181
|
+
const argc = new DataView(data.buffer, data.byteOffset).getInt32(0, true);
|
|
182
|
+
let offset = 4;
|
|
183
|
+
// Skip exec_path (find first null)
|
|
184
|
+
while (offset < size && data[offset] !== 0)
|
|
185
|
+
offset++;
|
|
186
|
+
offset++; // Skip the null
|
|
187
|
+
// Skip padding (multiple nulls)
|
|
188
|
+
while (offset < size && data[offset] === 0)
|
|
189
|
+
offset++;
|
|
190
|
+
// Now we're at the arguments - collect exactly argc args
|
|
191
|
+
const args = [];
|
|
192
|
+
let start = offset;
|
|
193
|
+
for (let i = offset; i < size; i++) {
|
|
194
|
+
if (data[i] === 0) {
|
|
195
|
+
if (i > start) {
|
|
196
|
+
args.push(new TextDecoder().decode(data.subarray(start, i)));
|
|
197
|
+
}
|
|
198
|
+
start = i + 1;
|
|
199
|
+
// Stop after collecting argc args
|
|
200
|
+
if (args.length >= argc)
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return args.join(' ');
|
|
205
|
+
}
|
|
127
206
|
}
|
|
128
|
-
// Walk up to parent
|
|
129
|
-
return walkTree(info.ppid, depth + 1);
|
|
130
207
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
resolve(undefined);
|
|
134
|
-
return;
|
|
208
|
+
catch {
|
|
209
|
+
// Ignore errors
|
|
135
210
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
});
|
|
211
|
+
return null;
|
|
212
|
+
};
|
|
213
|
+
return { getProcessPath, getParentPid, getProcessCmdline };
|
|
140
214
|
}
|
|
141
215
|
/**
|
|
142
|
-
*
|
|
143
|
-
* Call this early in CLI startup to begin detection in the background.
|
|
216
|
+
* Initialize Linux FFI functions using libc.so.6
|
|
144
217
|
*/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
218
|
+
function initLinuxFFI() {
|
|
219
|
+
const pathBuf = new Uint8Array(PATH_MAX);
|
|
220
|
+
const lib = dlopen('libc.so.6', {
|
|
221
|
+
readlink: {
|
|
222
|
+
args: [FFIType.cstring, FFIType.ptr, FFIType.u64],
|
|
223
|
+
returns: FFIType.i64,
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
const getProcessPath = (pid) => {
|
|
227
|
+
if (pid <= 0)
|
|
228
|
+
return null;
|
|
229
|
+
try {
|
|
230
|
+
const procPath = Buffer.from(`/proc/${pid}/exe\0`);
|
|
231
|
+
const len = Number(lib.symbols.readlink(ptr(procPath), ptr(pathBuf), PATH_MAX));
|
|
232
|
+
if (len > 0) {
|
|
233
|
+
return new TextDecoder().decode(pathBuf.subarray(0, len));
|
|
156
234
|
}
|
|
157
|
-
|
|
158
|
-
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Ignore errors (process may have died, permission denied, etc.)
|
|
238
|
+
}
|
|
239
|
+
return null;
|
|
240
|
+
};
|
|
241
|
+
const getParentPid = (pid) => {
|
|
242
|
+
if (pid <= 1)
|
|
243
|
+
return null;
|
|
244
|
+
try {
|
|
245
|
+
// Read /proc/{pid}/stat to get parent PID (4th field)
|
|
246
|
+
const statPath = `/proc/${pid}/stat`;
|
|
247
|
+
const content = readFileSync(statPath, 'utf-8');
|
|
248
|
+
// Format: pid (comm) state ppid ...
|
|
249
|
+
// Need to handle comm with spaces/parens: find last ')' then parse
|
|
250
|
+
const lastParen = content.lastIndexOf(')');
|
|
251
|
+
if (lastParen === -1)
|
|
252
|
+
return null;
|
|
253
|
+
const rest = content.slice(lastParen + 2); // Skip ') '
|
|
254
|
+
const fields = rest.split(' ');
|
|
255
|
+
const ppidField = fields[1]; // ppid is 2nd field after state
|
|
256
|
+
if (!ppidField)
|
|
257
|
+
return null;
|
|
258
|
+
const ppid = parseInt(ppidField, 10);
|
|
259
|
+
return isNaN(ppid) || ppid <= 1 ? null : ppid;
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// Ignore errors
|
|
263
|
+
}
|
|
264
|
+
return null;
|
|
265
|
+
};
|
|
266
|
+
// Read command line from /proc/{pid}/cmdline (null-separated args)
|
|
267
|
+
const getProcessCmdline = (pid) => {
|
|
268
|
+
if (pid <= 0)
|
|
269
|
+
return null;
|
|
270
|
+
try {
|
|
271
|
+
const cmdlinePath = `/proc/${pid}/cmdline`;
|
|
272
|
+
const content = readFileSync(cmdlinePath);
|
|
273
|
+
if (content.length > 0) {
|
|
274
|
+
// Replace null bytes with spaces to get full command line
|
|
275
|
+
return new TextDecoder().decode(content).replace(/\0/g, ' ').trim();
|
|
159
276
|
}
|
|
160
277
|
}
|
|
161
|
-
|
|
162
|
-
|
|
278
|
+
catch {
|
|
279
|
+
// Ignore errors
|
|
280
|
+
}
|
|
281
|
+
return null;
|
|
282
|
+
};
|
|
283
|
+
return { getProcessPath, getParentPid, getProcessCmdline };
|
|
284
|
+
}
|
|
285
|
+
// Initialize FFI functions lazily
|
|
286
|
+
let ffi = null;
|
|
287
|
+
function getFFI() {
|
|
288
|
+
if (!ffi) {
|
|
289
|
+
ffi = initFFI();
|
|
290
|
+
}
|
|
291
|
+
return ffi;
|
|
163
292
|
}
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// Agent Detection Logic
|
|
295
|
+
// ============================================================================
|
|
164
296
|
/**
|
|
165
|
-
*
|
|
166
|
-
* If detection has already completed, the callback is invoked immediately.
|
|
167
|
-
* This is non-blocking and does not return a promise.
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```typescript
|
|
171
|
-
* onAgentDetected((agent) => {
|
|
172
|
-
* if (agent) {
|
|
173
|
-
* console.log(`Detected agent: ${agent}`);
|
|
174
|
-
* }
|
|
175
|
-
* });
|
|
176
|
-
* ```
|
|
297
|
+
* Cached detection result (null = not yet run, undefined = no agent detected)
|
|
177
298
|
*/
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
299
|
+
let cachedResult = null;
|
|
300
|
+
/**
|
|
301
|
+
* Check if a path's basename matches any known agent
|
|
302
|
+
*/
|
|
303
|
+
function matchAgentPath(path) {
|
|
304
|
+
// Extract basename from path
|
|
305
|
+
const basename = path.split('/').pop()?.toLowerCase() ?? '';
|
|
306
|
+
for (const [processName, agentName] of KNOWN_AGENTS) {
|
|
307
|
+
if (basename.includes(processName)) {
|
|
308
|
+
return agentName;
|
|
183
309
|
}
|
|
184
|
-
|
|
185
|
-
|
|
310
|
+
}
|
|
311
|
+
return undefined;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Check if a cmdline matches any known agent.
|
|
315
|
+
* Only checks argv[0] and arguments that look like executable paths,
|
|
316
|
+
* NOT environment variables or arbitrary path strings.
|
|
317
|
+
*/
|
|
318
|
+
function matchAgentCmdline(cmdline) {
|
|
319
|
+
// Split cmdline into arguments (null-separated on macOS/Linux, but we get space-separated here)
|
|
320
|
+
// The cmdline format from our FFI is: "cmd arg1 arg2 ENV1=val1 ENV2=val2..."
|
|
321
|
+
// We only want to check the command and args that look like executables
|
|
322
|
+
const parts = cmdline.split(/\s+/);
|
|
323
|
+
for (const part of parts) {
|
|
324
|
+
// Skip environment variables (contain =)
|
|
325
|
+
if (part.includes('=')) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
// Check if this looks like an executable path or command
|
|
329
|
+
// - Starts with / (absolute path)
|
|
330
|
+
// - Is a simple command name (no path separators, no special chars)
|
|
331
|
+
const isPath = part.startsWith('/');
|
|
332
|
+
const isSimpleCommand = !part.includes('/') && !part.includes('=') && part.length < 50;
|
|
333
|
+
if (isPath || isSimpleCommand) {
|
|
334
|
+
const basename = part.split('/').pop()?.toLowerCase() ?? '';
|
|
335
|
+
for (const [processName, agentName] of KNOWN_AGENTS) {
|
|
336
|
+
if (basename.includes(processName)) {
|
|
337
|
+
return agentName;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
186
340
|
}
|
|
187
|
-
return;
|
|
188
341
|
}
|
|
189
|
-
|
|
190
|
-
detectionCallbacks.push(callback);
|
|
342
|
+
return undefined;
|
|
191
343
|
}
|
|
192
344
|
/**
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* Use this for synchronous access when you don't want to wait for detection.
|
|
345
|
+
* Check if stdin is connected to a TTY (interactive terminal).
|
|
346
|
+
* When humans type commands, stdin is usually a TTY.
|
|
347
|
+
* When agents run commands programmatically, stdin is usually piped/closed.
|
|
198
348
|
*/
|
|
199
|
-
|
|
200
|
-
return
|
|
349
|
+
function isInteractiveSession() {
|
|
350
|
+
return process.stdin.isTTY === true;
|
|
351
|
+
}
|
|
352
|
+
// Enable debug output with AGENTUITY_DEBUG_AGENT_DETECTION=1
|
|
353
|
+
const DEBUG = process.env.AGENTUITY_DEBUG_AGENT_DETECTION === '1';
|
|
354
|
+
function debugLog(...args) {
|
|
355
|
+
if (DEBUG) {
|
|
356
|
+
console.error('[agent-detection]', ...args);
|
|
357
|
+
}
|
|
201
358
|
}
|
|
202
359
|
/**
|
|
203
|
-
*
|
|
204
|
-
*
|
|
360
|
+
* Synchronously detect the parent agent by walking up the process tree.
|
|
361
|
+
* Uses FFI for fast process path and command line resolution.
|
|
205
362
|
*
|
|
206
|
-
*
|
|
363
|
+
* Detection strategy:
|
|
364
|
+
* - If stdin is a TTY (interactive session), don't report as agent
|
|
365
|
+
* (human is typing commands, even if inside an agent's terminal)
|
|
366
|
+
* - If stdin is NOT a TTY, check the process tree for known agents
|
|
207
367
|
*/
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
368
|
+
function detectParentAgent() {
|
|
369
|
+
debugLog('Starting detection, PID:', process.pid, 'PPID:', process.ppid);
|
|
370
|
+
debugLog('stdin.isTTY:', process.stdin.isTTY);
|
|
371
|
+
// Dump relevant env vars for debugging agent detection
|
|
372
|
+
if (DEBUG) {
|
|
373
|
+
const relevantEnvVars = Object.entries(process.env)
|
|
374
|
+
.filter(([key]) => key.startsWith('WARP') ||
|
|
375
|
+
key.startsWith('TERM') ||
|
|
376
|
+
key.startsWith('AGENTUITY') ||
|
|
377
|
+
key === 'SHELL' ||
|
|
378
|
+
key === 'LC_TERMINAL' ||
|
|
379
|
+
key === 'ITERM_SESSION_ID' ||
|
|
380
|
+
key === 'VSCODE_INJECTION' ||
|
|
381
|
+
key === 'CURSOR_TRACE_ID')
|
|
382
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
383
|
+
.join(', ');
|
|
384
|
+
debugLog('Relevant env vars:', relevantEnvVars || '(none)');
|
|
385
|
+
debugLog('WARP_AGENT_MODE:', process.env.WARP_AGENT_MODE ?? '(not set)');
|
|
211
386
|
}
|
|
387
|
+
// Short-circuit: if AGENTUITY_AGENT_MODE is set, use it directly
|
|
388
|
+
// Use "false", "0", or "none" to explicitly disable detection
|
|
389
|
+
const agentMode = process.env.AGENTUITY_AGENT_MODE;
|
|
390
|
+
if (agentMode) {
|
|
391
|
+
if (agentMode === 'false' || agentMode === '0' || agentMode === 'none') {
|
|
392
|
+
debugLog('AGENTUITY_AGENT_MODE explicitly disabled:', agentMode);
|
|
393
|
+
return undefined;
|
|
394
|
+
}
|
|
395
|
+
debugLog('Using AGENTUITY_AGENT_MODE:', agentMode);
|
|
396
|
+
return agentMode;
|
|
397
|
+
}
|
|
398
|
+
// Warp terminal: detect via WARP_AGENT_MODE env var (set by Warp AI)
|
|
399
|
+
// Note: Warp doesn't currently set this, but will in the future
|
|
400
|
+
if (process.env.WARP_AGENT_MODE === 'true') {
|
|
401
|
+
debugLog('Detected Warp AI via WARP_AGENT_MODE=true');
|
|
402
|
+
return 'warp';
|
|
403
|
+
}
|
|
404
|
+
// If this is an interactive session (TTY), assume human is running the command
|
|
405
|
+
// Note: Warp AI also runs with TTY=true, so Warp users should set
|
|
406
|
+
// AGENTUITY_AGENT_MODE=warp until Warp sets WARP_AGENT_MODE=true
|
|
407
|
+
if (isInteractiveSession()) {
|
|
408
|
+
debugLog('Interactive session (TTY), skipping detection');
|
|
409
|
+
return undefined;
|
|
410
|
+
}
|
|
411
|
+
// Unsupported on Windows (for now)
|
|
412
|
+
if (process.platform === 'win32') {
|
|
413
|
+
debugLog('Windows not supported');
|
|
414
|
+
return undefined;
|
|
415
|
+
}
|
|
416
|
+
const { getProcessPath, getParentPid, getProcessCmdline } = getFFI();
|
|
417
|
+
// Guard for no parent process (e.g., PID 1 in containers)
|
|
418
|
+
const ppid = process.ppid;
|
|
419
|
+
if (!ppid || ppid <= 1) {
|
|
420
|
+
debugLog('No parent process (ppid:', ppid, ')');
|
|
421
|
+
return undefined;
|
|
422
|
+
}
|
|
423
|
+
// Walk up the process tree looking for known agents
|
|
424
|
+
const maxDepth = 10;
|
|
425
|
+
let currentPid = ppid;
|
|
426
|
+
for (let depth = 0; depth < maxDepth && currentPid > 1; depth++) {
|
|
427
|
+
// Check the executable path for agent match
|
|
428
|
+
const path = getProcessPath(currentPid);
|
|
429
|
+
debugLog(`[${depth}] PID ${currentPid} path:`, path);
|
|
430
|
+
if (path) {
|
|
431
|
+
const agent = matchAgentPath(path);
|
|
432
|
+
if (agent) {
|
|
433
|
+
debugLog(`[${depth}] Matched agent from path:`, agent);
|
|
434
|
+
return agent;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// Check the command line (for agents running as node/bun scripts)
|
|
438
|
+
const cmdline = getProcessCmdline(currentPid);
|
|
439
|
+
debugLog(`[${depth}] PID ${currentPid} cmdline:`, cmdline?.substring(0, 200) + (cmdline && cmdline.length > 200 ? '...' : ''));
|
|
440
|
+
if (cmdline) {
|
|
441
|
+
const agent = matchAgentCmdline(cmdline);
|
|
442
|
+
if (agent) {
|
|
443
|
+
debugLog(`[${depth}] Matched agent from cmdline:`, agent);
|
|
444
|
+
return agent;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
// Move up
|
|
448
|
+
const parentPid = getParentPid(currentPid);
|
|
449
|
+
debugLog(`[${depth}] Parent of ${currentPid}:`, parentPid);
|
|
450
|
+
if (!parentPid)
|
|
451
|
+
break;
|
|
452
|
+
currentPid = parentPid;
|
|
453
|
+
}
|
|
454
|
+
debugLog('No agent found');
|
|
455
|
+
return undefined;
|
|
212
456
|
}
|
|
213
457
|
/**
|
|
214
|
-
*
|
|
215
|
-
* Returns the agent
|
|
458
|
+
* Get the executing agent if the CLI is being run from a known coding agent.
|
|
459
|
+
* Returns the agent ID if detected, undefined otherwise.
|
|
216
460
|
*
|
|
217
|
-
* This function
|
|
218
|
-
*
|
|
461
|
+
* This function runs synchronously using FFI for fast process path resolution.
|
|
462
|
+
* Results are cached after the first call.
|
|
219
463
|
*
|
|
220
464
|
* @example
|
|
221
465
|
* ```typescript
|
|
222
|
-
* const agent =
|
|
466
|
+
* const agent = getExecutingAgent();
|
|
223
467
|
* if (agent) {
|
|
224
468
|
* logger.debug(`Running from agent: ${agent}`);
|
|
225
469
|
* }
|
|
226
470
|
* ```
|
|
227
471
|
*/
|
|
228
|
-
export
|
|
229
|
-
// Return cached result if
|
|
472
|
+
export function getExecutingAgent() {
|
|
473
|
+
// Return cached result if already detected
|
|
230
474
|
if (cachedResult !== null) {
|
|
231
|
-
return cachedResult;
|
|
475
|
+
return cachedResult ?? undefined;
|
|
232
476
|
}
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
477
|
+
// Run detection and cache
|
|
478
|
+
cachedResult = detectParentAgent();
|
|
479
|
+
return cachedResult;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Get environment variables to pass to subprocesses for agent detection.
|
|
483
|
+
* This allows child processes to skip re-detection by using the cached result.
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* ```typescript
|
|
487
|
+
* const proc = Bun.spawn(['bun', 'run', 'dev'], {
|
|
488
|
+
* env: { ...process.env, ...getAgentEnv() },
|
|
489
|
+
* });
|
|
490
|
+
* ```
|
|
491
|
+
*/
|
|
492
|
+
export function getAgentEnv() {
|
|
493
|
+
const agent = getExecutingAgent();
|
|
494
|
+
if (agent) {
|
|
495
|
+
return { AGENTUITY_AGENT_MODE: agent };
|
|
236
496
|
}
|
|
237
|
-
|
|
238
|
-
return detectionPromise;
|
|
497
|
+
return {};
|
|
239
498
|
}
|
|
240
499
|
//# sourceMappingURL=agent-detection.js.map
|