@baton-dx/cli 0.1.3 → 0.2.0
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 +10 -0
- package/dist/{agent-detection-C5gaTtah.mjs → agent-detection-DTiVeO5W.mjs} +329 -36
- package/dist/agent-detection-DTiVeO5W.mjs.map +1 -0
- package/dist/{agent-detection-BW5-jGuR.mjs → agent-detection-l61K-AbU.mjs} +1 -1
- package/dist/{context-detection-mMNLg_4F.mjs → context-detection-DqOTnD6_.mjs} +5 -5
- package/dist/context-detection-DqOTnD6_.mjs.map +1 -0
- package/dist/{create-Diqnd3ci.mjs → create-C0x3t4GX.mjs} +5 -4
- package/dist/{create-Diqnd3ci.mjs.map → create-C0x3t4GX.mjs.map} +1 -1
- package/dist/index.mjs +8 -7
- package/dist/index.mjs.map +1 -1
- package/dist/{list-B5xUVBTU.mjs → list-CGmYHSHW.mjs} +4 -3
- package/dist/{list-B5xUVBTU.mjs.map → list-CGmYHSHW.mjs.map} +1 -1
- package/dist/{remove-6S8F9xcE.mjs → remove-BBs6Mv8t.mjs} +2 -2
- package/dist/{remove-6S8F9xcE.mjs.map → remove-BBs6Mv8t.mjs.map} +1 -1
- package/dist/{src-Dh0ZvHbV.mjs → src-DBbk6iAs.mjs} +125 -50
- package/dist/src-DBbk6iAs.mjs.map +1 -0
- package/package.json +2 -4
- package/dist/agent-detection-C5gaTtah.mjs.map +0 -1
- package/dist/context-detection-mMNLg_4F.mjs.map +0 -1
- package/dist/execa-RdtdAT4S.mjs +0 -6343
- package/dist/execa-RdtdAT4S.mjs.map +0 -1
- package/dist/src-Dh0ZvHbV.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -44,6 +44,16 @@ baton sync
|
|
|
44
44
|
| GitHub Copilot | `github-copilot` | Roo | `roo` |
|
|
45
45
|
| Junie | `junie` | Trae | `trae` |
|
|
46
46
|
|
|
47
|
+
## Official Source Repository
|
|
48
|
+
|
|
49
|
+
Baton's own configurations are published as [`baton-dx-source`](https://github.com/baton-dx/baton-dx-source) — a real-world example of sources and profiles in action:
|
|
50
|
+
|
|
51
|
+
| Profile | Command | Audience |
|
|
52
|
+
| ------- | ------- | -------- |
|
|
53
|
+
| **maintainer** | `baton init --profile github:baton-dx/baton-dx-source/maintainer` | Contributors to this repo |
|
|
54
|
+
| **creator** | `baton init --profile github:baton-dx/baton-dx-source/creator` | Developers building their own sources and profiles |
|
|
55
|
+
| **consumer** | `baton init --profile github:baton-dx/baton-dx-source/consumer` | Developers using Baton in their projects |
|
|
56
|
+
|
|
47
57
|
## Documentation
|
|
48
58
|
|
|
49
59
|
- [Installation](docs/01-installation.md) — Prerequisites and install methods
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { access, constants } from "node:fs/promises";
|
|
2
|
+
import { access, constants, readdir } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
5
6
|
|
|
6
7
|
//#region ../agent-paths/src/registry.ts
|
|
7
8
|
/**
|
|
@@ -36,7 +37,15 @@ const AGENT_PATHS = [
|
|
|
36
37
|
project: ".claude/commands/{name}.md",
|
|
37
38
|
global: "~/.claude/commands/{name}.md"
|
|
38
39
|
},
|
|
39
|
-
|
|
40
|
+
detectionConfig: { groups: [[{
|
|
41
|
+
type: "binary",
|
|
42
|
+
name: "claude",
|
|
43
|
+
versionPattern: /claude/i
|
|
44
|
+
}], [{
|
|
45
|
+
type: "directory",
|
|
46
|
+
path: "~/.claude/",
|
|
47
|
+
markerFile: "settings.json"
|
|
48
|
+
}]] },
|
|
40
49
|
legacy: {}
|
|
41
50
|
},
|
|
42
51
|
{
|
|
@@ -66,7 +75,21 @@ const AGENT_PATHS = [
|
|
|
66
75
|
project: ".cursor/commands/{name}.md",
|
|
67
76
|
global: "~/.cursor/commands/{name}.md"
|
|
68
77
|
},
|
|
69
|
-
|
|
78
|
+
detectionConfig: { groups: [
|
|
79
|
+
[{
|
|
80
|
+
type: "app",
|
|
81
|
+
name: "Cursor.app"
|
|
82
|
+
}],
|
|
83
|
+
[{
|
|
84
|
+
type: "binary",
|
|
85
|
+
name: "cursor"
|
|
86
|
+
}],
|
|
87
|
+
[{
|
|
88
|
+
type: "directory",
|
|
89
|
+
path: "~/.cursor/",
|
|
90
|
+
markerFile: "extensions"
|
|
91
|
+
}]
|
|
92
|
+
] },
|
|
70
93
|
legacy: { rules: [".cursorrules"] }
|
|
71
94
|
},
|
|
72
95
|
{
|
|
@@ -96,7 +119,21 @@ const AGENT_PATHS = [
|
|
|
96
119
|
project: ".windsurf/workflows/{name}.md",
|
|
97
120
|
global: "~/.codeium/windsurf/workflows/{name}.md"
|
|
98
121
|
},
|
|
99
|
-
|
|
122
|
+
detectionConfig: { groups: [
|
|
123
|
+
[{
|
|
124
|
+
type: "app",
|
|
125
|
+
name: "Windsurf.app"
|
|
126
|
+
}],
|
|
127
|
+
[{
|
|
128
|
+
type: "binary",
|
|
129
|
+
name: "windsurf"
|
|
130
|
+
}],
|
|
131
|
+
[{
|
|
132
|
+
type: "directory",
|
|
133
|
+
path: "~/.codeium/windsurf/",
|
|
134
|
+
markerFile: "settings.json"
|
|
135
|
+
}]
|
|
136
|
+
] },
|
|
100
137
|
legacy: { rules: [".windsurfrules"] }
|
|
101
138
|
},
|
|
102
139
|
{
|
|
@@ -126,7 +163,26 @@ const AGENT_PATHS = [
|
|
|
126
163
|
project: ".agent/workflows/{name}.md",
|
|
127
164
|
global: "~/.gemini/antigravity/workflows/{name}.md"
|
|
128
165
|
},
|
|
129
|
-
|
|
166
|
+
detectionConfig: { groups: [
|
|
167
|
+
[{
|
|
168
|
+
type: "app",
|
|
169
|
+
name: "Antigravity.app"
|
|
170
|
+
}],
|
|
171
|
+
[{
|
|
172
|
+
type: "binary",
|
|
173
|
+
name: "agy"
|
|
174
|
+
}],
|
|
175
|
+
[{
|
|
176
|
+
type: "binary",
|
|
177
|
+
name: "antigravity",
|
|
178
|
+
platforms: ["linux"]
|
|
179
|
+
}],
|
|
180
|
+
[{
|
|
181
|
+
type: "directory",
|
|
182
|
+
path: "~/.gemini/antigravity/",
|
|
183
|
+
markerFile: "settings.json"
|
|
184
|
+
}]
|
|
185
|
+
] },
|
|
130
186
|
legacy: {}
|
|
131
187
|
},
|
|
132
188
|
{
|
|
@@ -156,7 +212,15 @@ const AGENT_PATHS = [
|
|
|
156
212
|
project: ".codex/commands/{name}.md",
|
|
157
213
|
global: "~/.codex/commands/{name}.md"
|
|
158
214
|
},
|
|
159
|
-
|
|
215
|
+
detectionConfig: { groups: [[{
|
|
216
|
+
type: "binary",
|
|
217
|
+
name: "codex",
|
|
218
|
+
versionPattern: /codex/i
|
|
219
|
+
}], [{
|
|
220
|
+
type: "directory",
|
|
221
|
+
path: "~/.codex/",
|
|
222
|
+
markerFile: "config.toml"
|
|
223
|
+
}]] },
|
|
160
224
|
legacy: {}
|
|
161
225
|
},
|
|
162
226
|
{
|
|
@@ -186,7 +250,22 @@ const AGENT_PATHS = [
|
|
|
186
250
|
project: ".github/copilot/commands/{name}.md",
|
|
187
251
|
global: "~/.github/copilot/commands/{name}.md"
|
|
188
252
|
},
|
|
189
|
-
|
|
253
|
+
detectionConfig: { groups: [
|
|
254
|
+
[{
|
|
255
|
+
type: "binary",
|
|
256
|
+
name: "copilot",
|
|
257
|
+
versionPattern: /copilot|github/i
|
|
258
|
+
}],
|
|
259
|
+
[{
|
|
260
|
+
type: "vscode-extension",
|
|
261
|
+
extensionId: "GitHub.copilot",
|
|
262
|
+
editors: ["vscode", "cursor"]
|
|
263
|
+
}],
|
|
264
|
+
[{
|
|
265
|
+
type: "directory",
|
|
266
|
+
path: "~/.github/copilot/"
|
|
267
|
+
}]
|
|
268
|
+
] },
|
|
190
269
|
legacy: {}
|
|
191
270
|
},
|
|
192
271
|
{
|
|
@@ -216,7 +295,15 @@ const AGENT_PATHS = [
|
|
|
216
295
|
project: ".opencode/commands/{name}.md",
|
|
217
296
|
global: "~/.config/opencode/commands/{name}.md"
|
|
218
297
|
},
|
|
219
|
-
|
|
298
|
+
detectionConfig: { groups: [[{
|
|
299
|
+
type: "binary",
|
|
300
|
+
name: "opencode",
|
|
301
|
+
versionPattern: /opencode|sst/i
|
|
302
|
+
}], [{
|
|
303
|
+
type: "directory",
|
|
304
|
+
path: "~/.config/opencode/",
|
|
305
|
+
markerFile: "config.yaml"
|
|
306
|
+
}]] },
|
|
220
307
|
legacy: {}
|
|
221
308
|
},
|
|
222
309
|
{
|
|
@@ -246,7 +333,14 @@ const AGENT_PATHS = [
|
|
|
246
333
|
project: ".agents/commands/{name}.md",
|
|
247
334
|
global: "~/.config/agents/commands/{name}.md"
|
|
248
335
|
},
|
|
249
|
-
|
|
336
|
+
detectionConfig: { groups: [[{
|
|
337
|
+
type: "binary",
|
|
338
|
+
name: "amp",
|
|
339
|
+
versionPattern: /amp|sourcegraph/i
|
|
340
|
+
}], [{
|
|
341
|
+
type: "directory",
|
|
342
|
+
path: "~/.ampcache/"
|
|
343
|
+
}]] },
|
|
250
344
|
legacy: {}
|
|
251
345
|
},
|
|
252
346
|
{
|
|
@@ -276,7 +370,21 @@ const AGENT_PATHS = [
|
|
|
276
370
|
project: ".kiro/commands/{name}.md",
|
|
277
371
|
global: "~/.kiro/commands/{name}.md"
|
|
278
372
|
},
|
|
279
|
-
|
|
373
|
+
detectionConfig: { groups: [
|
|
374
|
+
[{
|
|
375
|
+
type: "app",
|
|
376
|
+
name: "Kiro.app"
|
|
377
|
+
}],
|
|
378
|
+
[{
|
|
379
|
+
type: "binary",
|
|
380
|
+
name: "kiro"
|
|
381
|
+
}],
|
|
382
|
+
[{
|
|
383
|
+
type: "directory",
|
|
384
|
+
path: "~/.kiro/",
|
|
385
|
+
markerFile: "settings.json"
|
|
386
|
+
}]
|
|
387
|
+
] },
|
|
280
388
|
legacy: {}
|
|
281
389
|
},
|
|
282
390
|
{
|
|
@@ -306,7 +414,21 @@ const AGENT_PATHS = [
|
|
|
306
414
|
project: ".zed/commands/{name}.md",
|
|
307
415
|
global: "~/.zed/commands/{name}.md"
|
|
308
416
|
},
|
|
309
|
-
|
|
417
|
+
detectionConfig: { groups: [
|
|
418
|
+
[{
|
|
419
|
+
type: "app",
|
|
420
|
+
name: "Zed.app"
|
|
421
|
+
}],
|
|
422
|
+
[{
|
|
423
|
+
type: "binary",
|
|
424
|
+
name: "zed"
|
|
425
|
+
}],
|
|
426
|
+
[{
|
|
427
|
+
type: "directory",
|
|
428
|
+
path: "~/.config/zed/",
|
|
429
|
+
markerFile: "settings.json"
|
|
430
|
+
}]
|
|
431
|
+
] },
|
|
310
432
|
legacy: {}
|
|
311
433
|
},
|
|
312
434
|
{
|
|
@@ -336,7 +458,19 @@ const AGENT_PATHS = [
|
|
|
336
458
|
project: ".cline/commands/{name}.md",
|
|
337
459
|
global: "~/.cline/commands/{name}.md"
|
|
338
460
|
},
|
|
339
|
-
|
|
461
|
+
detectionConfig: { groups: [[{
|
|
462
|
+
type: "vscode-extension",
|
|
463
|
+
extensionId: "saoudrizwan.claude-dev",
|
|
464
|
+
editors: [
|
|
465
|
+
"vscode",
|
|
466
|
+
"cursor",
|
|
467
|
+
"windsurf"
|
|
468
|
+
]
|
|
469
|
+
}], [{
|
|
470
|
+
type: "directory",
|
|
471
|
+
path: "~/.cline/",
|
|
472
|
+
markerFile: "settings.json"
|
|
473
|
+
}]] },
|
|
340
474
|
legacy: {}
|
|
341
475
|
},
|
|
342
476
|
{
|
|
@@ -366,7 +500,19 @@ const AGENT_PATHS = [
|
|
|
366
500
|
project: ".roo/commands/{name}.md",
|
|
367
501
|
global: "~/.roo/commands/{name}.md"
|
|
368
502
|
},
|
|
369
|
-
|
|
503
|
+
detectionConfig: { groups: [[{
|
|
504
|
+
type: "vscode-extension",
|
|
505
|
+
extensionId: "RooVeterinaryInc.roo-cline",
|
|
506
|
+
editors: [
|
|
507
|
+
"vscode",
|
|
508
|
+
"cursor",
|
|
509
|
+
"windsurf"
|
|
510
|
+
]
|
|
511
|
+
}], [{
|
|
512
|
+
type: "directory",
|
|
513
|
+
path: "~/.roo/",
|
|
514
|
+
markerFile: "settings.json"
|
|
515
|
+
}]] },
|
|
370
516
|
legacy: {}
|
|
371
517
|
},
|
|
372
518
|
{
|
|
@@ -396,7 +542,14 @@ const AGENT_PATHS = [
|
|
|
396
542
|
project: ".junie/commands/{name}.md",
|
|
397
543
|
global: "~/.junie/commands/{name}.md"
|
|
398
544
|
},
|
|
399
|
-
|
|
545
|
+
detectionConfig: { groups: [[{
|
|
546
|
+
type: "jetbrains-plugin",
|
|
547
|
+
pluginId: "junie"
|
|
548
|
+
}], [{
|
|
549
|
+
type: "directory",
|
|
550
|
+
path: "~/.junie/",
|
|
551
|
+
markerFile: "settings.json"
|
|
552
|
+
}]] },
|
|
400
553
|
legacy: {}
|
|
401
554
|
},
|
|
402
555
|
{
|
|
@@ -426,52 +579,192 @@ const AGENT_PATHS = [
|
|
|
426
579
|
project: ".trae/commands/{name}.md",
|
|
427
580
|
global: "~/.trae/commands/{name}.md"
|
|
428
581
|
},
|
|
429
|
-
|
|
582
|
+
detectionConfig: { groups: [[{
|
|
583
|
+
type: "app",
|
|
584
|
+
name: "Trae.app"
|
|
585
|
+
}], [{
|
|
586
|
+
type: "directory",
|
|
587
|
+
path: "~/.trae/",
|
|
588
|
+
markerFile: "settings.json"
|
|
589
|
+
}]] },
|
|
430
590
|
legacy: {}
|
|
431
591
|
}
|
|
432
592
|
];
|
|
433
593
|
|
|
434
594
|
//#endregion
|
|
435
|
-
//#region ../core/src/detection/
|
|
595
|
+
//#region ../core/src/detection/mechanisms.ts
|
|
436
596
|
/**
|
|
437
|
-
*
|
|
597
|
+
* Execute a command and return stdout/stderr as a promise.
|
|
598
|
+
* Rejects on non-zero exit code or timeout.
|
|
438
599
|
*/
|
|
439
|
-
|
|
600
|
+
function execAsync(command, args, options = {}) {
|
|
601
|
+
return new Promise((resolve, reject) => {
|
|
602
|
+
execFile(command, args, options, (error, stdout, stderr) => {
|
|
603
|
+
if (error) reject(error);
|
|
604
|
+
else resolve({
|
|
605
|
+
stdout: String(stdout),
|
|
606
|
+
stderr: String(stderr)
|
|
607
|
+
});
|
|
608
|
+
});
|
|
609
|
+
});
|
|
610
|
+
}
|
|
440
611
|
/**
|
|
441
|
-
* Check if a
|
|
612
|
+
* Check if a binary exists in PATH and optionally verify its identity via version output.
|
|
613
|
+
* Prevents false positives from binary name collisions (e.g., `opencode` by Litestar vs SST).
|
|
442
614
|
*/
|
|
443
|
-
async function
|
|
615
|
+
async function checkBinary(check) {
|
|
616
|
+
if (check.platforms && !check.platforms.includes(process.platform)) return false;
|
|
617
|
+
const lookupCommand = process.platform === "win32" ? "where" : "which";
|
|
444
618
|
try {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return
|
|
619
|
+
await execAsync(lookupCommand, [check.name]);
|
|
620
|
+
} catch {
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
if (!check.versionPattern) return true;
|
|
624
|
+
const versionFlag = check.versionFlag ?? "--version";
|
|
625
|
+
try {
|
|
626
|
+
const { stdout, stderr } = await execAsync(check.name, [versionFlag], { timeout: 5e3 });
|
|
627
|
+
const output = `${stdout}\n${stderr}`;
|
|
628
|
+
return check.versionPattern.test(output);
|
|
448
629
|
} catch {
|
|
449
630
|
return false;
|
|
450
631
|
}
|
|
451
632
|
}
|
|
452
633
|
/**
|
|
453
|
-
* Check if a directory exists
|
|
634
|
+
* Check if a directory exists and optionally contains a marker file.
|
|
635
|
+
* Prevents false positives from leftover empty directories (e.g., ~/.cline/ without settings.json).
|
|
454
636
|
*/
|
|
455
|
-
async function
|
|
637
|
+
async function checkDirectory(check) {
|
|
638
|
+
if (check.platforms && !check.platforms.includes(process.platform)) return false;
|
|
639
|
+
const expandedPath = check.path.startsWith("~/") ? join(homedir(), check.path.slice(2)) : check.path;
|
|
640
|
+
try {
|
|
641
|
+
await access(expandedPath, constants.R_OK);
|
|
642
|
+
} catch {
|
|
643
|
+
return false;
|
|
644
|
+
}
|
|
645
|
+
if (!check.markerFile) return true;
|
|
456
646
|
try {
|
|
457
|
-
await access(
|
|
647
|
+
await access(join(expandedPath, check.markerFile));
|
|
458
648
|
return true;
|
|
459
649
|
} catch {
|
|
460
650
|
return false;
|
|
461
651
|
}
|
|
462
652
|
}
|
|
463
653
|
/**
|
|
464
|
-
*
|
|
654
|
+
* Check if a macOS .app bundle exists in /Applications or ~/Applications.
|
|
655
|
+
* Returns false immediately on non-darwin platforms.
|
|
656
|
+
*/
|
|
657
|
+
async function checkAppBundle(check) {
|
|
658
|
+
if (process.platform !== "darwin") return false;
|
|
659
|
+
const searchPaths = check.searchPaths ?? ["/Applications", join(homedir(), "Applications")];
|
|
660
|
+
for (const dir of searchPaths) try {
|
|
661
|
+
await access(join(dir, check.name));
|
|
662
|
+
return true;
|
|
663
|
+
} catch {}
|
|
664
|
+
return false;
|
|
665
|
+
}
|
|
666
|
+
/** Map of editor names to their extension directory paths. */
|
|
667
|
+
const EDITOR_EXTENSION_DIRS = {
|
|
668
|
+
vscode: join(homedir(), ".vscode", "extensions"),
|
|
669
|
+
cursor: join(homedir(), ".cursor", "extensions"),
|
|
670
|
+
windsurf: join(homedir(), ".windsurf", "extensions")
|
|
671
|
+
};
|
|
672
|
+
/**
|
|
673
|
+
* Check if a VS Code extension is installed in VS Code, Cursor, or Windsurf.
|
|
674
|
+
* Matches extension directories by prefix (case-insensitive) since directories
|
|
675
|
+
* are named `<extensionId>-<version>`.
|
|
676
|
+
*/
|
|
677
|
+
async function checkVscodeExtension(check) {
|
|
678
|
+
const editors = check.editors ?? ["vscode"];
|
|
679
|
+
const prefix = check.extensionId.toLowerCase();
|
|
680
|
+
for (const editor of editors) {
|
|
681
|
+
const extDir = EDITOR_EXTENSION_DIRS[editor];
|
|
682
|
+
if (!extDir) {} else try {
|
|
683
|
+
if ((await readdir(extDir)).some((entry) => entry.toLowerCase().startsWith(prefix))) return true;
|
|
684
|
+
} catch {}
|
|
685
|
+
}
|
|
686
|
+
return false;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Get the JetBrains config base directory for the current platform.
|
|
690
|
+
* macOS: ~/Library/Application Support/JetBrains/
|
|
691
|
+
* Linux: ~/.config/JetBrains/
|
|
692
|
+
* Windows: %APPDATA%/JetBrains/
|
|
693
|
+
*/
|
|
694
|
+
function getJetbrainsConfigBase() {
|
|
695
|
+
switch (process.platform) {
|
|
696
|
+
case "darwin": return join(homedir(), "Library", "Application Support", "JetBrains");
|
|
697
|
+
case "linux": return join(homedir(), ".config", "JetBrains");
|
|
698
|
+
case "win32": return process.env.APPDATA ? join(process.env.APPDATA, "JetBrains") : void 0;
|
|
699
|
+
default: return;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
/**
|
|
703
|
+
* Check if a JetBrains plugin is installed by scanning IDE config directories.
|
|
704
|
+
* Looks for pluginId as a subdirectory under <version>/plugins/ across all IDE versions.
|
|
705
|
+
*/
|
|
706
|
+
async function checkJetbrainsPlugin(check) {
|
|
707
|
+
const base = getJetbrainsConfigBase();
|
|
708
|
+
if (!base) return false;
|
|
709
|
+
let versionDirs;
|
|
710
|
+
try {
|
|
711
|
+
versionDirs = await readdir(base);
|
|
712
|
+
} catch {
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
for (const versionDir of versionDirs) try {
|
|
716
|
+
if ((await readdir(join(base, versionDir, "plugins"))).some((entry) => entry.toLowerCase() === check.pluginId.toLowerCase())) return true;
|
|
717
|
+
} catch {}
|
|
718
|
+
return false;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Handler map for dispatching detection checks by type.
|
|
722
|
+
* Uses an object so that individual handlers can be spied on in tests
|
|
723
|
+
* (ESM module exports are not interceptable for intra-module calls).
|
|
724
|
+
*/
|
|
725
|
+
const checkHandlers = {
|
|
726
|
+
binary: checkBinary,
|
|
727
|
+
directory: checkDirectory,
|
|
728
|
+
app: checkAppBundle,
|
|
729
|
+
"vscode-extension": checkVscodeExtension,
|
|
730
|
+
"jetbrains-plugin": checkJetbrainsPlugin
|
|
731
|
+
};
|
|
732
|
+
/**
|
|
733
|
+
* Dispatch a single detection check to the appropriate mechanism function.
|
|
734
|
+
*/
|
|
735
|
+
function runCheck(check) {
|
|
736
|
+
switch (check.type) {
|
|
737
|
+
case "binary": return checkHandlers.binary(check);
|
|
738
|
+
case "directory": return checkHandlers.directory(check);
|
|
739
|
+
case "app": return checkHandlers.app(check);
|
|
740
|
+
case "vscode-extension": return checkHandlers["vscode-extension"](check);
|
|
741
|
+
case "jetbrains-plugin": return checkHandlers["jetbrains-plugin"](check);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Evaluate a DetectionConfig using OR-of-ANDs logic.
|
|
746
|
+
* Each group is evaluated in parallel. Within a group, ALL checks must pass (AND).
|
|
747
|
+
* ANY group passing means the tool is detected (OR across groups).
|
|
748
|
+
*/
|
|
749
|
+
async function evaluateDetection(config) {
|
|
750
|
+
return (await Promise.all(config.groups.map(async (group) => {
|
|
751
|
+
return (await Promise.all(group.map(runCheck))).every(Boolean);
|
|
752
|
+
}))).some(Boolean);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
//#endregion
|
|
756
|
+
//#region ../core/src/detection/agent-detection.ts
|
|
757
|
+
/**
|
|
758
|
+
* Cache for detected agents (valid for process lifetime)
|
|
759
|
+
*/
|
|
760
|
+
let cachedAgents = null;
|
|
761
|
+
/**
|
|
762
|
+
* Detect if a specific agent is installed using structured detectionConfig.
|
|
465
763
|
*/
|
|
466
764
|
async function isAgentInstalled(agentKey) {
|
|
467
765
|
const agentConfig = AGENT_PATHS.find((agent) => agent.key === agentKey);
|
|
468
|
-
if (!agentConfig) return false;
|
|
469
|
-
|
|
470
|
-
if (await directoryExists(join(homedir(), detection.slice(2)))) return true;
|
|
471
|
-
} else if (detection.startsWith(".")) {
|
|
472
|
-
if (await directoryExists(join(homedir(), detection))) return true;
|
|
473
|
-
} else if (await commandExists(detection)) return true;
|
|
474
|
-
return false;
|
|
766
|
+
if (!agentConfig?.detectionConfig) return false;
|
|
767
|
+
return evaluateDetection(agentConfig.detectionConfig);
|
|
475
768
|
}
|
|
476
769
|
/**
|
|
477
770
|
* Detect all installed AI agents
|
|
@@ -497,5 +790,5 @@ function clearAgentCache() {
|
|
|
497
790
|
}
|
|
498
791
|
|
|
499
792
|
//#endregion
|
|
500
|
-
export { detectInstalledAgents as n,
|
|
501
|
-
//# sourceMappingURL=agent-detection-
|
|
793
|
+
export { AGENT_PATHS as i, detectInstalledAgents as n, evaluateDetection as r, clearAgentCache as t };
|
|
794
|
+
//# sourceMappingURL=agent-detection-DTiVeO5W.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-detection-DTiVeO5W.mjs","names":[],"sources":["../../agent-paths/src/registry.ts","../../core/src/detection/mechanisms.ts","../../core/src/detection/agent-detection.ts"],"sourcesContent":["import type { AgentPathConfig } from \"./types.js\";\n\n/**\n * Registry of all supported AI agents and their path configurations.\n * Each agent defines where it expects skills, rules, agents, memory, settings, and commands.\n */\nexport const AGENT_PATHS: readonly AgentPathConfig[] = [\n {\n key: \"claude-code\",\n name: \"Claude Code\",\n skills: {\n project: \".claude/skills/{name}\",\n global: \"~/.claude/skills/{name}\",\n },\n rules: {\n project: \".claude/rules/{name}.md\",\n global: \"~/.claude/rules/{name}.md\",\n },\n agents: {\n project: \".claude/agents/{name}.md\",\n global: \"~/.claude/agents/{name}.md\",\n },\n memory: {\n project: \"CLAUDE.md\",\n global: \"~/.claude/CLAUDE.md\",\n },\n settings: {\n project: \".claude/settings.json\",\n global: \"~/.claude/settings.json\",\n },\n commands: {\n project: \".claude/commands/{name}.md\",\n global: \"~/.claude/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"binary\", name: \"claude\", versionPattern: /claude/i }],\n [{ type: \"directory\", path: \"~/.claude/\", markerFile: \"settings.json\" }],\n ],\n },\n legacy: {},\n },\n {\n key: \"cursor\",\n name: \"Cursor\",\n skills: {\n project: \".cursor/skills/{name}\",\n global: \"~/.cursor/skills/{name}\",\n },\n rules: {\n project: \".cursor/rules/{name}.mdc\",\n global: \"~/.cursor/rules/{name}.mdc\",\n },\n agents: {\n project: \".cursor/agents/{name}.md\",\n global: \"~/.cursor/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.cursor/AGENTS.md\",\n },\n settings: {\n project: \".cursor/settings.json\",\n global: \"~/.cursor/settings.json\",\n },\n commands: {\n project: \".cursor/commands/{name}.md\",\n global: \"~/.cursor/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"app\", name: \"Cursor.app\" }],\n [{ type: \"binary\", name: \"cursor\" }],\n [{ type: \"directory\", path: \"~/.cursor/\", markerFile: \"extensions\" }],\n ],\n },\n legacy: {\n rules: [\".cursorrules\"],\n },\n },\n {\n key: \"windsurf\",\n name: \"Windsurf\",\n skills: {\n project: \".windsurf/skills/{name}\",\n global: \"~/.codeium/windsurf/skills/{name}\",\n },\n rules: {\n project: \".windsurf/rules/{name}.md\",\n global: \"~/.codeium/windsurf/rules/{name}.md\",\n },\n agents: {\n project: \".windsurf/agents/{name}.md\",\n global: \"~/.codeium/windsurf/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.codeium/windsurf/AGENTS.md\",\n },\n settings: {\n project: \".windsurf/settings.json\",\n global: \"~/.codeium/windsurf/settings.json\",\n },\n commands: {\n project: \".windsurf/workflows/{name}.md\",\n global: \"~/.codeium/windsurf/workflows/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"app\", name: \"Windsurf.app\" }],\n [{ type: \"binary\", name: \"windsurf\" }],\n [\n {\n type: \"directory\",\n path: \"~/.codeium/windsurf/\",\n markerFile: \"settings.json\",\n },\n ],\n ],\n },\n legacy: {\n rules: [\".windsurfrules\"],\n },\n },\n {\n key: \"antigravity\",\n name: \"Antigravity\",\n skills: {\n project: \".agent/skills/{name}\",\n global: \"~/.gemini/antigravity/skills/{name}\",\n },\n rules: {\n project: \".agent/rules/{name}.md\",\n global: \"~/.gemini/antigravity/rules/{name}.md\",\n },\n agents: {\n project: \".agent/agents/{name}.md\",\n global: \"~/.gemini/antigravity/agents/{name}.md\",\n },\n memory: {\n project: \"GEMINI.md\",\n global: \"~/.gemini/antigravity/GEMINI.md\",\n },\n settings: {\n project: \".agent/settings.json\",\n global: \"~/.gemini/antigravity/settings.json\",\n },\n commands: {\n project: \".agent/workflows/{name}.md\",\n global: \"~/.gemini/antigravity/workflows/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"app\", name: \"Antigravity.app\" }],\n [{ type: \"binary\", name: \"agy\" }],\n [{ type: \"binary\", name: \"antigravity\", platforms: [\"linux\"] }],\n [\n {\n type: \"directory\",\n path: \"~/.gemini/antigravity/\",\n markerFile: \"settings.json\",\n },\n ],\n ],\n },\n legacy: {},\n },\n {\n key: \"codex\",\n name: \"Codex CLI\",\n skills: {\n project: \".codex/skills/{name}\",\n global: \"~/.codex/skills/{name}\",\n },\n rules: {\n project: \".codex/rules/{name}.md\",\n global: \"~/.codex/rules/{name}.md\",\n },\n agents: {\n project: \".codex/agents/{name}.md\",\n global: \"~/.codex/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.codex/AGENTS.md\",\n },\n settings: {\n project: \".codex/config.toml\",\n global: \"~/.codex/config.toml\",\n },\n commands: {\n project: \".codex/commands/{name}.md\",\n global: \"~/.codex/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"binary\", name: \"codex\", versionPattern: /codex/i }],\n [{ type: \"directory\", path: \"~/.codex/\", markerFile: \"config.toml\" }],\n ],\n },\n legacy: {},\n },\n {\n key: \"github-copilot\",\n name: \"GitHub Copilot\",\n skills: {\n project: \".github/skills/{name}\",\n global: \"~/.github/skills/{name}\",\n },\n rules: {\n project: \".github/copilot-instructions.md\",\n global: \"~/.github/copilot-instructions.md\",\n },\n agents: {\n project: \".github/agents/{name}.md\",\n global: \"~/.github/agents/{name}.md\",\n },\n memory: {\n project: \".github/copilot-instructions.md\",\n global: \"~/.github/copilot-instructions.md\",\n },\n settings: {\n project: \".github/copilot/settings.json\",\n global: \"~/.github/copilot/settings.json\",\n },\n commands: {\n project: \".github/copilot/commands/{name}.md\",\n global: \"~/.github/copilot/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [\n {\n type: \"binary\",\n name: \"copilot\",\n versionPattern: /copilot|github/i,\n },\n ],\n [\n {\n type: \"vscode-extension\",\n extensionId: \"GitHub.copilot\",\n editors: [\"vscode\", \"cursor\"],\n },\n ],\n [{ type: \"directory\", path: \"~/.github/copilot/\" }],\n ],\n },\n legacy: {},\n },\n {\n key: \"opencode\",\n name: \"OpenCode\",\n skills: {\n project: \".opencode/skills/{name}\",\n global: \"~/.config/opencode/skills/{name}\",\n },\n rules: {\n project: \".opencode/rules/{name}.md\",\n global: \"~/.config/opencode/rules/{name}.md\",\n },\n agents: {\n project: \".opencode/agents/{name}.md\",\n global: \"~/.config/opencode/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.config/opencode/AGENTS.md\",\n },\n settings: {\n project: \".opencode/settings.json\",\n global: \"~/.config/opencode/settings.json\",\n },\n commands: {\n project: \".opencode/commands/{name}.md\",\n global: \"~/.config/opencode/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"binary\", name: \"opencode\", versionPattern: /opencode|sst/i }],\n [\n {\n type: \"directory\",\n path: \"~/.config/opencode/\",\n markerFile: \"config.yaml\",\n },\n ],\n ],\n },\n legacy: {},\n },\n {\n key: \"amp\",\n name: \"Amp\",\n skills: {\n project: \".agents/skills/{name}\",\n global: \"~/.config/agents/skills/{name}\",\n },\n rules: {\n project: \".agents/rules/{name}.md\",\n global: \"~/.config/agents/rules/{name}.md\",\n },\n agents: {\n project: \".agents/agents/{name}.md\",\n global: \"~/.config/agents/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.config/agents/AGENTS.md\",\n },\n settings: {\n project: \".agents/settings.json\",\n global: \"~/.config/agents/settings.json\",\n },\n commands: {\n project: \".agents/commands/{name}.md\",\n global: \"~/.config/agents/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"binary\", name: \"amp\", versionPattern: /amp|sourcegraph/i }],\n [{ type: \"directory\", path: \"~/.ampcache/\" }],\n ],\n },\n legacy: {},\n },\n {\n key: \"kiro\",\n name: \"Kiro\",\n skills: {\n project: \".kiro/skills/{name}\",\n global: \"~/.kiro/skills/{name}\",\n },\n rules: {\n project: \".kiro/rules/{name}.md\",\n global: \"~/.kiro/rules/{name}.md\",\n },\n agents: {\n project: \".kiro/agents/{name}.md\",\n global: \"~/.kiro/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.kiro/AGENTS.md\",\n },\n settings: {\n project: \".kiro/settings.json\",\n global: \"~/.kiro/settings.json\",\n },\n commands: {\n project: \".kiro/commands/{name}.md\",\n global: \"~/.kiro/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"app\", name: \"Kiro.app\" }],\n [{ type: \"binary\", name: \"kiro\" }],\n [{ type: \"directory\", path: \"~/.kiro/\", markerFile: \"settings.json\" }],\n ],\n },\n legacy: {},\n },\n {\n key: \"zed\",\n name: \"Zed\",\n skills: {\n project: \".zed/skills/{name}\",\n global: \"~/.zed/skills/{name}\",\n },\n rules: {\n project: \".zed/rules/{name}.md\",\n global: \"~/.zed/rules/{name}.md\",\n },\n agents: {\n project: \".zed/agents/{name}.md\",\n global: \"~/.zed/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.zed/AGENTS.md\",\n },\n settings: {\n project: \".zed/settings.json\",\n global: \"~/.zed/settings.json\",\n },\n commands: {\n project: \".zed/commands/{name}.md\",\n global: \"~/.zed/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"app\", name: \"Zed.app\" }],\n [{ type: \"binary\", name: \"zed\" }],\n [\n {\n type: \"directory\",\n path: \"~/.config/zed/\",\n markerFile: \"settings.json\",\n },\n ],\n ],\n },\n legacy: {},\n },\n {\n key: \"cline\",\n name: \"Cline\",\n skills: {\n project: \".cline/skills/{name}\",\n global: \"~/.cline/skills/{name}\",\n },\n rules: {\n project: \".cline/rules/{name}.md\",\n global: \"~/.cline/rules/{name}.md\",\n },\n agents: {\n project: \".cline/agents/{name}.md\",\n global: \"~/.cline/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.cline/AGENTS.md\",\n },\n settings: {\n project: \".cline/settings.json\",\n global: \"~/.cline/settings.json\",\n },\n commands: {\n project: \".cline/commands/{name}.md\",\n global: \"~/.cline/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [\n {\n type: \"vscode-extension\",\n extensionId: \"saoudrizwan.claude-dev\",\n editors: [\"vscode\", \"cursor\", \"windsurf\"],\n },\n ],\n [\n {\n type: \"directory\",\n path: \"~/.cline/\",\n markerFile: \"settings.json\",\n },\n ],\n ],\n },\n legacy: {},\n },\n {\n key: \"roo\",\n name: \"Roo\",\n skills: {\n project: \".roo/skills/{name}\",\n global: \"~/.roo/skills/{name}\",\n },\n rules: {\n project: \".roo/rules/{name}.md\",\n global: \"~/.roo/rules/{name}.md\",\n },\n agents: {\n project: \".roo/agents/{name}.md\",\n global: \"~/.roo/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.roo/AGENTS.md\",\n },\n settings: {\n project: \".roo/settings.json\",\n global: \"~/.roo/settings.json\",\n },\n commands: {\n project: \".roo/commands/{name}.md\",\n global: \"~/.roo/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [\n {\n type: \"vscode-extension\",\n extensionId: \"RooVeterinaryInc.roo-cline\",\n editors: [\"vscode\", \"cursor\", \"windsurf\"],\n },\n ],\n [{ type: \"directory\", path: \"~/.roo/\", markerFile: \"settings.json\" }],\n ],\n },\n legacy: {},\n },\n {\n key: \"junie\",\n name: \"Junie\",\n skills: {\n project: \".junie/skills/{name}\",\n global: \"~/.junie/skills/{name}\",\n },\n rules: {\n project: \".junie/rules/{name}.md\",\n global: \"~/.junie/rules/{name}.md\",\n },\n agents: {\n project: \".junie/agents/{name}.md\",\n global: \"~/.junie/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.junie/AGENTS.md\",\n },\n settings: {\n project: \".junie/settings.json\",\n global: \"~/.junie/settings.json\",\n },\n commands: {\n project: \".junie/commands/{name}.md\",\n global: \"~/.junie/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"jetbrains-plugin\", pluginId: \"junie\" }],\n [\n {\n type: \"directory\",\n path: \"~/.junie/\",\n markerFile: \"settings.json\",\n },\n ],\n ],\n },\n legacy: {},\n },\n {\n key: \"trae\",\n name: \"Trae\",\n skills: {\n project: \".trae/skills/{name}\",\n global: \"~/.trae/skills/{name}\",\n },\n rules: {\n project: \".trae/rules/{name}.md\",\n global: \"~/.trae/rules/{name}.md\",\n },\n agents: {\n project: \".trae/agents/{name}.md\",\n global: \"~/.trae/agents/{name}.md\",\n },\n memory: {\n project: \"AGENTS.md\",\n global: \"~/.trae/AGENTS.md\",\n },\n settings: {\n project: \".trae/settings.json\",\n global: \"~/.trae/settings.json\",\n },\n commands: {\n project: \".trae/commands/{name}.md\",\n global: \"~/.trae/commands/{name}.md\",\n },\n detectionConfig: {\n groups: [\n [{ type: \"app\", name: \"Trae.app\" }],\n [{ type: \"directory\", path: \"~/.trae/\", markerFile: \"settings.json\" }],\n ],\n },\n legacy: {},\n },\n];\n","import { execFile } from \"node:child_process\";\nimport { constants, access, readdir } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type {\n AppBundleCheck,\n BinaryCheck,\n DetectionCheck,\n DetectionConfig,\n DirectoryCheck,\n JetbrainsPluginCheck,\n Platform,\n VscodeExtensionCheck,\n} from \"@baton-dx/agent-paths\";\n\n/**\n * Execute a command and return stdout/stderr as a promise.\n * Rejects on non-zero exit code or timeout.\n */\nfunction execAsync(\n command: string,\n args: string[],\n options: { timeout?: number } = {},\n): Promise<{ stdout: string; stderr: string }> {\n return new Promise((resolve, reject) => {\n execFile(command, args, options, (error, stdout, stderr) => {\n if (error) {\n reject(error);\n } else {\n resolve({ stdout: String(stdout), stderr: String(stderr) });\n }\n });\n });\n}\n\n/**\n * Check if a binary exists in PATH and optionally verify its identity via version output.\n * Prevents false positives from binary name collisions (e.g., `opencode` by Litestar vs SST).\n */\nexport async function checkBinary(check: BinaryCheck): Promise<boolean> {\n if (check.platforms && !check.platforms.includes(process.platform as Platform)) {\n return false;\n }\n\n const lookupCommand = process.platform === \"win32\" ? \"where\" : \"which\";\n\n try {\n await execAsync(lookupCommand, [check.name]);\n } catch {\n return false;\n }\n\n if (!check.versionPattern) {\n return true;\n }\n\n const versionFlag = check.versionFlag ?? \"--version\";\n try {\n const { stdout, stderr } = await execAsync(check.name, [versionFlag], {\n timeout: 5000,\n });\n const output = `${stdout}\\n${stderr}`;\n return check.versionPattern.test(output);\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a directory exists and optionally contains a marker file.\n * Prevents false positives from leftover empty directories (e.g., ~/.cline/ without settings.json).\n */\nexport async function checkDirectory(check: DirectoryCheck): Promise<boolean> {\n if (check.platforms && !check.platforms.includes(process.platform as Platform)) {\n return false;\n }\n\n const expandedPath = check.path.startsWith(\"~/\")\n ? join(homedir(), check.path.slice(2))\n : check.path;\n\n try {\n await access(expandedPath, constants.R_OK);\n } catch {\n return false;\n }\n\n if (!check.markerFile) {\n return true;\n }\n\n try {\n await access(join(expandedPath, check.markerFile));\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if a macOS .app bundle exists in /Applications or ~/Applications.\n * Returns false immediately on non-darwin platforms.\n */\nexport async function checkAppBundle(check: AppBundleCheck): Promise<boolean> {\n if (process.platform !== \"darwin\") {\n return false;\n }\n\n const searchPaths = check.searchPaths ?? [\"/Applications\", join(homedir(), \"Applications\")];\n\n for (const dir of searchPaths) {\n try {\n await access(join(dir, check.name));\n return true;\n } catch {\n // not found in this path, try next\n }\n }\n\n return false;\n}\n\n/** Map of editor names to their extension directory paths. */\nconst EDITOR_EXTENSION_DIRS: Record<string, string> = {\n vscode: join(homedir(), \".vscode\", \"extensions\"),\n cursor: join(homedir(), \".cursor\", \"extensions\"),\n windsurf: join(homedir(), \".windsurf\", \"extensions\"),\n};\n\n/**\n * Check if a VS Code extension is installed in VS Code, Cursor, or Windsurf.\n * Matches extension directories by prefix (case-insensitive) since directories\n * are named `<extensionId>-<version>`.\n */\nexport async function checkVscodeExtension(check: VscodeExtensionCheck): Promise<boolean> {\n const editors = check.editors ?? [\"vscode\"];\n const prefix = check.extensionId.toLowerCase();\n\n for (const editor of editors) {\n const extDir = EDITOR_EXTENSION_DIRS[editor];\n if (!extDir) {\n // skip unknown editor\n } else {\n try {\n const entries = await readdir(extDir);\n if (entries.some((entry) => entry.toLowerCase().startsWith(prefix))) {\n return true;\n }\n } catch {\n // extension directory missing (ENOENT) — skip, not throw\n }\n }\n }\n\n return false;\n}\n\n/**\n * Get the JetBrains config base directory for the current platform.\n * macOS: ~/Library/Application Support/JetBrains/\n * Linux: ~/.config/JetBrains/\n * Windows: %APPDATA%/JetBrains/\n */\nfunction getJetbrainsConfigBase(): string | undefined {\n switch (process.platform) {\n case \"darwin\":\n return join(homedir(), \"Library\", \"Application Support\", \"JetBrains\");\n case \"linux\":\n return join(homedir(), \".config\", \"JetBrains\");\n case \"win32\":\n return process.env.APPDATA ? join(process.env.APPDATA, \"JetBrains\") : undefined;\n default:\n return undefined;\n }\n}\n\n/**\n * Check if a JetBrains plugin is installed by scanning IDE config directories.\n * Looks for pluginId as a subdirectory under <version>/plugins/ across all IDE versions.\n */\nexport async function checkJetbrainsPlugin(check: JetbrainsPluginCheck): Promise<boolean> {\n const base = getJetbrainsConfigBase();\n if (!base) {\n return false;\n }\n\n let versionDirs: string[];\n try {\n versionDirs = await readdir(base);\n } catch {\n return false;\n }\n\n for (const versionDir of versionDirs) {\n try {\n const pluginEntries = await readdir(join(base, versionDir, \"plugins\"));\n if (pluginEntries.some((entry) => entry.toLowerCase() === check.pluginId.toLowerCase())) {\n return true;\n }\n } catch {\n // plugins directory missing for this version — skip\n }\n }\n\n return false;\n}\n\n/**\n * Handler map for dispatching detection checks by type.\n * Uses an object so that individual handlers can be spied on in tests\n * (ESM module exports are not interceptable for intra-module calls).\n */\nexport const checkHandlers = {\n binary: checkBinary,\n directory: checkDirectory,\n app: checkAppBundle,\n \"vscode-extension\": checkVscodeExtension,\n \"jetbrains-plugin\": checkJetbrainsPlugin,\n};\n\n/**\n * Dispatch a single detection check to the appropriate mechanism function.\n */\nfunction runCheck(check: DetectionCheck): Promise<boolean> {\n switch (check.type) {\n case \"binary\":\n return checkHandlers.binary(check);\n case \"directory\":\n return checkHandlers.directory(check);\n case \"app\":\n return checkHandlers.app(check);\n case \"vscode-extension\":\n return checkHandlers[\"vscode-extension\"](check);\n case \"jetbrains-plugin\":\n return checkHandlers[\"jetbrains-plugin\"](check);\n }\n}\n\n/**\n * Evaluate a DetectionConfig using OR-of-ANDs logic.\n * Each group is evaluated in parallel. Within a group, ALL checks must pass (AND).\n * ANY group passing means the tool is detected (OR across groups).\n */\nexport async function evaluateDetection(config: DetectionConfig): Promise<boolean> {\n const groupResults = await Promise.all(\n config.groups.map(async (group) => {\n const results = await Promise.all(group.map(runCheck));\n return results.every(Boolean);\n }),\n );\n return groupResults.some(Boolean);\n}\n","import { AGENT_PATHS } from \"@baton-dx/agent-paths\";\nimport { evaluateDetection } from \"./mechanisms.js\";\n\n/**\n * Cache for detected agents (valid for process lifetime)\n */\nlet cachedAgents: string[] | null = null;\n\n/**\n * Detect if a specific agent is installed using structured detectionConfig.\n */\nasync function isAgentInstalled(agentKey: string): Promise<boolean> {\n const agentConfig = AGENT_PATHS.find((agent) => agent.key === agentKey);\n if (!agentConfig?.detectionConfig) return false;\n\n return evaluateDetection(agentConfig.detectionConfig);\n}\n\n/**\n * Detect all installed AI agents\n * Results are cached for the duration of the process\n */\nexport async function detectInstalledAgents(): Promise<string[]> {\n // Return cached result if available\n if (cachedAgents !== null) {\n return cachedAgents;\n }\n\n const installedAgents: string[] = [];\n\n // Check each agent in parallel\n const detectionPromises = AGENT_PATHS.map(async (agent) => {\n const isInstalled = await isAgentInstalled(agent.key);\n return isInstalled ? agent.key : null;\n });\n\n const results = await Promise.all(detectionPromises);\n\n // Filter out null results\n for (const result of results) {\n if (result !== null) {\n installedAgents.push(result);\n }\n }\n\n // Cache the result\n cachedAgents = installedAgents;\n\n return installedAgents;\n}\n\n/**\n * Clear the agent detection cache\n * Useful for testing or when agent installation state may have changed\n */\nexport function clearAgentCache(): void {\n cachedAgents = null;\n}\n\n/**\n * Override agent detection with a specific list of agents\n * Used when --agents flag is provided\n */\nexport function setDetectedAgents(agents: string[]): void {\n cachedAgents = [...agents];\n}\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { access } from "node:fs/promises";
|
|
|
4
4
|
import { dirname, join, sep } from "node:path";
|
|
5
5
|
import { formatWithOptions, stripVTControlCharacters } from "node:util";
|
|
6
6
|
import g$1, { stdin, stdout } from "node:process";
|
|
7
|
-
import * as tty
|
|
7
|
+
import * as tty from "node:tty";
|
|
8
8
|
import { ReadStream } from "node:tty";
|
|
9
9
|
import * as k from "node:readline";
|
|
10
10
|
import f from "node:readline";
|
|
@@ -457,12 +457,12 @@ ${indent}`);
|
|
|
457
457
|
|
|
458
458
|
//#endregion
|
|
459
459
|
//#region ../../node_modules/.bun/consola@3.4.2/node_modules/consola/dist/shared/consola.DXBYu-KD.mjs
|
|
460
|
-
const { env = {}, argv = [], platform
|
|
460
|
+
const { env = {}, argv = [], platform = "" } = typeof process === "undefined" ? {} : process;
|
|
461
461
|
const isDisabled = "NO_COLOR" in env || argv.includes("--no-color");
|
|
462
462
|
const isForced = "FORCE_COLOR" in env || argv.includes("--color");
|
|
463
|
-
const isWindows = platform
|
|
463
|
+
const isWindows = platform === "win32";
|
|
464
464
|
const isDumbTerminal = env.TERM === "dumb";
|
|
465
|
-
const isCompatibleTerminal = tty
|
|
465
|
+
const isCompatibleTerminal = tty && tty.isatty && tty.isatty(1) && env.TERM && !isDumbTerminal;
|
|
466
466
|
const isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
|
|
467
467
|
const isColorSupported = !isDisabled && (isForced || isWindows && !isDumbTerminal || isCompatibleTerminal || isCI);
|
|
468
468
|
function replaceClose(index, string, close, replace, head = string.slice(0, Math.max(0, index)) + replace, tail = string.slice(Math.max(0, index + close.length)), next = tail.indexOf(close)) {
|
|
@@ -9838,4 +9838,4 @@ async function findSourceRoot(cwd = process.cwd(), options) {
|
|
|
9838
9838
|
|
|
9839
9839
|
//#endregion
|
|
9840
9840
|
export { Ne as a, Ve as c, bt as d, je as f, runMain as g, defineCommand as h, Le as i, We as l, require_dist as m, isInSourceRepo as n, R as o, Ct$1 as p, Je as r, Re as s, findSourceRoot as t, Ze as u };
|
|
9841
|
-
//# sourceMappingURL=context-detection-
|
|
9841
|
+
//# sourceMappingURL=context-detection-DqOTnD6_.mjs.map
|