@baton-dx/cli 0.3.1 → 0.4.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.
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { n as detectInstalledAITools, t as clearAIToolCache } from "./ai-tool-detection-CMsBNa9e.mjs";
3
+
4
+ export { detectInstalledAITools };
@@ -4,12 +4,12 @@ import { join } from "node:path";
4
4
  import { homedir } from "node:os";
5
5
  import { execFile } from "node:child_process";
6
6
 
7
- //#region ../agent-paths/src/registry.ts
7
+ //#region ../ai-tool-paths/src/registry.ts
8
8
  /**
9
9
  * Registry of all supported AI agents and their path configurations.
10
- * Each agent defines where it expects skills, rules, agents, memory, settings, and commands.
10
+ * Each agent defines where it expects skills, rules, agents, memory, and commands.
11
11
  */
12
- const AGENT_PATHS = [
12
+ const AI_TOOL_PATHS = [
13
13
  {
14
14
  key: "claude-code",
15
15
  name: "Claude Code",
@@ -29,10 +29,6 @@ const AGENT_PATHS = [
29
29
  project: "CLAUDE.md",
30
30
  global: "~/.claude/CLAUDE.md"
31
31
  },
32
- settings: {
33
- project: ".claude/settings.json",
34
- global: "~/.claude/settings.json"
35
- },
36
32
  commands: {
37
33
  project: ".claude/commands/{name}.md",
38
34
  global: "~/.claude/commands/{name}.md"
@@ -67,10 +63,6 @@ const AGENT_PATHS = [
67
63
  project: "AGENTS.md",
68
64
  global: "~/.cursor/AGENTS.md"
69
65
  },
70
- settings: {
71
- project: ".cursor/settings.json",
72
- global: "~/.cursor/settings.json"
73
- },
74
66
  commands: {
75
67
  project: ".cursor/commands/{name}.md",
76
68
  global: "~/.cursor/commands/{name}.md"
@@ -111,10 +103,6 @@ const AGENT_PATHS = [
111
103
  project: "AGENTS.md",
112
104
  global: "~/.codeium/windsurf/AGENTS.md"
113
105
  },
114
- settings: {
115
- project: ".windsurf/settings.json",
116
- global: "~/.codeium/windsurf/settings.json"
117
- },
118
106
  commands: {
119
107
  project: ".windsurf/workflows/{name}.md",
120
108
  global: "~/.codeium/windsurf/workflows/{name}.md"
@@ -155,10 +143,6 @@ const AGENT_PATHS = [
155
143
  project: "GEMINI.md",
156
144
  global: "~/.gemini/antigravity/GEMINI.md"
157
145
  },
158
- settings: {
159
- project: ".agent/settings.json",
160
- global: "~/.gemini/antigravity/settings.json"
161
- },
162
146
  commands: {
163
147
  project: ".agent/workflows/{name}.md",
164
148
  global: "~/.gemini/antigravity/workflows/{name}.md"
@@ -204,10 +188,6 @@ const AGENT_PATHS = [
204
188
  project: "AGENTS.md",
205
189
  global: "~/.codex/AGENTS.md"
206
190
  },
207
- settings: {
208
- project: ".codex/config.toml",
209
- global: "~/.codex/config.toml"
210
- },
211
191
  commands: {
212
192
  project: ".codex/commands/{name}.md",
213
193
  global: "~/.codex/commands/{name}.md"
@@ -242,10 +222,6 @@ const AGENT_PATHS = [
242
222
  project: ".github/copilot-instructions.md",
243
223
  global: "~/.github/copilot-instructions.md"
244
224
  },
245
- settings: {
246
- project: ".github/copilot/settings.json",
247
- global: "~/.github/copilot/settings.json"
248
- },
249
225
  commands: {
250
226
  project: ".github/copilot/commands/{name}.md",
251
227
  global: "~/.github/copilot/commands/{name}.md"
@@ -287,10 +263,6 @@ const AGENT_PATHS = [
287
263
  project: "AGENTS.md",
288
264
  global: "~/.config/opencode/AGENTS.md"
289
265
  },
290
- settings: {
291
- project: ".opencode/settings.json",
292
- global: "~/.config/opencode/settings.json"
293
- },
294
266
  commands: {
295
267
  project: ".opencode/commands/{name}.md",
296
268
  global: "~/.config/opencode/commands/{name}.md"
@@ -325,10 +297,6 @@ const AGENT_PATHS = [
325
297
  project: "AGENTS.md",
326
298
  global: "~/.config/agents/AGENTS.md"
327
299
  },
328
- settings: {
329
- project: ".agents/settings.json",
330
- global: "~/.config/agents/settings.json"
331
- },
332
300
  commands: {
333
301
  project: ".agents/commands/{name}.md",
334
302
  global: "~/.config/agents/commands/{name}.md"
@@ -362,10 +330,6 @@ const AGENT_PATHS = [
362
330
  project: "AGENTS.md",
363
331
  global: "~/.kiro/AGENTS.md"
364
332
  },
365
- settings: {
366
- project: ".kiro/settings.json",
367
- global: "~/.kiro/settings.json"
368
- },
369
333
  commands: {
370
334
  project: ".kiro/commands/{name}.md",
371
335
  global: "~/.kiro/commands/{name}.md"
@@ -406,10 +370,6 @@ const AGENT_PATHS = [
406
370
  project: "AGENTS.md",
407
371
  global: "~/.zed/AGENTS.md"
408
372
  },
409
- settings: {
410
- project: ".zed/settings.json",
411
- global: "~/.zed/settings.json"
412
- },
413
373
  commands: {
414
374
  project: ".zed/commands/{name}.md",
415
375
  global: "~/.zed/commands/{name}.md"
@@ -450,10 +410,6 @@ const AGENT_PATHS = [
450
410
  project: "AGENTS.md",
451
411
  global: "~/.cline/AGENTS.md"
452
412
  },
453
- settings: {
454
- project: ".cline/settings.json",
455
- global: "~/.cline/settings.json"
456
- },
457
413
  commands: {
458
414
  project: ".cline/commands/{name}.md",
459
415
  global: "~/.cline/commands/{name}.md"
@@ -492,10 +448,6 @@ const AGENT_PATHS = [
492
448
  project: "AGENTS.md",
493
449
  global: "~/.roo/AGENTS.md"
494
450
  },
495
- settings: {
496
- project: ".roo/settings.json",
497
- global: "~/.roo/settings.json"
498
- },
499
451
  commands: {
500
452
  project: ".roo/commands/{name}.md",
501
453
  global: "~/.roo/commands/{name}.md"
@@ -534,10 +486,6 @@ const AGENT_PATHS = [
534
486
  project: "AGENTS.md",
535
487
  global: "~/.junie/AGENTS.md"
536
488
  },
537
- settings: {
538
- project: ".junie/settings.json",
539
- global: "~/.junie/settings.json"
540
- },
541
489
  commands: {
542
490
  project: ".junie/commands/{name}.md",
543
491
  global: "~/.junie/commands/{name}.md"
@@ -571,10 +519,6 @@ const AGENT_PATHS = [
571
519
  project: "AGENTS.md",
572
520
  global: "~/.trae/AGENTS.md"
573
521
  },
574
- settings: {
575
- project: ".trae/settings.json",
576
- global: "~/.trae/settings.json"
577
- },
578
522
  commands: {
579
523
  project: ".trae/commands/{name}.md",
580
524
  global: "~/.trae/commands/{name}.md"
@@ -753,42 +697,42 @@ async function evaluateDetection(config) {
753
697
  }
754
698
 
755
699
  //#endregion
756
- //#region ../core/src/detection/agent-detection.ts
700
+ //#region ../core/src/detection/ai-tool-detection.ts
757
701
  /**
758
- * Cache for detected agents (valid for process lifetime)
702
+ * Cache for detected AI tools (valid for process lifetime)
759
703
  */
760
- let cachedAgents = null;
704
+ let cachedAITools = null;
761
705
  /**
762
- * Detect if a specific agent is installed using structured detectionConfig.
706
+ * Detect if a specific AI tool is installed using structured detectionConfig.
763
707
  */
764
- async function isAgentInstalled(agentKey) {
765
- const agentConfig = AGENT_PATHS.find((agent) => agent.key === agentKey);
766
- if (!agentConfig?.detectionConfig) return false;
767
- return evaluateDetection(agentConfig.detectionConfig);
708
+ async function isAIToolInstalled(toolKey) {
709
+ const toolConfig = AI_TOOL_PATHS.find((agent) => agent.key === toolKey);
710
+ if (!toolConfig?.detectionConfig) return false;
711
+ return evaluateDetection(toolConfig.detectionConfig);
768
712
  }
769
713
  /**
770
- * Detect all installed AI agents
714
+ * Detect all installed AI tools
771
715
  * Results are cached for the duration of the process
772
716
  */
773
- async function detectInstalledAgents() {
774
- if (cachedAgents !== null) return cachedAgents;
775
- const installedAgents = [];
776
- const detectionPromises = AGENT_PATHS.map(async (agent) => {
777
- return await isAgentInstalled(agent.key) ? agent.key : null;
717
+ async function detectInstalledAITools() {
718
+ if (cachedAITools !== null) return cachedAITools;
719
+ const installedAITools = [];
720
+ const detectionPromises = AI_TOOL_PATHS.map(async (agent) => {
721
+ return await isAIToolInstalled(agent.key) ? agent.key : null;
778
722
  });
779
723
  const results = await Promise.all(detectionPromises);
780
- for (const result of results) if (result !== null) installedAgents.push(result);
781
- cachedAgents = installedAgents;
782
- return installedAgents;
724
+ for (const result of results) if (result !== null) installedAITools.push(result);
725
+ cachedAITools = installedAITools;
726
+ return installedAITools;
783
727
  }
784
728
  /**
785
- * Clear the agent detection cache
786
- * Useful for testing or when agent installation state may have changed
729
+ * Clear the AI tool detection cache
730
+ * Useful for testing or when tool installation state may have changed
787
731
  */
788
- function clearAgentCache() {
789
- cachedAgents = null;
732
+ function clearAIToolCache() {
733
+ cachedAITools = null;
790
734
  }
791
735
 
792
736
  //#endregion
793
- export { AGENT_PATHS as i, detectInstalledAgents as n, evaluateDetection as r, clearAgentCache as t };
794
- //# sourceMappingURL=agent-detection-DTiVeO5W.mjs.map
737
+ export { AI_TOOL_PATHS as i, detectInstalledAITools as n, evaluateDetection as r, clearAIToolCache as t };
738
+ //# sourceMappingURL=ai-tool-detection-CMsBNa9e.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-tool-detection-CMsBNa9e.mjs","names":[],"sources":["../../ai-tool-paths/src/registry.ts","../../core/src/detection/mechanisms.ts","../../core/src/detection/ai-tool-detection.ts"],"sourcesContent":["import type { AIToolPathConfig } 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, and commands.\n */\nexport const AI_TOOL_PATHS: readonly AIToolPathConfig[] = [\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 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 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 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 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 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 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 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 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 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 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 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 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 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 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/ai-tool-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 { AI_TOOL_PATHS } from \"@baton-dx/ai-tool-paths\";\nimport { evaluateDetection } from \"./mechanisms.js\";\n\n/**\n * Cache for detected AI tools (valid for process lifetime)\n */\nlet cachedAITools: string[] | null = null;\n\n/**\n * Detect if a specific AI tool is installed using structured detectionConfig.\n */\nasync function isAIToolInstalled(toolKey: string): Promise<boolean> {\n const toolConfig = AI_TOOL_PATHS.find((agent) => agent.key === toolKey);\n if (!toolConfig?.detectionConfig) return false;\n\n return evaluateDetection(toolConfig.detectionConfig);\n}\n\n/**\n * Detect all installed AI tools\n * Results are cached for the duration of the process\n */\nexport async function detectInstalledAITools(): Promise<string[]> {\n // Return cached result if available\n if (cachedAITools !== null) {\n return cachedAITools;\n }\n\n const installedAITools: string[] = [];\n\n // Check each tool in parallel\n const detectionPromises = AI_TOOL_PATHS.map(async (agent) => {\n const isInstalled = await isAIToolInstalled(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 installedAITools.push(result);\n }\n }\n\n // Cache the result\n cachedAITools = installedAITools;\n\n return installedAITools;\n}\n\n/**\n * Clear the AI tool detection cache\n * Useful for testing or when tool installation state may have changed\n */\nexport function clearAIToolCache(): void {\n cachedAITools = null;\n}\n\n/**\n * Override AI tool detection with a specific list of tools\n * Used when --agents flag is provided\n */\nexport function setDetectedAITools(tools: string[]): void {\n cachedAITools = [...tools];\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { r as __toESM } from "./chunk-BbwQpWto.mjs";
3
3
  import { a as Ne, h as defineCommand, i as Le, l as We, p as Ct, t as findSourceRoot, u as Ze } from "./context-detection-DqOTnD6_.mjs";
4
- import { Z as KEBAB_CASE_REGEX, h as require_lib } from "./src-C3-Vz-R7.mjs";
5
- import "./agent-detection-DTiVeO5W.mjs";
4
+ import { _ as require_lib, nt as KEBAB_CASE_REGEX } from "./src-D41VR6ro.mjs";
5
+ import "./ai-tool-detection-CMsBNa9e.mjs";
6
6
  import "./esm-BagM-kVd.mjs";
7
7
  import { mkdir, readFile, readdir, writeFile } from "node:fs/promises";
8
8
  import { dirname, join } from "node:path";
@@ -79,4 +79,4 @@ async function copyProfileTemplate(sourceDir, targetDir, variables) {
79
79
 
80
80
  //#endregion
81
81
  export { createCommand };
82
- //# sourceMappingURL=create-BOcW-DBk.mjs.map
82
+ //# sourceMappingURL=create-SYKl8g0B.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-BOcW-DBk.mjs","names":["p.text","p.isCancel","Handlebars"],"sources":["../src/commands/profile/create.ts"],"sourcesContent":["import { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { KEBAB_CASE_REGEX } from \"@baton-dx/core\";\nimport * as p from \"@clack/prompts\";\nimport { defineCommand } from \"citty\";\nimport Handlebars from \"handlebars\";\nimport { findSourceRoot } from \"../../utils/context-detection.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const createCommand = defineCommand({\n meta: {\n name: \"create\",\n description: \"Create a new profile in your source repository\",\n },\n args: {\n name: {\n type: \"positional\",\n description: \"Profile name (kebab-case)\",\n required: false,\n },\n },\n async run({ args }) {\n p.intro(\"Create Profile\");\n\n // Check for baton.source.yaml in current or parent directories\n const sourceRoot = await findSourceRoot();\n if (!sourceRoot) {\n p.cancel(\"This command must be run inside a source directory (baton.source.yaml not found)\");\n process.exit(1);\n }\n\n // Get profile name — from argument or wizard prompt\n let name = args.name as string | undefined;\n\n if (!name) {\n const nameInput = await p.text({\n message: \"Profile name (kebab-case)\",\n placeholder: \"e.g., backend, frontend, my-profile\",\n validate(value) {\n if (!value || value.trim().length === 0) {\n return \"Profile name is required\";\n }\n if (!KEBAB_CASE_REGEX.test(value.trim())) {\n return \"Profile name must be in kebab-case (e.g., my-profile, backend, frontend)\";\n }\n },\n });\n\n if (p.isCancel(nameInput)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n name = (nameInput as string).trim();\n }\n\n // Validate name format (kebab-case)\n if (!KEBAB_CASE_REGEX.test(name)) {\n p.cancel(\"Profile name must be in kebab-case (e.g., my-profile, backend, frontend)\");\n process.exit(1);\n }\n\n // Check if profile already exists in profiles/ directory\n const targetDir = join(sourceRoot, \"profiles\", name);\n try {\n await readdir(targetDir);\n p.cancel(`Profile '${name}' already exists in profiles/${name}/`);\n process.exit(1);\n } catch {\n // Directory doesn't exist - good to proceed\n }\n\n // Create profile directory\n await mkdir(targetDir, { recursive: true });\n\n // Copy minimal template files\n const templateDir = join(__dirname, \"templates\", \"profile\", \"minimal\");\n await copyProfileTemplate(templateDir, targetDir, { name });\n\n p.outro(`Profile '${name}' created in profiles/${name}/`);\n },\n});\n\n/**\n * Recursively copy profile template with variable substitution\n */\nasync function copyProfileTemplate(\n sourceDir: string,\n targetDir: string,\n variables: { name: string },\n): Promise<void> {\n const entries = await readdir(sourceDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, entry.name);\n\n if (entry.isDirectory()) {\n await mkdir(targetPath, { recursive: true });\n await copyProfileTemplate(sourcePath, targetPath, variables);\n } else {\n // Read file content\n const content = await readFile(sourcePath, \"utf-8\");\n\n // Apply Handlebars substitution for text files\n const processed = Handlebars.compile(content, { noEscape: true })(variables);\n\n // Write processed content\n await writeFile(targetPath, processed, \"utf-8\");\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AASA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAEzD,MAAa,gBAAgB,cAAc;CACzC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,EACJ,MAAM;EACJ,MAAM;EACN,aAAa;EACb,UAAU;EACX,EACF;CACD,MAAM,IAAI,EAAE,QAAQ;AAClB,KAAQ,iBAAiB;EAGzB,MAAM,aAAa,MAAM,gBAAgB;AACzC,MAAI,CAAC,YAAY;AACf,MAAS,mFAAmF;AAC5F,WAAQ,KAAK,EAAE;;EAIjB,IAAI,OAAO,KAAK;AAEhB,MAAI,CAAC,MAAM;GACT,MAAM,YAAY,MAAMA,GAAO;IAC7B,SAAS;IACT,aAAa;IACb,SAAS,OAAO;AACd,SAAI,CAAC,SAAS,MAAM,MAAM,CAAC,WAAW,EACpC,QAAO;AAET,SAAI,CAAC,iBAAiB,KAAK,MAAM,MAAM,CAAC,CACtC,QAAO;;IAGZ,CAAC;AAEF,OAAIC,GAAW,UAAU,EAAE;AACzB,OAAS,aAAa;AACtB,YAAQ,KAAK,EAAE;;AAGjB,UAAQ,UAAqB,MAAM;;AAIrC,MAAI,CAAC,iBAAiB,KAAK,KAAK,EAAE;AAChC,MAAS,2EAA2E;AACpF,WAAQ,KAAK,EAAE;;EAIjB,MAAM,YAAY,KAAK,YAAY,YAAY,KAAK;AACpD,MAAI;AACF,SAAM,QAAQ,UAAU;AACxB,MAAS,YAAY,KAAK,+BAA+B,KAAK,GAAG;AACjE,WAAQ,KAAK,EAAE;UACT;AAKR,QAAM,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAI3C,QAAM,oBADc,KAAK,WAAW,aAAa,WAAW,UAAU,EAC/B,WAAW,EAAE,MAAM,CAAC;AAE3D,KAAQ,YAAY,KAAK,wBAAwB,KAAK,GAAG;;CAE5D,CAAC;;;;AAKF,eAAe,oBACb,WACA,WACA,WACe;CACf,MAAM,UAAU,MAAM,QAAQ,WAAW,EAAE,eAAe,MAAM,CAAC;AAEjE,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,aAAa,KAAK,WAAW,MAAM,KAAK;EAC9C,MAAM,aAAa,KAAK,WAAW,MAAM,KAAK;AAE9C,MAAI,MAAM,aAAa,EAAE;AACvB,SAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;AAC5C,SAAM,oBAAoB,YAAY,YAAY,UAAU;SACvD;GAEL,MAAM,UAAU,MAAM,SAAS,YAAY,QAAQ;AAMnD,SAAM,UAAU,YAHEC,mBAAW,QAAQ,SAAS,EAAE,UAAU,MAAM,CAAC,CAAC,UAAU,EAGrC,QAAQ"}
1
+ {"version":3,"file":"create-SYKl8g0B.mjs","names":["p.text","p.isCancel","Handlebars"],"sources":["../src/commands/profile/create.ts"],"sourcesContent":["import { mkdir, readFile, readdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { KEBAB_CASE_REGEX } from \"@baton-dx/core\";\nimport * as p from \"@clack/prompts\";\nimport { defineCommand } from \"citty\";\nimport Handlebars from \"handlebars\";\nimport { findSourceRoot } from \"../../utils/context-detection.js\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport const createCommand = defineCommand({\n meta: {\n name: \"create\",\n description: \"Create a new profile in your source repository\",\n },\n args: {\n name: {\n type: \"positional\",\n description: \"Profile name (kebab-case)\",\n required: false,\n },\n },\n async run({ args }) {\n p.intro(\"Create Profile\");\n\n // Check for baton.source.yaml in current or parent directories\n const sourceRoot = await findSourceRoot();\n if (!sourceRoot) {\n p.cancel(\"This command must be run inside a source directory (baton.source.yaml not found)\");\n process.exit(1);\n }\n\n // Get profile name — from argument or wizard prompt\n let name = args.name as string | undefined;\n\n if (!name) {\n const nameInput = await p.text({\n message: \"Profile name (kebab-case)\",\n placeholder: \"e.g., backend, frontend, my-profile\",\n validate(value) {\n if (!value || value.trim().length === 0) {\n return \"Profile name is required\";\n }\n if (!KEBAB_CASE_REGEX.test(value.trim())) {\n return \"Profile name must be in kebab-case (e.g., my-profile, backend, frontend)\";\n }\n },\n });\n\n if (p.isCancel(nameInput)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n\n name = (nameInput as string).trim();\n }\n\n // Validate name format (kebab-case)\n if (!KEBAB_CASE_REGEX.test(name)) {\n p.cancel(\"Profile name must be in kebab-case (e.g., my-profile, backend, frontend)\");\n process.exit(1);\n }\n\n // Check if profile already exists in profiles/ directory\n const targetDir = join(sourceRoot, \"profiles\", name);\n try {\n await readdir(targetDir);\n p.cancel(`Profile '${name}' already exists in profiles/${name}/`);\n process.exit(1);\n } catch {\n // Directory doesn't exist - good to proceed\n }\n\n // Create profile directory\n await mkdir(targetDir, { recursive: true });\n\n // Copy minimal template files\n const templateDir = join(__dirname, \"templates\", \"profile\", \"minimal\");\n await copyProfileTemplate(templateDir, targetDir, { name });\n\n p.outro(`Profile '${name}' created in profiles/${name}/`);\n },\n});\n\n/**\n * Recursively copy profile template with variable substitution\n */\nasync function copyProfileTemplate(\n sourceDir: string,\n targetDir: string,\n variables: { name: string },\n): Promise<void> {\n const entries = await readdir(sourceDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const sourcePath = join(sourceDir, entry.name);\n const targetPath = join(targetDir, entry.name);\n\n if (entry.isDirectory()) {\n await mkdir(targetPath, { recursive: true });\n await copyProfileTemplate(sourcePath, targetPath, variables);\n } else {\n // Read file content\n const content = await readFile(sourcePath, \"utf-8\");\n\n // Apply Handlebars substitution for text files\n const processed = Handlebars.compile(content, { noEscape: true })(variables);\n\n // Write processed content\n await writeFile(targetPath, processed, \"utf-8\");\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;AASA,MAAM,YAAY,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAEzD,MAAa,gBAAgB,cAAc;CACzC,MAAM;EACJ,MAAM;EACN,aAAa;EACd;CACD,MAAM,EACJ,MAAM;EACJ,MAAM;EACN,aAAa;EACb,UAAU;EACX,EACF;CACD,MAAM,IAAI,EAAE,QAAQ;AAClB,KAAQ,iBAAiB;EAGzB,MAAM,aAAa,MAAM,gBAAgB;AACzC,MAAI,CAAC,YAAY;AACf,MAAS,mFAAmF;AAC5F,WAAQ,KAAK,EAAE;;EAIjB,IAAI,OAAO,KAAK;AAEhB,MAAI,CAAC,MAAM;GACT,MAAM,YAAY,MAAMA,GAAO;IAC7B,SAAS;IACT,aAAa;IACb,SAAS,OAAO;AACd,SAAI,CAAC,SAAS,MAAM,MAAM,CAAC,WAAW,EACpC,QAAO;AAET,SAAI,CAAC,iBAAiB,KAAK,MAAM,MAAM,CAAC,CACtC,QAAO;;IAGZ,CAAC;AAEF,OAAIC,GAAW,UAAU,EAAE;AACzB,OAAS,aAAa;AACtB,YAAQ,KAAK,EAAE;;AAGjB,UAAQ,UAAqB,MAAM;;AAIrC,MAAI,CAAC,iBAAiB,KAAK,KAAK,EAAE;AAChC,MAAS,2EAA2E;AACpF,WAAQ,KAAK,EAAE;;EAIjB,MAAM,YAAY,KAAK,YAAY,YAAY,KAAK;AACpD,MAAI;AACF,SAAM,QAAQ,UAAU;AACxB,MAAS,YAAY,KAAK,+BAA+B,KAAK,GAAG;AACjE,WAAQ,KAAK,EAAE;UACT;AAKR,QAAM,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;AAI3C,QAAM,oBADc,KAAK,WAAW,aAAa,WAAW,UAAU,EAC/B,WAAW,EAAE,MAAM,CAAC;AAE3D,KAAQ,YAAY,KAAK,wBAAwB,KAAK,GAAG;;CAE5D,CAAC;;;;AAKF,eAAe,oBACb,WACA,WACA,WACe;CACf,MAAM,UAAU,MAAM,QAAQ,WAAW,EAAE,eAAe,MAAM,CAAC;AAEjE,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,aAAa,KAAK,WAAW,MAAM,KAAK;EAC9C,MAAM,aAAa,KAAK,WAAW,MAAM,KAAK;AAE9C,MAAI,MAAM,aAAa,EAAE;AACvB,SAAM,MAAM,YAAY,EAAE,WAAW,MAAM,CAAC;AAC5C,SAAM,oBAAoB,YAAY,YAAY,UAAU;SACvD;GAEL,MAAM,UAAU,MAAM,SAAS,YAAY,QAAQ;AAMnD,SAAM,UAAU,YAHEC,mBAAW,QAAQ,SAAS,EAAE,UAAU,MAAM,CAAC,CAAC,UAAU,EAGrC,QAAQ"}