@industry-theme/agent-panels 0.2.46 → 0.2.47

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.
@@ -2795,133 +2795,62 @@ const parseSkillContent = async (content2, path2, fileTree, fileSystemAdapter, i
2795
2795
  };
2796
2796
  };
2797
2797
  const EMPTY_SKILLS_ARRAY$1 = [];
2798
- const getDeduplicationKey = (skill) => {
2799
- var _a, _b, _c;
2800
- if (((_a = skill.metadata) == null ? void 0 : _a.owner) && ((_b = skill.metadata) == null ? void 0 : _b.repo) && ((_c = skill.metadata) == null ? void 0 : _c.skillPath)) {
2801
- return `github:${skill.metadata.owner}/${skill.metadata.repo}/${skill.metadata.skillPath}`;
2802
- }
2803
- const normalizedName = skill.name.toLowerCase().replace(/\s+/g, "-");
2804
- return `name:${normalizedName}`;
2805
- };
2806
- const comparePriority = (skill1, skill2) => {
2807
- var _a, _b;
2808
- if (skill1.priority !== skill2.priority) {
2809
- return skill1.priority < skill2.priority;
2810
- }
2811
- const time1 = ((_a = skill1.metadata) == null ? void 0 : _a.installedAt) ? new Date(skill1.metadata.installedAt).getTime() : 0;
2812
- const time2 = ((_b = skill2.metadata) == null ? void 0 : _b.installedAt) ? new Date(skill2.metadata.installedAt).getTime() : 0;
2813
- return time1 > time2;
2814
- };
2815
- const skillToInstallation = (skill) => ({
2816
- path: skill.path,
2817
- source: skill.source,
2818
- priority: skill.priority,
2819
- skillFolderPath: skill.skillFolderPath,
2820
- metadata: skill.metadata
2821
- });
2822
- const deduplicateSkills = (skills, isBrowserMode = false) => {
2823
- if (isBrowserMode) {
2824
- return skills;
2825
- }
2826
- if (skills.length === 0) {
2827
- return skills;
2828
- }
2829
- const skillGroups = /* @__PURE__ */ new Map();
2830
- for (const skill of skills) {
2831
- const key = getDeduplicationKey(skill);
2832
- const group = skillGroups.get(key) || [];
2833
- group.push(skill);
2834
- skillGroups.set(key, group);
2835
- }
2836
- const deduplicatedSkills = [];
2837
- for (const group of skillGroups.values()) {
2838
- if (group.length === 1) {
2839
- deduplicatedSkills.push({
2840
- ...group[0],
2841
- installedLocations: [skillToInstallation(group[0])]
2842
- });
2843
- continue;
2844
- }
2845
- const sortedByPriority = [...group].sort(
2846
- (a, b) => comparePriority(a, b) ? -1 : 1
2847
- );
2848
- const primary = sortedByPriority[0];
2849
- const installations = group.map(skillToInstallation);
2850
- installations.sort((a, b) => a.priority - b.priority);
2851
- deduplicatedSkills.push({
2852
- ...primary,
2853
- installedLocations: installations
2854
- });
2855
- }
2856
- return deduplicatedSkills;
2857
- };
2858
- const useSkillsData = ({
2798
+ const useSkillsBrowseData = ({
2859
2799
  context
2860
2800
  }) => {
2861
- var _a, _b, _c;
2801
+ var _a, _b;
2862
2802
  const [skills, setSkills] = useState(EMPTY_SKILLS_ARRAY$1);
2863
2803
  const [isLoading, setIsLoading] = useState(true);
2864
2804
  const [error, setError] = useState(null);
2865
2805
  const fileTreeSlice = context.fileTree;
2866
2806
  const fileTree = fileTreeSlice == null ? void 0 : fileTreeSlice.data;
2867
2807
  const fileTreeSha = fileTree == null ? void 0 : fileTree.sha;
2868
- const globalSkillsSlice = context.globalSkills;
2869
- const globalSkills = ((_a = globalSkillsSlice == null ? void 0 : globalSkillsSlice.data) == null ? void 0 : _a.skills) ?? EMPTY_SKILLS_ARRAY$1;
2870
- const globalSkillsCount = globalSkills.length;
2871
- const repoPath = (_b = context.currentScope.repository) == null ? void 0 : _b.path;
2872
- const fileSystem = (_c = context.adapters) == null ? void 0 : _c.fileSystem;
2808
+ const repoPath = (_a = context.currentScope.repository) == null ? void 0 : _a.path;
2809
+ const fileSystem = (_b = context.adapters) == null ? void 0 : _b.fileSystem;
2873
2810
  const lastLoadedSha = useRef(void 0);
2874
- const lastGlobalSkillsCount = useRef(0);
2875
2811
  const loadSkills = useCallback(async () => {
2876
- if (fileTreeSha === lastLoadedSha.current && globalSkillsCount === lastGlobalSkillsCount.current) {
2812
+ if (fileTreeSha === lastLoadedSha.current) {
2877
2813
  return;
2878
2814
  }
2879
2815
  setIsLoading(true);
2880
2816
  setError(null);
2881
2817
  try {
2882
- let localSkills = [];
2883
- let isBrowserMode = false;
2818
+ let repoSkills = [];
2884
2819
  if (fileTree && (fileSystem == null ? void 0 : fileSystem.readFile) && repoPath) {
2885
- isBrowserMode = !repoPath.startsWith("/");
2886
- console.log("[useSkillsData] fileTree:", fileTree);
2887
- console.log("[useSkillsData] typeof fileTree:", typeof fileTree);
2888
- console.log("[useSkillsData] fileTree keys:", Object.keys(fileTree));
2889
- console.log("[useSkillsData] Browser mode:", isBrowserMode);
2890
- const skillPaths = findSkillFiles(fileTree, isBrowserMode);
2891
- console.log("[useSkillsData] Found skill paths:", skillPaths);
2820
+ const isGithubRepo = !repoPath.startsWith("/");
2821
+ if (!isGithubRepo) {
2822
+ console.warn("[useSkillsBrowseData] Not a GitHub repo, skipping skill load");
2823
+ setSkills(EMPTY_SKILLS_ARRAY$1);
2824
+ lastLoadedSha.current = fileTreeSha;
2825
+ setIsLoading(false);
2826
+ return;
2827
+ }
2828
+ const skillPaths = findSkillFiles(fileTree, true);
2892
2829
  const skillPromises = skillPaths.map(async (skillPath) => {
2893
2830
  try {
2894
- const fullPath = isBrowserMode ? skillPath : `${repoPath}/${skillPath}`;
2895
- const content2 = await fileSystem.readFile(fullPath);
2896
- return parseSkillContent(content2, skillPath, fileTree, fileSystem, isBrowserMode);
2831
+ const content2 = await fileSystem.readFile(skillPath);
2832
+ return parseSkillContent(content2, skillPath, fileTree, fileSystem, true);
2897
2833
  } catch (err) {
2898
- console.error(`Failed to read skill at ${skillPath}:`, err);
2834
+ console.error(`[useSkillsBrowseData] Failed to read skill at ${skillPath}:`, err);
2899
2835
  return null;
2900
2836
  }
2901
2837
  });
2902
- localSkills = (await Promise.all(skillPromises)).filter(
2838
+ repoSkills = (await Promise.all(skillPromises)).filter(
2903
2839
  (skill) => skill !== null
2904
2840
  );
2905
2841
  }
2906
- console.log("[useSkillsData] Global skills:", globalSkills);
2907
- const allSkills = [...localSkills, ...globalSkills];
2908
- console.log("[useSkillsData] Total skills before deduplication:", allSkills.length);
2909
- const deduplicatedSkills = deduplicateSkills(allSkills, isBrowserMode);
2910
- console.log("[useSkillsData] Total skills after deduplication:", deduplicatedSkills.length);
2911
- setSkills(deduplicatedSkills);
2842
+ setSkills(repoSkills);
2912
2843
  lastLoadedSha.current = fileTreeSha;
2913
- lastGlobalSkillsCount.current = globalSkillsCount;
2914
2844
  } catch (err) {
2915
2845
  const errorMessage = err instanceof Error ? err.message : "Failed to load skills";
2916
2846
  setError(errorMessage);
2917
- console.error("Error loading skills:", err);
2847
+ console.error("[useSkillsBrowseData] Error loading skills:", err);
2918
2848
  } finally {
2919
2849
  setIsLoading(false);
2920
2850
  }
2921
- }, [fileTree, fileTreeSha, globalSkills, globalSkillsCount, repoPath, fileSystem]);
2851
+ }, [fileTree, fileTreeSha, repoPath, fileSystem]);
2922
2852
  const refreshSkills = useCallback(async () => {
2923
2853
  lastLoadedSha.current = void 0;
2924
- lastGlobalSkillsCount.current = -1;
2925
2854
  await loadSkills();
2926
2855
  }, [loadSkills]);
2927
2856
  useEffect(() => {
@@ -3528,21 +3457,30 @@ ${otherLocations.map((loc) => `${abbreviateSourceName(loc.source)}: ${loc.path}`
3528
3457
  }
3529
3458
  );
3530
3459
  };
3531
- const SkillsListPanel = ({
3460
+ const SkillsBrowsePanel = ({
3532
3461
  context,
3533
3462
  events,
3534
- browseMode = false,
3535
3463
  supportsRefresh = false
3536
3464
  }) => {
3537
- var _a;
3465
+ var _a, _b;
3538
3466
  const { theme: theme2 } = useTheme();
3539
3467
  const panelRef = useRef(null);
3540
3468
  const [selectedSkillId, setSelectedSkillId] = useState(null);
3541
3469
  const [searchQuery, setSearchQuery] = useState("");
3542
- const [skillFilter, setSkillFilter] = useState("project");
3543
3470
  const [isRefreshing, setIsRefreshing] = useState(false);
3544
- const { skills, isLoading, error, refreshSkills } = useSkillsData({ context });
3545
- gt("skills-list", events, () => {
3471
+ const { skills, isLoading, error, refreshSkills } = useSkillsBrowseData({ context });
3472
+ const fileTreeSlice = context.fileTree;
3473
+ const fileTree = fileTreeSlice == null ? void 0 : fileTreeSlice.data;
3474
+ const sourceInfo = (_a = fileTree == null ? void 0 : fileTree.metadata) == null ? void 0 : _a.sourceInfo;
3475
+ const owner = sourceInfo == null ? void 0 : sourceInfo.owner;
3476
+ const repo = sourceInfo == null ? void 0 : sourceInfo.repo;
3477
+ const globalSkillsSlice = context.globalSkills;
3478
+ const installedSkillNames = useMemo(() => {
3479
+ var _a2;
3480
+ const globalSkills = ((_a2 = globalSkillsSlice == null ? void 0 : globalSkillsSlice.data) == null ? void 0 : _a2.skills) || [];
3481
+ return new Set(globalSkills.map((skill) => skill.name));
3482
+ }, [(_b = globalSkillsSlice == null ? void 0 : globalSkillsSlice.data) == null ? void 0 : _b.skills]);
3483
+ gt("skills-browse", events, () => {
3546
3484
  var _a2;
3547
3485
  return (_a2 = panelRef.current) == null ? void 0 : _a2.focus();
3548
3486
  });
@@ -3558,52 +3496,29 @@ const SkillsListPanel = ({
3558
3496
  unsubscribeUninstalled();
3559
3497
  };
3560
3498
  }, [events, refreshSkills]);
3561
- const hasRepository = useMemo(() => {
3562
- var _a2;
3563
- return !!((_a2 = context.fileTree) == null ? void 0 : _a2.data);
3564
- }, [(_a = context.fileTree) == null ? void 0 : _a.data]);
3565
3499
  const filteredSkills = useMemo(() => {
3566
3500
  let filtered = skills;
3567
- if (skillFilter === "project") {
3568
- filtered = filtered.filter((skill) => {
3569
- if (skill.installedLocations && skill.installedLocations.length > 0) {
3570
- return skill.installedLocations.some(
3571
- (loc) => loc.source === "project-universal" || loc.source === "project-claude" || loc.source === "project-other"
3572
- );
3573
- }
3574
- return skill.source === "project-universal" || skill.source === "project-claude" || skill.source === "project-other";
3575
- });
3576
- } else if (skillFilter === "global") {
3577
- filtered = filtered.filter((skill) => {
3578
- if (skill.installedLocations && skill.installedLocations.length > 0) {
3579
- return skill.installedLocations.some(
3580
- (loc) => loc.source === "global-universal" || loc.source === "global-claude"
3581
- );
3582
- }
3583
- return skill.source === "global-universal" || skill.source === "global-claude";
3584
- });
3585
- }
3586
3501
  if (searchQuery.trim()) {
3587
3502
  const query = searchQuery.toLowerCase().trim();
3588
3503
  filtered = filtered.filter((skill) => {
3589
- var _a2, _b;
3504
+ var _a2, _b2;
3590
3505
  if (skill.name.toLowerCase().includes(query)) return true;
3591
3506
  if ((_a2 = skill.description) == null ? void 0 : _a2.toLowerCase().includes(query)) return true;
3592
- if ((_b = skill.capabilities) == null ? void 0 : _b.some((cap2) => cap2.toLowerCase().includes(query)))
3507
+ if ((_b2 = skill.capabilities) == null ? void 0 : _b2.some((cap2) => cap2.toLowerCase().includes(query)))
3593
3508
  return true;
3594
3509
  if (skill.path.toLowerCase().includes(query)) return true;
3595
3510
  return false;
3596
3511
  });
3597
3512
  }
3598
3513
  return filtered;
3599
- }, [skills, searchQuery, skillFilter]);
3514
+ }, [skills, searchQuery]);
3600
3515
  const handleSkillClick = (skill) => {
3601
3516
  setSelectedSkillId(skill.id);
3602
3517
  if (events) {
3603
3518
  events.emit({
3604
3519
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3605
3520
  type: "skill:selected",
3606
- source: "skills-list-panel",
3521
+ source: "skills-browse-panel",
3607
3522
  timestamp: Date.now(),
3608
3523
  payload: { skillId: skill.id, skill }
3609
3524
  });
@@ -3615,7 +3530,7 @@ const SkillsListPanel = ({
3615
3530
  events.emit({
3616
3531
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
3617
3532
  type: "skills:refresh",
3618
- source: "skills-list-panel",
3533
+ source: "skills-browse-panel",
3619
3534
  timestamp: Date.now(),
3620
3535
  payload: {}
3621
3536
  });
@@ -3656,7 +3571,50 @@ const SkillsListPanel = ({
3656
3571
  },
3657
3572
  children: [
3658
3573
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
3659
- /* @__PURE__ */ jsx(
3574
+ owner && repo ? /* @__PURE__ */ jsxs(
3575
+ "a",
3576
+ {
3577
+ href: `https://github.com/${owner}/${repo}`,
3578
+ target: "_blank",
3579
+ rel: "noopener noreferrer",
3580
+ style: {
3581
+ textDecoration: "none",
3582
+ display: "flex",
3583
+ flexDirection: "column",
3584
+ gap: "2px"
3585
+ },
3586
+ children: [
3587
+ /* @__PURE__ */ jsx(
3588
+ "h2",
3589
+ {
3590
+ style: {
3591
+ margin: 0,
3592
+ fontSize: theme2.fontSizes[4],
3593
+ color: theme2.colors.text,
3594
+ fontFamily: theme2.fonts.monospace,
3595
+ lineHeight: 1.2
3596
+ },
3597
+ onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
3598
+ onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
3599
+ children: String(repo || "")
3600
+ }
3601
+ ),
3602
+ /* @__PURE__ */ jsx(
3603
+ "div",
3604
+ {
3605
+ style: {
3606
+ fontSize: theme2.fontSizes[1],
3607
+ color: theme2.colors.textSecondary,
3608
+ fontFamily: theme2.fonts.monospace
3609
+ },
3610
+ onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
3611
+ onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
3612
+ children: String(owner || "")
3613
+ }
3614
+ )
3615
+ ]
3616
+ }
3617
+ ) : /* @__PURE__ */ jsx(
3660
3618
  "h2",
3661
3619
  {
3662
3620
  style: {
@@ -3676,7 +3634,7 @@ const SkillsListPanel = ({
3676
3634
  },
3677
3635
  onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
3678
3636
  onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
3679
- children: "Agent Skills"
3637
+ children: "Browse Skills"
3680
3638
  }
3681
3639
  )
3682
3640
  }
@@ -3802,66 +3760,6 @@ const SkillsListPanel = ({
3802
3760
  ]
3803
3761
  }
3804
3762
  ),
3805
- hasRepository && /* @__PURE__ */ jsxs(
3806
- "div",
3807
- {
3808
- style: {
3809
- flexShrink: 0,
3810
- display: "flex",
3811
- gap: "8px"
3812
- },
3813
- children: [
3814
- /* @__PURE__ */ jsx(
3815
- "button",
3816
- {
3817
- onClick: () => setSkillFilter("project"),
3818
- style: {
3819
- flex: 1,
3820
- padding: "8px 16px",
3821
- fontSize: theme2.fontSizes[1],
3822
- fontFamily: theme2.fonts.body,
3823
- border: `1px solid ${skillFilter === "project" ? theme2.colors.primary : theme2.colors.border}`,
3824
- borderRadius: theme2.radii[1],
3825
- background: skillFilter === "project" ? `${theme2.colors.primary}15` : theme2.colors.backgroundSecondary,
3826
- color: skillFilter === "project" ? theme2.colors.primary : theme2.colors.text,
3827
- cursor: "pointer",
3828
- display: "flex",
3829
- alignItems: "center",
3830
- justifyContent: "center",
3831
- gap: "6px",
3832
- fontWeight: skillFilter === "project" ? 600 : 400,
3833
- transition: "all 0.2s ease"
3834
- },
3835
- children: browseMode ? "Git Repo" : "Project"
3836
- }
3837
- ),
3838
- /* @__PURE__ */ jsx(
3839
- "button",
3840
- {
3841
- onClick: () => setSkillFilter("global"),
3842
- style: {
3843
- flex: 1,
3844
- padding: "8px 16px",
3845
- fontSize: theme2.fontSizes[1],
3846
- fontFamily: theme2.fonts.body,
3847
- border: `1px solid ${skillFilter === "global" ? theme2.colors.primary : theme2.colors.border}`,
3848
- borderRadius: theme2.radii[1],
3849
- background: skillFilter === "global" ? `${theme2.colors.primary}15` : theme2.colors.backgroundSecondary,
3850
- color: skillFilter === "global" ? theme2.colors.primary : theme2.colors.text,
3851
- cursor: "pointer",
3852
- display: "flex",
3853
- alignItems: "center",
3854
- justifyContent: "center",
3855
- gap: "6px",
3856
- fontWeight: skillFilter === "global" ? 600 : 400,
3857
- transition: "all 0.2s ease"
3858
- },
3859
- children: "Global"
3860
- }
3861
- )
3862
- ]
3863
- }
3864
- ),
3865
3763
  error && /* @__PURE__ */ jsxs(
3866
3764
  "div",
3867
3765
  {
@@ -3902,7 +3800,7 @@ const SkillsListPanel = ({
3902
3800
  color: theme2.colors.textSecondary,
3903
3801
  fontSize: theme2.fontSizes[2]
3904
3802
  },
3905
- children: "Loading skills..."
3803
+ children: "Loading skills from repository..."
3906
3804
  }
3907
3805
  ) : filteredSkills.length === 0 ? /* @__PURE__ */ jsxs(
3908
3806
  "div",
@@ -3920,8 +3818,8 @@ const SkillsListPanel = ({
3920
3818
  children: [
3921
3819
  /* @__PURE__ */ jsx(FileCode, { size: 48, color: theme2.colors.border }),
3922
3820
  /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
3923
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: theme2.fontSizes[2] }, children: searchQuery ? "No skills match your search" : "No skills found" }),
3924
- /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: theme2.fontSizes[1] }, children: searchQuery ? "Try a different search term" : "Add SKILL.md files to your repository to get started" })
3821
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: theme2.fontSizes[2] }, children: searchQuery ? "No skills match your search" : "No skills found in this repository" }),
3822
+ /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: theme2.fontSizes[1] }, children: searchQuery ? "Try a different search term" : "This repository does not contain any SKILL.md files" })
3925
3823
  ] })
3926
3824
  ]
3927
3825
  }
@@ -3940,7 +3838,7 @@ const SkillsListPanel = ({
3940
3838
  skill,
3941
3839
  onClick: handleSkillClick,
3942
3840
  isSelected: selectedSkillId === skill.id,
3943
- filterContext: skillFilter
3841
+ isInstalled: installedSkillNames.has(skill.name)
3944
3842
  },
3945
3843
  skill.id
3946
3844
  ))
@@ -3958,62 +3856,133 @@ const SkillsListPanel = ({
3958
3856
  );
3959
3857
  };
3960
3858
  const EMPTY_SKILLS_ARRAY = [];
3961
- const useSkillsBrowseData = ({
3859
+ const getDeduplicationKey = (skill) => {
3860
+ var _a, _b, _c;
3861
+ if (((_a = skill.metadata) == null ? void 0 : _a.owner) && ((_b = skill.metadata) == null ? void 0 : _b.repo) && ((_c = skill.metadata) == null ? void 0 : _c.skillPath)) {
3862
+ return `github:${skill.metadata.owner}/${skill.metadata.repo}/${skill.metadata.skillPath}`;
3863
+ }
3864
+ const normalizedName = skill.name.toLowerCase().replace(/\s+/g, "-");
3865
+ return `name:${normalizedName}`;
3866
+ };
3867
+ const comparePriority = (skill1, skill2) => {
3868
+ var _a, _b;
3869
+ if (skill1.priority !== skill2.priority) {
3870
+ return skill1.priority < skill2.priority;
3871
+ }
3872
+ const time1 = ((_a = skill1.metadata) == null ? void 0 : _a.installedAt) ? new Date(skill1.metadata.installedAt).getTime() : 0;
3873
+ const time2 = ((_b = skill2.metadata) == null ? void 0 : _b.installedAt) ? new Date(skill2.metadata.installedAt).getTime() : 0;
3874
+ return time1 > time2;
3875
+ };
3876
+ const skillToInstallation = (skill) => ({
3877
+ path: skill.path,
3878
+ source: skill.source,
3879
+ priority: skill.priority,
3880
+ skillFolderPath: skill.skillFolderPath,
3881
+ metadata: skill.metadata
3882
+ });
3883
+ const deduplicateSkills = (skills, isBrowserMode = false) => {
3884
+ if (isBrowserMode) {
3885
+ return skills;
3886
+ }
3887
+ if (skills.length === 0) {
3888
+ return skills;
3889
+ }
3890
+ const skillGroups = /* @__PURE__ */ new Map();
3891
+ for (const skill of skills) {
3892
+ const key = getDeduplicationKey(skill);
3893
+ const group = skillGroups.get(key) || [];
3894
+ group.push(skill);
3895
+ skillGroups.set(key, group);
3896
+ }
3897
+ const deduplicatedSkills = [];
3898
+ for (const group of skillGroups.values()) {
3899
+ if (group.length === 1) {
3900
+ deduplicatedSkills.push({
3901
+ ...group[0],
3902
+ installedLocations: [skillToInstallation(group[0])]
3903
+ });
3904
+ continue;
3905
+ }
3906
+ const sortedByPriority = [...group].sort(
3907
+ (a, b) => comparePriority(a, b) ? -1 : 1
3908
+ );
3909
+ const primary = sortedByPriority[0];
3910
+ const installations = group.map(skillToInstallation);
3911
+ installations.sort((a, b) => a.priority - b.priority);
3912
+ deduplicatedSkills.push({
3913
+ ...primary,
3914
+ installedLocations: installations
3915
+ });
3916
+ }
3917
+ return deduplicatedSkills;
3918
+ };
3919
+ const useSkillsData = ({
3962
3920
  context
3963
3921
  }) => {
3964
- var _a, _b;
3922
+ var _a, _b, _c;
3965
3923
  const [skills, setSkills] = useState(EMPTY_SKILLS_ARRAY);
3966
3924
  const [isLoading, setIsLoading] = useState(true);
3967
3925
  const [error, setError] = useState(null);
3968
3926
  const fileTreeSlice = context.fileTree;
3969
3927
  const fileTree = fileTreeSlice == null ? void 0 : fileTreeSlice.data;
3970
3928
  const fileTreeSha = fileTree == null ? void 0 : fileTree.sha;
3971
- const repoPath = (_a = context.currentScope.repository) == null ? void 0 : _a.path;
3972
- const fileSystem = (_b = context.adapters) == null ? void 0 : _b.fileSystem;
3929
+ const globalSkillsSlice = context.globalSkills;
3930
+ const globalSkills = ((_a = globalSkillsSlice == null ? void 0 : globalSkillsSlice.data) == null ? void 0 : _a.skills) ?? EMPTY_SKILLS_ARRAY;
3931
+ const globalSkillsCount = globalSkills.length;
3932
+ const repoPath = (_b = context.currentScope.repository) == null ? void 0 : _b.path;
3933
+ const fileSystem = (_c = context.adapters) == null ? void 0 : _c.fileSystem;
3973
3934
  const lastLoadedSha = useRef(void 0);
3935
+ const lastGlobalSkillsCount = useRef(0);
3974
3936
  const loadSkills = useCallback(async () => {
3975
- if (fileTreeSha === lastLoadedSha.current) {
3937
+ if (fileTreeSha === lastLoadedSha.current && globalSkillsCount === lastGlobalSkillsCount.current) {
3976
3938
  return;
3977
3939
  }
3978
3940
  setIsLoading(true);
3979
3941
  setError(null);
3980
3942
  try {
3981
- let repoSkills = [];
3943
+ let localSkills = [];
3944
+ let isBrowserMode = false;
3982
3945
  if (fileTree && (fileSystem == null ? void 0 : fileSystem.readFile) && repoPath) {
3983
- const isGithubRepo = !repoPath.startsWith("/");
3984
- if (!isGithubRepo) {
3985
- console.warn("[useSkillsBrowseData] Not a GitHub repo, skipping skill load");
3986
- setSkills(EMPTY_SKILLS_ARRAY);
3987
- lastLoadedSha.current = fileTreeSha;
3988
- setIsLoading(false);
3989
- return;
3990
- }
3991
- const skillPaths = findSkillFiles(fileTree, true);
3946
+ isBrowserMode = !repoPath.startsWith("/");
3947
+ console.log("[useSkillsData] fileTree:", fileTree);
3948
+ console.log("[useSkillsData] typeof fileTree:", typeof fileTree);
3949
+ console.log("[useSkillsData] fileTree keys:", Object.keys(fileTree));
3950
+ console.log("[useSkillsData] Browser mode:", isBrowserMode);
3951
+ const skillPaths = findSkillFiles(fileTree, isBrowserMode);
3952
+ console.log("[useSkillsData] Found skill paths:", skillPaths);
3992
3953
  const skillPromises = skillPaths.map(async (skillPath) => {
3993
3954
  try {
3994
- const content2 = await fileSystem.readFile(skillPath);
3995
- return parseSkillContent(content2, skillPath, fileTree, fileSystem, true);
3955
+ const fullPath = isBrowserMode ? skillPath : `${repoPath}/${skillPath}`;
3956
+ const content2 = await fileSystem.readFile(fullPath);
3957
+ return parseSkillContent(content2, skillPath, fileTree, fileSystem, isBrowserMode);
3996
3958
  } catch (err) {
3997
- console.error(`[useSkillsBrowseData] Failed to read skill at ${skillPath}:`, err);
3959
+ console.error(`Failed to read skill at ${skillPath}:`, err);
3998
3960
  return null;
3999
3961
  }
4000
3962
  });
4001
- repoSkills = (await Promise.all(skillPromises)).filter(
3963
+ localSkills = (await Promise.all(skillPromises)).filter(
4002
3964
  (skill) => skill !== null
4003
3965
  );
4004
3966
  }
4005
- setSkills(repoSkills);
3967
+ console.log("[useSkillsData] Global skills:", globalSkills);
3968
+ const allSkills = [...localSkills, ...globalSkills];
3969
+ console.log("[useSkillsData] Total skills before deduplication:", allSkills.length);
3970
+ const deduplicatedSkills = deduplicateSkills(allSkills, isBrowserMode);
3971
+ console.log("[useSkillsData] Total skills after deduplication:", deduplicatedSkills.length);
3972
+ setSkills(deduplicatedSkills);
4006
3973
  lastLoadedSha.current = fileTreeSha;
3974
+ lastGlobalSkillsCount.current = globalSkillsCount;
4007
3975
  } catch (err) {
4008
3976
  const errorMessage = err instanceof Error ? err.message : "Failed to load skills";
4009
3977
  setError(errorMessage);
4010
- console.error("[useSkillsBrowseData] Error loading skills:", err);
3978
+ console.error("Error loading skills:", err);
4011
3979
  } finally {
4012
3980
  setIsLoading(false);
4013
3981
  }
4014
- }, [fileTree, fileTreeSha, repoPath, fileSystem]);
3982
+ }, [fileTree, fileTreeSha, globalSkills, globalSkillsCount, repoPath, fileSystem]);
4015
3983
  const refreshSkills = useCallback(async () => {
4016
3984
  lastLoadedSha.current = void 0;
3985
+ lastGlobalSkillsCount.current = -1;
4017
3986
  await loadSkills();
4018
3987
  }, [loadSkills]);
4019
3988
  useEffect(() => {
@@ -4026,32 +3995,20 @@ const useSkillsBrowseData = ({
4026
3995
  refreshSkills
4027
3996
  };
4028
3997
  };
4029
- const SkillsBrowsePanel = ({
3998
+ const GlobalSkillsPanel = ({
4030
3999
  context,
4031
4000
  events,
4032
4001
  supportsRefresh = false
4033
4002
  }) => {
4034
- var _a, _b;
4035
4003
  const { theme: theme2 } = useTheme();
4036
4004
  const panelRef = useRef(null);
4037
4005
  const [selectedSkillId, setSelectedSkillId] = useState(null);
4038
4006
  const [searchQuery, setSearchQuery] = useState("");
4039
4007
  const [isRefreshing, setIsRefreshing] = useState(false);
4040
- const { skills, isLoading, error, refreshSkills } = useSkillsBrowseData({ context });
4041
- const fileTreeSlice = context.fileTree;
4042
- const fileTree = fileTreeSlice == null ? void 0 : fileTreeSlice.data;
4043
- const sourceInfo = (_a = fileTree == null ? void 0 : fileTree.metadata) == null ? void 0 : _a.sourceInfo;
4044
- const owner = sourceInfo == null ? void 0 : sourceInfo.owner;
4045
- const repo = sourceInfo == null ? void 0 : sourceInfo.repo;
4046
- const globalSkillsSlice = context.globalSkills;
4047
- const installedSkillNames = useMemo(() => {
4048
- var _a2;
4049
- const globalSkills = ((_a2 = globalSkillsSlice == null ? void 0 : globalSkillsSlice.data) == null ? void 0 : _a2.skills) || [];
4050
- return new Set(globalSkills.map((skill) => skill.name));
4051
- }, [(_b = globalSkillsSlice == null ? void 0 : globalSkillsSlice.data) == null ? void 0 : _b.skills]);
4052
- gt("skills-browse", events, () => {
4053
- var _a2;
4054
- return (_a2 = panelRef.current) == null ? void 0 : _a2.focus();
4008
+ const { skills, isLoading, error, refreshSkills } = useSkillsData({ context });
4009
+ gt("global-skills", events, () => {
4010
+ var _a;
4011
+ return (_a = panelRef.current) == null ? void 0 : _a.focus();
4055
4012
  });
4056
4013
  useEffect(() => {
4057
4014
  const unsubscribeInstalled = events.on("skill:installed", () => {
@@ -4066,14 +4023,21 @@ const SkillsBrowsePanel = ({
4066
4023
  };
4067
4024
  }, [events, refreshSkills]);
4068
4025
  const filteredSkills = useMemo(() => {
4069
- let filtered = skills;
4026
+ let filtered = skills.filter((skill) => {
4027
+ if (skill.installedLocations && skill.installedLocations.length > 0) {
4028
+ return skill.installedLocations.some(
4029
+ (loc) => loc.source === "global-universal" || loc.source === "global-claude"
4030
+ );
4031
+ }
4032
+ return skill.source === "global-universal" || skill.source === "global-claude";
4033
+ });
4070
4034
  if (searchQuery.trim()) {
4071
4035
  const query = searchQuery.toLowerCase().trim();
4072
4036
  filtered = filtered.filter((skill) => {
4073
- var _a2, _b2;
4037
+ var _a, _b;
4074
4038
  if (skill.name.toLowerCase().includes(query)) return true;
4075
- if ((_a2 = skill.description) == null ? void 0 : _a2.toLowerCase().includes(query)) return true;
4076
- if ((_b2 = skill.capabilities) == null ? void 0 : _b2.some((cap2) => cap2.toLowerCase().includes(query)))
4039
+ if ((_a = skill.description) == null ? void 0 : _a.toLowerCase().includes(query)) return true;
4040
+ if ((_b = skill.capabilities) == null ? void 0 : _b.some((cap2) => cap2.toLowerCase().includes(query)))
4077
4041
  return true;
4078
4042
  if (skill.path.toLowerCase().includes(query)) return true;
4079
4043
  return false;
@@ -4087,7 +4051,7 @@ const SkillsBrowsePanel = ({
4087
4051
  events.emit({
4088
4052
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4089
4053
  type: "skill:selected",
4090
- source: "skills-browse-panel",
4054
+ source: "global-skills-panel",
4091
4055
  timestamp: Date.now(),
4092
4056
  payload: { skillId: skill.id, skill }
4093
4057
  });
@@ -4099,7 +4063,7 @@ const SkillsBrowsePanel = ({
4099
4063
  events.emit({
4100
4064
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4101
4065
  type: "skills:refresh",
4102
- source: "skills-browse-panel",
4066
+ source: "global-skills-panel",
4103
4067
  timestamp: Date.now(),
4104
4068
  payload: {}
4105
4069
  });
@@ -4140,50 +4104,7 @@ const SkillsBrowsePanel = ({
4140
4104
  },
4141
4105
  children: [
4142
4106
  /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
4143
- owner && repo ? /* @__PURE__ */ jsxs(
4144
- "a",
4145
- {
4146
- href: `https://github.com/${owner}/${repo}`,
4147
- target: "_blank",
4148
- rel: "noopener noreferrer",
4149
- style: {
4150
- textDecoration: "none",
4151
- display: "flex",
4152
- flexDirection: "column",
4153
- gap: "2px"
4154
- },
4155
- children: [
4156
- /* @__PURE__ */ jsx(
4157
- "h2",
4158
- {
4159
- style: {
4160
- margin: 0,
4161
- fontSize: theme2.fontSizes[4],
4162
- color: theme2.colors.text,
4163
- fontFamily: theme2.fonts.monospace,
4164
- lineHeight: 1.2
4165
- },
4166
- onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
4167
- onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
4168
- children: String(repo || "")
4169
- }
4170
- ),
4171
- /* @__PURE__ */ jsx(
4172
- "div",
4173
- {
4174
- style: {
4175
- fontSize: theme2.fontSizes[1],
4176
- color: theme2.colors.textSecondary,
4177
- fontFamily: theme2.fonts.monospace
4178
- },
4179
- onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
4180
- onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
4181
- children: String(owner || "")
4182
- }
4183
- )
4184
- ]
4185
- }
4186
- ) : /* @__PURE__ */ jsx(
4107
+ /* @__PURE__ */ jsx(
4187
4108
  "h2",
4188
4109
  {
4189
4110
  style: {
@@ -4203,7 +4124,7 @@ const SkillsBrowsePanel = ({
4203
4124
  },
4204
4125
  onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
4205
4126
  onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
4206
- children: "Browse Skills"
4127
+ children: "Global Skills"
4207
4128
  }
4208
4129
  )
4209
4130
  }
@@ -4254,7 +4175,7 @@ const SkillsBrowsePanel = ({
4254
4175
  "input",
4255
4176
  {
4256
4177
  type: "text",
4257
- placeholder: "Search skills...",
4178
+ placeholder: "Search global skills...",
4258
4179
  value: searchQuery,
4259
4180
  onChange: (e) => setSearchQuery(e.target.value),
4260
4181
  style: {
@@ -4369,7 +4290,7 @@ const SkillsBrowsePanel = ({
4369
4290
  color: theme2.colors.textSecondary,
4370
4291
  fontSize: theme2.fontSizes[2]
4371
4292
  },
4372
- children: "Loading skills from repository..."
4293
+ children: "Loading global skills..."
4373
4294
  }
4374
4295
  ) : filteredSkills.length === 0 ? /* @__PURE__ */ jsxs(
4375
4296
  "div",
@@ -4387,8 +4308,8 @@ const SkillsBrowsePanel = ({
4387
4308
  children: [
4388
4309
  /* @__PURE__ */ jsx(FileCode, { size: 48, color: theme2.colors.border }),
4389
4310
  /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
4390
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: theme2.fontSizes[2] }, children: searchQuery ? "No skills match your search" : "No skills found in this repository" }),
4391
- /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: theme2.fontSizes[1] }, children: searchQuery ? "Try a different search term" : "This repository does not contain any SKILL.md files" })
4311
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: theme2.fontSizes[2] }, children: searchQuery ? "No global skills match your search" : "No global skills found" }),
4312
+ /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: theme2.fontSizes[1] }, children: searchQuery ? "Try a different search term" : "Install skills from repositories to see them here" })
4392
4313
  ] })
4393
4314
  ]
4394
4315
  }
@@ -4407,7 +4328,7 @@ const SkillsBrowsePanel = ({
4407
4328
  skill,
4408
4329
  onClick: handleSkillClick,
4409
4330
  isSelected: selectedSkillId === skill.id,
4410
- isInstalled: installedSkillNames.has(skill.name)
4331
+ filterContext: "global"
4411
4332
  },
4412
4333
  skill.id
4413
4334
  ))
@@ -4424,553 +4345,203 @@ const SkillsBrowsePanel = ({
4424
4345
  }
4425
4346
  );
4426
4347
  };
4427
- const GlobalSkillsPanel = ({
4428
- context,
4429
- events,
4430
- supportsRefresh = false
4431
- }) => {
4432
- const { theme: theme2 } = useTheme();
4433
- const panelRef = useRef(null);
4434
- const [selectedSkillId, setSelectedSkillId] = useState(null);
4435
- const [searchQuery, setSearchQuery] = useState("");
4436
- const [isRefreshing, setIsRefreshing] = useState(false);
4437
- const { skills, isLoading, error, refreshSkills } = useSkillsData({ context });
4438
- gt("global-skills", events, () => {
4439
- var _a;
4440
- return (_a = panelRef.current) == null ? void 0 : _a.focus();
4441
- });
4442
- useEffect(() => {
4443
- const unsubscribeInstalled = events.on("skill:installed", () => {
4444
- refreshSkills();
4445
- });
4446
- const unsubscribeUninstalled = events.on("skill:uninstalled", () => {
4447
- refreshSkills();
4448
- });
4449
- return () => {
4450
- unsubscribeInstalled();
4451
- unsubscribeUninstalled();
4452
- };
4453
- }, [events, refreshSkills]);
4454
- const filteredSkills = useMemo(() => {
4455
- let filtered = skills.filter((skill) => {
4456
- if (skill.installedLocations && skill.installedLocations.length > 0) {
4457
- return skill.installedLocations.some(
4458
- (loc) => loc.source === "global-universal" || loc.source === "global-claude"
4459
- );
4348
+ var MarkdownSourceType$1;
4349
+ ((MarkdownSourceType2) => {
4350
+ MarkdownSourceType2["WORKSPACE_FILE"] = "workspace_file";
4351
+ MarkdownSourceType2["REMOTE_FILE"] = "remote_file";
4352
+ MarkdownSourceType2["GITHUB_FILE"] = "github_file";
4353
+ MarkdownSourceType2["DRAFT"] = "draft";
4354
+ MarkdownSourceType2["GITHUB_ISSUE"] = "github_issue";
4355
+ MarkdownSourceType2["GITHUB_PULL_REQUEST"] = "github_pull_request";
4356
+ MarkdownSourceType2["GITHUB_GIST"] = "github_gist";
4357
+ })(MarkdownSourceType$1 || (MarkdownSourceType$1 = {}));
4358
+ class SkillParseError extends Error {
4359
+ constructor(message, cause) {
4360
+ super(message);
4361
+ __publicField(this, "cause");
4362
+ this.cause = cause;
4363
+ this.name = "SkillParseError";
4364
+ }
4365
+ }
4366
+ function extractFrontmatter(content2) {
4367
+ const trimmed = content2.trim();
4368
+ if (!trimmed.startsWith("---")) {
4369
+ throw new SkillParseError("SKILL.md must start with YAML frontmatter (---)");
4370
+ }
4371
+ const afterFirstDelimiter = trimmed.slice(3);
4372
+ const closingIndex = afterFirstDelimiter.indexOf(`
4373
+ ---`);
4374
+ if (closingIndex === -1) {
4375
+ throw new SkillParseError("SKILL.md frontmatter is not properly closed with ---");
4376
+ }
4377
+ const frontmatter = afterFirstDelimiter.slice(0, closingIndex).trim();
4378
+ const body = afterFirstDelimiter.slice(closingIndex + 4).trim();
4379
+ return { frontmatter, body };
4380
+ }
4381
+ function parseYamlFrontmatter(yaml2) {
4382
+ const result = {};
4383
+ const lines = yaml2.split(`
4384
+ `);
4385
+ let currentObject = null;
4386
+ let currentList = null;
4387
+ for (let i = 0; i < lines.length; i++) {
4388
+ const line = lines[i];
4389
+ const trimmed = line.trim();
4390
+ if (!trimmed || trimmed.startsWith("#")) {
4391
+ continue;
4392
+ }
4393
+ const lineIndent = line.search(/\S/);
4394
+ if (trimmed.startsWith("- ")) {
4395
+ const value = trimmed.slice(2).trim();
4396
+ if (currentList) {
4397
+ currentList.push(value);
4460
4398
  }
4461
- return skill.source === "global-universal" || skill.source === "global-claude";
4399
+ continue;
4400
+ }
4401
+ const colonIndex = line.indexOf(":");
4402
+ if (colonIndex > 0) {
4403
+ const key = line.slice(0, colonIndex).trim();
4404
+ const value = line.slice(colonIndex + 1).trim();
4405
+ if (lineIndent === 0) {
4406
+ currentList = null;
4407
+ currentObject = null;
4408
+ if (!value) {
4409
+ if (i + 1 < lines.length) {
4410
+ const nextLine = lines[i + 1];
4411
+ const nextTrimmed = nextLine.trim();
4412
+ if (nextTrimmed.startsWith("- ")) {
4413
+ currentList = [];
4414
+ result[key] = currentList;
4415
+ } else if (nextLine.search(/\S/) > 0 && nextLine.includes(":")) {
4416
+ currentObject = {};
4417
+ result[key] = currentObject;
4418
+ }
4419
+ }
4420
+ } else {
4421
+ const cleanValue = value.replace(/^["']|["']$/g, "");
4422
+ result[key] = cleanValue;
4423
+ }
4424
+ } else if (lineIndent > 0 && currentObject) {
4425
+ const cleanValue = value.replace(/^["']|["']$/g, "");
4426
+ currentObject[key] = cleanValue;
4427
+ }
4428
+ }
4429
+ }
4430
+ return result;
4431
+ }
4432
+ function parseSkillMetadataGraceful(metadata) {
4433
+ const warnings = [];
4434
+ const partialMetadata = {};
4435
+ if (!metadata.name || typeof metadata.name !== "string" || !metadata.name.trim()) {
4436
+ warnings.push({
4437
+ field: "name",
4438
+ message: 'Required field "name" is missing or empty'
4462
4439
  });
4463
- if (searchQuery.trim()) {
4464
- const query = searchQuery.toLowerCase().trim();
4465
- filtered = filtered.filter((skill) => {
4466
- var _a, _b;
4467
- if (skill.name.toLowerCase().includes(query)) return true;
4468
- if ((_a = skill.description) == null ? void 0 : _a.toLowerCase().includes(query)) return true;
4469
- if ((_b = skill.capabilities) == null ? void 0 : _b.some((cap2) => cap2.toLowerCase().includes(query)))
4470
- return true;
4471
- if (skill.path.toLowerCase().includes(query)) return true;
4472
- return false;
4440
+ } else {
4441
+ partialMetadata.name = metadata.name;
4442
+ }
4443
+ if (!metadata.description || typeof metadata.description !== "string" || !metadata.description.trim()) {
4444
+ warnings.push({
4445
+ field: "description",
4446
+ message: 'Required field "description" is missing or empty'
4447
+ });
4448
+ } else {
4449
+ partialMetadata.description = metadata.description;
4450
+ }
4451
+ if (metadata.license !== void 0) {
4452
+ if (typeof metadata.license !== "string") {
4453
+ warnings.push({
4454
+ field: "license",
4455
+ message: 'Field "license" must be a string'
4473
4456
  });
4457
+ } else {
4458
+ partialMetadata.license = metadata.license;
4474
4459
  }
4475
- return filtered;
4476
- }, [skills, searchQuery]);
4477
- const handleSkillClick = (skill) => {
4478
- setSelectedSkillId(skill.id);
4479
- if (events) {
4480
- events.emit({
4481
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4482
- type: "skill:selected",
4483
- source: "global-skills-panel",
4484
- timestamp: Date.now(),
4485
- payload: { skillId: skill.id, skill }
4460
+ }
4461
+ if (metadata.compatibility !== void 0) {
4462
+ if (typeof metadata.compatibility !== "string") {
4463
+ warnings.push({
4464
+ field: "compatibility",
4465
+ message: 'Field "compatibility" must be a string'
4486
4466
  });
4467
+ } else {
4468
+ partialMetadata.compatibility = metadata.compatibility;
4487
4469
  }
4488
- };
4489
- const handleRefresh = () => {
4490
- setIsRefreshing(true);
4491
- if (events) {
4492
- events.emit({
4493
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4494
- type: "skills:refresh",
4495
- source: "global-skills-panel",
4496
- timestamp: Date.now(),
4497
- payload: {}
4470
+ }
4471
+ if (metadata["allowed-tools"] !== void 0) {
4472
+ if (typeof metadata["allowed-tools"] === "string") {
4473
+ const toolsString = metadata["allowed-tools"];
4474
+ partialMetadata["allowed-tools"] = toolsString.trim() ? toolsString.trim().split(/\s+/) : [];
4475
+ } else {
4476
+ warnings.push({
4477
+ field: "allowed-tools",
4478
+ message: 'Field "allowed-tools" must be a space-delimited string'
4498
4479
  });
4499
4480
  }
4500
- setTimeout(() => {
4501
- setIsRefreshing(false);
4502
- }, 800);
4503
- };
4504
- return /* @__PURE__ */ jsxs(
4505
- "div",
4506
- {
4507
- ref: panelRef,
4508
- tabIndex: -1,
4509
- style: {
4510
- padding: "clamp(12px, 3vw, 20px)",
4511
- fontFamily: theme2.fonts.body,
4512
- height: "100%",
4513
- boxSizing: "border-box",
4514
- display: "flex",
4515
- flexDirection: "column",
4516
- gap: "16px",
4517
- overflow: "hidden",
4518
- backgroundColor: theme2.colors.background,
4519
- color: theme2.colors.text,
4520
- outline: "none"
4521
- },
4522
- children: [
4523
- /* @__PURE__ */ jsxs(
4524
- "div",
4525
- {
4526
- style: {
4527
- flexShrink: 0,
4528
- display: "flex",
4529
- alignItems: "center",
4530
- justifyContent: "space-between",
4531
- gap: "12px",
4532
- flexWrap: "wrap"
4533
- },
4534
- children: [
4535
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
4536
- /* @__PURE__ */ jsx(
4537
- "h2",
4538
- {
4539
- style: {
4540
- margin: 0,
4541
- fontSize: theme2.fontSizes[4],
4542
- color: theme2.colors.text
4543
- },
4544
- children: /* @__PURE__ */ jsx(
4545
- "a",
4546
- {
4547
- href: "https://agentskills.io/",
4548
- target: "_blank",
4549
- rel: "noopener noreferrer",
4550
- style: {
4551
- color: "inherit",
4552
- textDecoration: "none"
4553
- },
4554
- onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
4555
- onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
4556
- children: "Global Skills"
4557
- }
4558
- )
4559
- }
4560
- ),
4561
- !isLoading && /* @__PURE__ */ jsxs(
4562
- "span",
4563
- {
4564
- style: {
4565
- fontSize: theme2.fontSizes[1],
4566
- color: theme2.colors.textSecondary,
4567
- background: theme2.colors.backgroundSecondary,
4568
- padding: "4px 10px",
4569
- borderRadius: theme2.radii[1]
4570
- },
4571
- children: [
4572
- filteredSkills.length,
4573
- " ",
4574
- filteredSkills.length === 1 ? "skill" : "skills"
4575
- ]
4576
- }
4577
- )
4578
- ] }),
4579
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px", flex: "1 1 200px", maxWidth: "400px" }, children: [
4580
- /* @__PURE__ */ jsxs(
4581
- "div",
4582
- {
4583
- style: {
4584
- position: "relative",
4585
- flex: 1,
4586
- minWidth: "150px"
4587
- },
4588
- children: [
4589
- /* @__PURE__ */ jsx(
4590
- Search,
4591
- {
4592
- size: 16,
4593
- color: theme2.colors.textSecondary,
4594
- style: {
4595
- position: "absolute",
4596
- left: "10px",
4597
- top: "50%",
4598
- transform: "translateY(-50%)",
4599
- pointerEvents: "none"
4600
- }
4601
- }
4602
- ),
4603
- /* @__PURE__ */ jsx(
4604
- "input",
4605
- {
4606
- type: "text",
4607
- placeholder: "Search global skills...",
4608
- value: searchQuery,
4609
- onChange: (e) => setSearchQuery(e.target.value),
4610
- style: {
4611
- width: "100%",
4612
- padding: "8px 32px 8px 32px",
4613
- fontSize: theme2.fontSizes[1],
4614
- fontFamily: theme2.fonts.body,
4615
- border: `1px solid ${theme2.colors.border}`,
4616
- borderRadius: theme2.radii[2],
4617
- background: theme2.colors.backgroundSecondary,
4618
- color: theme2.colors.text,
4619
- outline: "none",
4620
- boxSizing: "border-box"
4621
- }
4622
- }
4623
- ),
4624
- searchQuery && /* @__PURE__ */ jsx(
4625
- "button",
4626
- {
4627
- onClick: () => setSearchQuery(""),
4628
- style: {
4629
- position: "absolute",
4630
- right: "6px",
4631
- top: "50%",
4632
- transform: "translateY(-50%)",
4633
- background: "transparent",
4634
- border: "none",
4635
- padding: "4px",
4636
- cursor: "pointer",
4637
- display: "flex",
4638
- alignItems: "center",
4639
- justifyContent: "center",
4640
- color: theme2.colors.textSecondary
4641
- },
4642
- "aria-label": "Clear search",
4643
- children: /* @__PURE__ */ jsx(X, { size: 14 })
4644
- }
4645
- )
4646
- ]
4647
- }
4648
- ),
4649
- supportsRefresh && /* @__PURE__ */ jsx(
4650
- "button",
4651
- {
4652
- onClick: handleRefresh,
4653
- disabled: isRefreshing || isLoading,
4654
- style: {
4655
- background: theme2.colors.backgroundSecondary,
4656
- border: `1px solid ${theme2.colors.border}`,
4657
- borderRadius: theme2.radii[1],
4658
- padding: "8px",
4659
- cursor: isRefreshing || isLoading ? "default" : "pointer",
4660
- display: "flex",
4661
- alignItems: "center",
4662
- justifyContent: "center",
4663
- transition: "all 0.2s ease"
4664
- },
4665
- title: "Refresh skills",
4666
- children: /* @__PURE__ */ jsx(
4667
- RefreshCw,
4668
- {
4669
- size: 16,
4670
- color: theme2.colors.textSecondary,
4671
- style: {
4672
- animation: isRefreshing ? "spin 1s linear infinite" : "none"
4673
- }
4674
- }
4675
- )
4676
- }
4677
- )
4678
- ] })
4679
- ]
4680
- }
4681
- ),
4682
- error && /* @__PURE__ */ jsxs(
4683
- "div",
4684
- {
4685
- style: {
4686
- flexShrink: 0,
4687
- padding: "12px",
4688
- background: `${theme2.colors.error}20`,
4689
- border: `1px solid ${theme2.colors.error}`,
4690
- borderRadius: theme2.radii[2],
4691
- display: "flex",
4692
- alignItems: "center",
4693
- gap: "8px",
4694
- color: theme2.colors.error,
4695
- fontSize: theme2.fontSizes[1]
4696
- },
4697
- children: [
4698
- /* @__PURE__ */ jsx(CircleAlert, { size: 16 }),
4699
- /* @__PURE__ */ jsx("span", { children: error })
4700
- ]
4701
- }
4702
- ),
4703
- /* @__PURE__ */ jsx(
4704
- "div",
4705
- {
4706
- style: {
4707
- flex: 1,
4708
- overflowY: "auto",
4709
- minHeight: 0
4710
- },
4711
- children: isLoading ? /* @__PURE__ */ jsx(
4712
- "div",
4713
- {
4714
- style: {
4715
- height: "100%",
4716
- display: "flex",
4717
- alignItems: "center",
4718
- justifyContent: "center",
4719
- color: theme2.colors.textSecondary,
4720
- fontSize: theme2.fontSizes[2]
4721
- },
4722
- children: "Loading global skills..."
4723
- }
4724
- ) : filteredSkills.length === 0 ? /* @__PURE__ */ jsxs(
4725
- "div",
4726
- {
4727
- style: {
4728
- height: "100%",
4729
- display: "flex",
4730
- flexDirection: "column",
4731
- alignItems: "center",
4732
- justifyContent: "center",
4733
- gap: "16px",
4734
- color: theme2.colors.textSecondary,
4735
- padding: "24px"
4736
- },
4737
- children: [
4738
- /* @__PURE__ */ jsx(FileCode, { size: 48, color: theme2.colors.border }),
4739
- /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
4740
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: theme2.fontSizes[2] }, children: searchQuery ? "No global skills match your search" : "No global skills found" }),
4741
- /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: theme2.fontSizes[1] }, children: searchQuery ? "Try a different search term" : "Install skills from repositories to see them here" })
4742
- ] })
4743
- ]
4744
- }
4745
- ) : /* @__PURE__ */ jsx(
4746
- "div",
4747
- {
4748
- style: {
4749
- display: "grid",
4750
- gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))",
4751
- gap: "16px",
4752
- padding: "4px"
4753
- },
4754
- children: filteredSkills.map((skill) => /* @__PURE__ */ jsx(
4755
- SkillCard,
4756
- {
4757
- skill,
4758
- onClick: handleSkillClick,
4759
- isSelected: selectedSkillId === skill.id,
4760
- filterContext: "global"
4761
- },
4762
- skill.id
4763
- ))
4764
- }
4765
- )
4766
- }
4767
- ),
4768
- /* @__PURE__ */ jsx("style", { children: `
4769
- @keyframes spin {
4770
- to { transform: rotate(360deg); }
4771
- }
4772
- ` })
4773
- ]
4774
- }
4775
- );
4776
- };
4777
- var MarkdownSourceType$1;
4778
- ((MarkdownSourceType2) => {
4779
- MarkdownSourceType2["WORKSPACE_FILE"] = "workspace_file";
4780
- MarkdownSourceType2["REMOTE_FILE"] = "remote_file";
4781
- MarkdownSourceType2["GITHUB_FILE"] = "github_file";
4782
- MarkdownSourceType2["DRAFT"] = "draft";
4783
- MarkdownSourceType2["GITHUB_ISSUE"] = "github_issue";
4784
- MarkdownSourceType2["GITHUB_PULL_REQUEST"] = "github_pull_request";
4785
- MarkdownSourceType2["GITHUB_GIST"] = "github_gist";
4786
- })(MarkdownSourceType$1 || (MarkdownSourceType$1 = {}));
4787
- class SkillParseError extends Error {
4788
- constructor(message, cause) {
4789
- super(message);
4790
- __publicField(this, "cause");
4791
- this.cause = cause;
4792
- this.name = "SkillParseError";
4793
- }
4794
- }
4795
- function extractFrontmatter(content2) {
4796
- const trimmed = content2.trim();
4797
- if (!trimmed.startsWith("---")) {
4798
- throw new SkillParseError("SKILL.md must start with YAML frontmatter (---)");
4799
- }
4800
- const afterFirstDelimiter = trimmed.slice(3);
4801
- const closingIndex = afterFirstDelimiter.indexOf(`
4802
- ---`);
4803
- if (closingIndex === -1) {
4804
- throw new SkillParseError("SKILL.md frontmatter is not properly closed with ---");
4805
- }
4806
- const frontmatter = afterFirstDelimiter.slice(0, closingIndex).trim();
4807
- const body = afterFirstDelimiter.slice(closingIndex + 4).trim();
4808
- return { frontmatter, body };
4809
- }
4810
- function parseYamlFrontmatter(yaml2) {
4811
- const result = {};
4812
- const lines = yaml2.split(`
4813
- `);
4814
- let currentObject = null;
4815
- let currentList = null;
4816
- for (let i = 0; i < lines.length; i++) {
4817
- const line = lines[i];
4818
- const trimmed = line.trim();
4819
- if (!trimmed || trimmed.startsWith("#")) {
4820
- continue;
4821
- }
4822
- const lineIndent = line.search(/\S/);
4823
- if (trimmed.startsWith("- ")) {
4824
- const value = trimmed.slice(2).trim();
4825
- if (currentList) {
4826
- currentList.push(value);
4827
- }
4828
- continue;
4829
- }
4830
- const colonIndex = line.indexOf(":");
4831
- if (colonIndex > 0) {
4832
- const key = line.slice(0, colonIndex).trim();
4833
- const value = line.slice(colonIndex + 1).trim();
4834
- if (lineIndent === 0) {
4835
- currentList = null;
4836
- currentObject = null;
4837
- if (!value) {
4838
- if (i + 1 < lines.length) {
4839
- const nextLine = lines[i + 1];
4840
- const nextTrimmed = nextLine.trim();
4841
- if (nextTrimmed.startsWith("- ")) {
4842
- currentList = [];
4843
- result[key] = currentList;
4844
- } else if (nextLine.search(/\S/) > 0 && nextLine.includes(":")) {
4845
- currentObject = {};
4846
- result[key] = currentObject;
4847
- }
4848
- }
4849
- } else {
4850
- const cleanValue = value.replace(/^["']|["']$/g, "");
4851
- result[key] = cleanValue;
4852
- }
4853
- } else if (lineIndent > 0 && currentObject) {
4854
- const cleanValue = value.replace(/^["']|["']$/g, "");
4855
- currentObject[key] = cleanValue;
4856
- }
4857
- }
4858
- }
4859
- return result;
4860
- }
4861
- function parseSkillMetadataGraceful(metadata) {
4862
- const warnings = [];
4863
- const partialMetadata = {};
4864
- if (!metadata.name || typeof metadata.name !== "string" || !metadata.name.trim()) {
4865
- warnings.push({
4866
- field: "name",
4867
- message: 'Required field "name" is missing or empty'
4868
- });
4869
- } else {
4870
- partialMetadata.name = metadata.name;
4871
- }
4872
- if (!metadata.description || typeof metadata.description !== "string" || !metadata.description.trim()) {
4873
- warnings.push({
4874
- field: "description",
4875
- message: 'Required field "description" is missing or empty'
4876
- });
4877
- } else {
4878
- partialMetadata.description = metadata.description;
4879
- }
4880
- if (metadata.license !== void 0) {
4881
- if (typeof metadata.license !== "string") {
4882
- warnings.push({
4883
- field: "license",
4884
- message: 'Field "license" must be a string'
4885
- });
4886
- } else {
4887
- partialMetadata.license = metadata.license;
4888
- }
4889
- }
4890
- if (metadata.compatibility !== void 0) {
4891
- if (typeof metadata.compatibility !== "string") {
4892
- warnings.push({
4893
- field: "compatibility",
4894
- message: 'Field "compatibility" must be a string'
4895
- });
4896
- } else {
4897
- partialMetadata.compatibility = metadata.compatibility;
4898
- }
4899
- }
4900
- if (metadata["allowed-tools"] !== void 0) {
4901
- if (typeof metadata["allowed-tools"] === "string") {
4902
- const toolsString = metadata["allowed-tools"];
4903
- partialMetadata["allowed-tools"] = toolsString.trim() ? toolsString.trim().split(/\s+/) : [];
4904
- } else {
4905
- warnings.push({
4906
- field: "allowed-tools",
4907
- message: 'Field "allowed-tools" must be a space-delimited string'
4908
- });
4909
- }
4910
- }
4911
- if (metadata.metadata !== void 0) {
4912
- if (typeof metadata.metadata !== "object" || Array.isArray(metadata.metadata)) {
4913
- warnings.push({
4914
- field: "metadata",
4915
- message: 'Field "metadata" must be an object'
4916
- });
4917
- } else {
4918
- partialMetadata.metadata = metadata.metadata;
4919
- }
4920
- }
4921
- return { metadata: partialMetadata, warnings };
4922
- }
4923
- function parseSkillMarkdownGraceful(content2) {
4924
- try {
4925
- const { frontmatter, body } = extractFrontmatter(content2);
4926
- let rawMetadata;
4927
- try {
4928
- rawMetadata = parseYamlFrontmatter(frontmatter);
4929
- } catch (error) {
4930
- return {
4931
- metadata: {},
4932
- body,
4933
- raw: content2,
4934
- warnings: [{
4935
- field: "frontmatter",
4936
- message: `Failed to parse YAML frontmatter: ${error instanceof Error ? error.message : String(error)}`
4937
- }]
4938
- };
4939
- }
4940
- const { metadata, warnings } = parseSkillMetadataGraceful(rawMetadata);
4941
- return {
4942
- metadata,
4943
- body,
4944
- raw: content2,
4945
- warnings
4946
- };
4947
- } catch (error) {
4948
- return {
4949
- metadata: {},
4950
- body: content2,
4951
- raw: content2,
4952
- warnings: [{
4953
- field: "structure",
4954
- message: error instanceof Error ? error.message : "Failed to parse SKILL.md structure"
4955
- }]
4956
- };
4957
- }
4958
- }
4959
- const VOID = -1;
4960
- const PRIMITIVE = 0;
4961
- const ARRAY = 1;
4962
- const OBJECT = 2;
4963
- const DATE = 3;
4964
- const REGEXP = 4;
4965
- const MAP = 5;
4966
- const SET = 6;
4967
- const ERROR = 7;
4968
- const BIGINT = 8;
4969
- const env = typeof self === "object" ? self : globalThis;
4970
- const deserializer = ($2, _) => {
4971
- const as = (out, index2) => {
4972
- $2.set(index2, out);
4973
- return out;
4481
+ }
4482
+ if (metadata.metadata !== void 0) {
4483
+ if (typeof metadata.metadata !== "object" || Array.isArray(metadata.metadata)) {
4484
+ warnings.push({
4485
+ field: "metadata",
4486
+ message: 'Field "metadata" must be an object'
4487
+ });
4488
+ } else {
4489
+ partialMetadata.metadata = metadata.metadata;
4490
+ }
4491
+ }
4492
+ return { metadata: partialMetadata, warnings };
4493
+ }
4494
+ function parseSkillMarkdownGraceful(content2) {
4495
+ try {
4496
+ const { frontmatter, body } = extractFrontmatter(content2);
4497
+ let rawMetadata;
4498
+ try {
4499
+ rawMetadata = parseYamlFrontmatter(frontmatter);
4500
+ } catch (error) {
4501
+ return {
4502
+ metadata: {},
4503
+ body,
4504
+ raw: content2,
4505
+ warnings: [{
4506
+ field: "frontmatter",
4507
+ message: `Failed to parse YAML frontmatter: ${error instanceof Error ? error.message : String(error)}`
4508
+ }]
4509
+ };
4510
+ }
4511
+ const { metadata, warnings } = parseSkillMetadataGraceful(rawMetadata);
4512
+ return {
4513
+ metadata,
4514
+ body,
4515
+ raw: content2,
4516
+ warnings
4517
+ };
4518
+ } catch (error) {
4519
+ return {
4520
+ metadata: {},
4521
+ body: content2,
4522
+ raw: content2,
4523
+ warnings: [{
4524
+ field: "structure",
4525
+ message: error instanceof Error ? error.message : "Failed to parse SKILL.md structure"
4526
+ }]
4527
+ };
4528
+ }
4529
+ }
4530
+ const VOID = -1;
4531
+ const PRIMITIVE = 0;
4532
+ const ARRAY = 1;
4533
+ const OBJECT = 2;
4534
+ const DATE = 3;
4535
+ const REGEXP = 4;
4536
+ const MAP = 5;
4537
+ const SET = 6;
4538
+ const ERROR = 7;
4539
+ const BIGINT = 8;
4540
+ const env = typeof self === "object" ? self : globalThis;
4541
+ const deserializer = ($2, _) => {
4542
+ const as = (out, index2) => {
4543
+ $2.set(index2, out);
4544
+ return out;
4974
4545
  };
4975
4546
  const unpair = (index2) => {
4976
4547
  if ($2.has(index2))
@@ -50846,887 +50417,6 @@ const useSubagentsData = ({
50846
50417
  refreshSubagents
50847
50418
  };
50848
50419
  };
50849
- const getSourceBadge$1 = (source2) => {
50850
- switch (source2) {
50851
- case "project-root":
50852
- return {
50853
- label: "Root",
50854
- icon: /* @__PURE__ */ jsx(FileText, { size: 12 }),
50855
- color: "#10b981",
50856
- bgColor: "#10b98120"
50857
- };
50858
- case "project-nested":
50859
- return {
50860
- label: "Nested",
50861
- icon: /* @__PURE__ */ jsx(FolderTree, { size: 12 }),
50862
- color: "#3b82f6",
50863
- bgColor: "#3b82f620"
50864
- };
50865
- case "global-universal":
50866
- return {
50867
- label: "Global",
50868
- icon: /* @__PURE__ */ jsx(Folder, { size: 12 }),
50869
- color: "#8b5cf6",
50870
- bgColor: "#8b5cf620"
50871
- };
50872
- }
50873
- };
50874
- const AgentCard = ({ agent, onClick, isSelected }) => {
50875
- var _a;
50876
- const { theme: theme2 } = useTheme();
50877
- const sourceBadge = getSourceBadge$1(agent.source);
50878
- const [pathCopied, setPathCopied] = React2__default.useState(false);
50879
- const preview = ((_a = agent.content.split("\n").find((line) => line.trim() && !line.startsWith("#"))) == null ? void 0 : _a.substring(0, 150)) || "No description available";
50880
- const handleCopyPath = async (e) => {
50881
- e.stopPropagation();
50882
- try {
50883
- await navigator.clipboard.writeText(agent.path);
50884
- setPathCopied(true);
50885
- setTimeout(() => setPathCopied(false), 2e3);
50886
- } catch (err) {
50887
- console.error("Failed to copy path:", err);
50888
- }
50889
- };
50890
- return /* @__PURE__ */ jsxs(
50891
- "div",
50892
- {
50893
- onClick: () => onClick(agent),
50894
- style: {
50895
- padding: "16px",
50896
- background: isSelected ? `${theme2.colors.primary}10` : theme2.colors.backgroundSecondary,
50897
- border: `1px solid ${isSelected ? theme2.colors.primary : theme2.colors.border}`,
50898
- borderRadius: theme2.radii[2],
50899
- cursor: "pointer",
50900
- transition: "all 0.2s ease",
50901
- display: "flex",
50902
- flexDirection: "column",
50903
- gap: "12px"
50904
- },
50905
- onMouseEnter: (e) => {
50906
- if (!isSelected) {
50907
- e.currentTarget.style.borderColor = theme2.colors.textSecondary;
50908
- }
50909
- },
50910
- onMouseLeave: (e) => {
50911
- if (!isSelected) {
50912
- e.currentTarget.style.borderColor = theme2.colors.border;
50913
- }
50914
- },
50915
- children: [
50916
- /* @__PURE__ */ jsxs(
50917
- "div",
50918
- {
50919
- style: {
50920
- display: "flex",
50921
- alignItems: "flex-start",
50922
- justifyContent: "space-between",
50923
- gap: "8px"
50924
- },
50925
- children: [
50926
- /* @__PURE__ */ jsx(
50927
- "h3",
50928
- {
50929
- style: {
50930
- margin: 0,
50931
- fontSize: theme2.fontSizes[2],
50932
- color: theme2.colors.text,
50933
- fontWeight: 600,
50934
- flex: 1
50935
- },
50936
- children: agent.name
50937
- }
50938
- ),
50939
- /* @__PURE__ */ jsxs(
50940
- "div",
50941
- {
50942
- style: {
50943
- display: "flex",
50944
- alignItems: "center",
50945
- gap: "4px",
50946
- padding: "4px 8px",
50947
- fontSize: theme2.fontSizes[0],
50948
- color: sourceBadge.color,
50949
- background: sourceBadge.bgColor,
50950
- border: `1px solid ${sourceBadge.color}40`,
50951
- borderRadius: theme2.radii[1],
50952
- flexShrink: 0
50953
- },
50954
- children: [
50955
- sourceBadge.icon,
50956
- /* @__PURE__ */ jsx("span", { children: sourceBadge.label })
50957
- ]
50958
- }
50959
- )
50960
- ]
50961
- }
50962
- ),
50963
- /* @__PURE__ */ jsx(
50964
- "div",
50965
- {
50966
- onClick: handleCopyPath,
50967
- style: {
50968
- fontSize: theme2.fontSizes[0],
50969
- color: pathCopied ? theme2.colors.success : theme2.colors.textMuted,
50970
- fontFamily: theme2.fonts.monospace,
50971
- background: pathCopied ? `${theme2.colors.success}15` : theme2.colors.background,
50972
- padding: "4px 8px",
50973
- borderRadius: theme2.radii[1],
50974
- overflow: "hidden",
50975
- textOverflow: "ellipsis",
50976
- whiteSpace: "nowrap",
50977
- cursor: "pointer",
50978
- transition: "all 0.2s ease",
50979
- border: `1px solid ${pathCopied ? theme2.colors.success : "transparent"}`
50980
- },
50981
- title: pathCopied ? "Copied!" : `Click to copy: ${agent.path}`,
50982
- onMouseEnter: (e) => {
50983
- if (!pathCopied) {
50984
- e.currentTarget.style.background = theme2.colors.backgroundTertiary || theme2.colors.border;
50985
- }
50986
- },
50987
- onMouseLeave: (e) => {
50988
- if (!pathCopied) {
50989
- e.currentTarget.style.background = theme2.colors.background;
50990
- }
50991
- },
50992
- children: pathCopied ? "Copied!" : agent.path
50993
- }
50994
- ),
50995
- /* @__PURE__ */ jsx(
50996
- "div",
50997
- {
50998
- style: {
50999
- fontSize: theme2.fontSizes[1],
51000
- color: theme2.colors.textSecondary,
51001
- lineHeight: 1.5,
51002
- overflow: "hidden",
51003
- textOverflow: "ellipsis",
51004
- display: "-webkit-box",
51005
- WebkitLineClamp: 3,
51006
- WebkitBoxOrient: "vertical"
51007
- },
51008
- children: preview
51009
- }
51010
- ),
51011
- agent.sections && Object.keys(agent.sections).length > 0 && /* @__PURE__ */ jsx(
51012
- "div",
51013
- {
51014
- style: {
51015
- display: "flex",
51016
- flexWrap: "wrap",
51017
- gap: "6px",
51018
- marginTop: "4px"
51019
- },
51020
- children: Object.keys(agent.sections).map((section) => /* @__PURE__ */ jsx(
51021
- "span",
51022
- {
51023
- style: {
51024
- fontSize: theme2.fontSizes[0],
51025
- padding: "2px 8px",
51026
- background: theme2.colors.background,
51027
- border: `1px solid ${theme2.colors.border}`,
51028
- borderRadius: theme2.radii[1],
51029
- color: theme2.colors.textSecondary,
51030
- textTransform: "capitalize"
51031
- },
51032
- children: section
51033
- },
51034
- section
51035
- ))
51036
- }
51037
- )
51038
- ]
51039
- }
51040
- );
51041
- };
51042
- const getSourceBadge = (source2) => {
51043
- switch (source2) {
51044
- case "project-claude":
51045
- return {
51046
- label: "Project",
51047
- icon: /* @__PURE__ */ jsx(Folder, { size: 12 }),
51048
- color: "#06b6d4",
51049
- bgColor: "#06b6d420"
51050
- };
51051
- case "global-claude":
51052
- return {
51053
- label: "Global",
51054
- icon: /* @__PURE__ */ jsx(Globe, { size: 12 }),
51055
- color: "#8b5cf6",
51056
- bgColor: "#8b5cf620"
51057
- };
51058
- }
51059
- };
51060
- const getModelColor = (model) => {
51061
- switch (model) {
51062
- case "opus":
51063
- return "#f59e0b";
51064
- case "sonnet":
51065
- return "#10b981";
51066
- case "haiku":
51067
- return "#3b82f6";
51068
- case "inherit":
51069
- return "#6b7280";
51070
- default:
51071
- return "#10b981";
51072
- }
51073
- };
51074
- const SubagentCard = ({ subagent, onClick, isSelected }) => {
51075
- const { theme: theme2 } = useTheme();
51076
- const sourceBadge = getSourceBadge(subagent.source);
51077
- const modelColor = getModelColor(subagent.frontmatter.model);
51078
- const hasTools = subagent.frontmatter.tools;
51079
- const toolsArray = hasTools ? hasTools.split(",").map((t) => t.trim()) : null;
51080
- return /* @__PURE__ */ jsxs(
51081
- "div",
51082
- {
51083
- onClick: () => onClick(subagent),
51084
- style: {
51085
- padding: "16px",
51086
- background: isSelected ? `${theme2.colors.primary}10` : theme2.colors.backgroundSecondary,
51087
- border: `1px solid ${isSelected ? theme2.colors.primary : theme2.colors.border}`,
51088
- borderRadius: theme2.radii[2],
51089
- cursor: "pointer",
51090
- transition: "all 0.2s ease",
51091
- display: "flex",
51092
- flexDirection: "column",
51093
- gap: "12px"
51094
- },
51095
- onMouseEnter: (e) => {
51096
- if (!isSelected) {
51097
- e.currentTarget.style.borderColor = theme2.colors.textSecondary;
51098
- }
51099
- },
51100
- onMouseLeave: (e) => {
51101
- if (!isSelected) {
51102
- e.currentTarget.style.borderColor = theme2.colors.border;
51103
- }
51104
- },
51105
- children: [
51106
- /* @__PURE__ */ jsxs(
51107
- "div",
51108
- {
51109
- style: {
51110
- display: "flex",
51111
- alignItems: "flex-start",
51112
- justifyContent: "space-between",
51113
- gap: "8px"
51114
- },
51115
- children: [
51116
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", flex: 1 }, children: [
51117
- /* @__PURE__ */ jsx(Bot, { size: 18, color: theme2.colors.primary }),
51118
- /* @__PURE__ */ jsx(
51119
- "h3",
51120
- {
51121
- style: {
51122
- margin: 0,
51123
- fontSize: theme2.fontSizes[2],
51124
- color: theme2.colors.text,
51125
- fontWeight: 600
51126
- },
51127
- children: subagent.name
51128
- }
51129
- )
51130
- ] }),
51131
- /* @__PURE__ */ jsxs(
51132
- "div",
51133
- {
51134
- style: {
51135
- display: "flex",
51136
- alignItems: "center",
51137
- gap: "4px",
51138
- padding: "4px 8px",
51139
- fontSize: theme2.fontSizes[0],
51140
- color: sourceBadge.color,
51141
- background: sourceBadge.bgColor,
51142
- border: `1px solid ${sourceBadge.color}40`,
51143
- borderRadius: theme2.radii[1],
51144
- flexShrink: 0
51145
- },
51146
- children: [
51147
- sourceBadge.icon,
51148
- /* @__PURE__ */ jsx("span", { children: sourceBadge.label })
51149
- ]
51150
- }
51151
- )
51152
- ]
51153
- }
51154
- ),
51155
- /* @__PURE__ */ jsx(
51156
- "div",
51157
- {
51158
- style: {
51159
- fontSize: theme2.fontSizes[1],
51160
- color: theme2.colors.textSecondary,
51161
- lineHeight: 1.5
51162
- },
51163
- children: subagent.frontmatter.description
51164
- }
51165
- ),
51166
- /* @__PURE__ */ jsx(
51167
- "div",
51168
- {
51169
- style: {
51170
- fontSize: theme2.fontSizes[0],
51171
- color: theme2.colors.textSecondary,
51172
- fontFamily: theme2.fonts.monospace,
51173
- wordBreak: "break-all",
51174
- opacity: 0.7
51175
- },
51176
- children: subagent.path
51177
- }
51178
- ),
51179
- /* @__PURE__ */ jsxs(
51180
- "div",
51181
- {
51182
- style: {
51183
- display: "flex",
51184
- flexWrap: "wrap",
51185
- gap: "6px",
51186
- marginTop: "4px"
51187
- },
51188
- children: [
51189
- subagent.frontmatter.model && /* @__PURE__ */ jsxs(
51190
- "div",
51191
- {
51192
- style: {
51193
- display: "flex",
51194
- alignItems: "center",
51195
- gap: "4px",
51196
- fontSize: theme2.fontSizes[0],
51197
- padding: "3px 8px",
51198
- background: `${modelColor}20`,
51199
- border: `1px solid ${modelColor}40`,
51200
- borderRadius: theme2.radii[1],
51201
- color: modelColor
51202
- },
51203
- children: [
51204
- /* @__PURE__ */ jsx(Zap, { size: 11 }),
51205
- /* @__PURE__ */ jsx("span", { children: subagent.frontmatter.model })
51206
- ]
51207
- }
51208
- ),
51209
- toolsArray && /* @__PURE__ */ jsxs(
51210
- "div",
51211
- {
51212
- style: {
51213
- display: "flex",
51214
- alignItems: "center",
51215
- gap: "4px",
51216
- fontSize: theme2.fontSizes[0],
51217
- padding: "3px 8px",
51218
- background: theme2.colors.background,
51219
- border: `1px solid ${theme2.colors.border}`,
51220
- borderRadius: theme2.radii[1],
51221
- color: theme2.colors.textSecondary
51222
- },
51223
- children: [
51224
- /* @__PURE__ */ jsx(Wrench, { size: 11 }),
51225
- /* @__PURE__ */ jsxs("span", { children: [
51226
- toolsArray.length,
51227
- " ",
51228
- toolsArray.length === 1 ? "tool" : "tools"
51229
- ] })
51230
- ]
51231
- }
51232
- ),
51233
- subagent.frontmatter.permissionMode && subagent.frontmatter.permissionMode !== "default" && /* @__PURE__ */ jsx(
51234
- "div",
51235
- {
51236
- style: {
51237
- fontSize: theme2.fontSizes[0],
51238
- padding: "3px 8px",
51239
- background: theme2.colors.background,
51240
- border: `1px solid ${theme2.colors.border}`,
51241
- borderRadius: theme2.radii[1],
51242
- color: theme2.colors.textSecondary
51243
- },
51244
- children: subagent.frontmatter.permissionMode
51245
- }
51246
- )
51247
- ]
51248
- }
51249
- )
51250
- ]
51251
- }
51252
- );
51253
- };
51254
- const AgentsListPanel = ({
51255
- context,
51256
- events
51257
- }) => {
51258
- const { theme: theme2 } = useTheme();
51259
- const panelRef = useRef(null);
51260
- const [selectedItemId, setSelectedItemId] = useState(null);
51261
- const [searchQuery, setSearchQuery] = useState("");
51262
- const [agentFilter, setAgentFilter] = useState("all");
51263
- const [isRefreshing, setIsRefreshing] = useState(false);
51264
- const {
51265
- agents,
51266
- isLoading: agentsLoading,
51267
- error: agentsError
51268
- } = useAgentsData({ context });
51269
- const {
51270
- subagents,
51271
- isLoading: subagentsLoading,
51272
- error: subagentsError
51273
- } = useSubagentsData({ context });
51274
- const isLoading = agentsLoading || subagentsLoading;
51275
- const error = agentsError || subagentsError;
51276
- gt("agents-list", events, () => {
51277
- var _a;
51278
- return (_a = panelRef.current) == null ? void 0 : _a.focus();
51279
- });
51280
- const allItems = useMemo(() => {
51281
- const items = [];
51282
- agents.forEach((agent) => {
51283
- items.push({ type: "agent", data: agent });
51284
- });
51285
- subagents.forEach((subagent) => {
51286
- items.push({ type: "subagent", data: subagent });
51287
- });
51288
- return items;
51289
- }, [agents, subagents]);
51290
- const filteredItems = useMemo(() => {
51291
- let filtered = allItems;
51292
- if (agentFilter === "documentation") {
51293
- filtered = filtered.filter((item) => item.type === "agent");
51294
- } else if (agentFilter === "subagents") {
51295
- filtered = filtered.filter((item) => item.type === "subagent");
51296
- }
51297
- if (searchQuery.trim()) {
51298
- const query = searchQuery.toLowerCase().trim();
51299
- filtered = filtered.filter((item) => {
51300
- if (item.type === "agent") {
51301
- const agent = item.data;
51302
- if (agent.name.toLowerCase().includes(query)) return true;
51303
- if (agent.path.toLowerCase().includes(query)) return true;
51304
- if (agent.content.toLowerCase().includes(query)) return true;
51305
- return false;
51306
- } else {
51307
- const subagent = item.data;
51308
- if (subagent.name.toLowerCase().includes(query)) return true;
51309
- if (subagent.path.toLowerCase().includes(query)) return true;
51310
- if (subagent.frontmatter.description.toLowerCase().includes(query)) return true;
51311
- if (subagent.prompt.toLowerCase().includes(query)) return true;
51312
- return false;
51313
- }
51314
- });
51315
- }
51316
- return filtered;
51317
- }, [allItems, searchQuery, agentFilter]);
51318
- const handleItemClick = (item) => {
51319
- const itemId = item.type === "agent" ? item.data.id : item.data.id;
51320
- setSelectedItemId(itemId);
51321
- if (events) {
51322
- events.emit({
51323
- type: item.type === "agent" ? "agent:selected" : "subagent:selected",
51324
- source: "agents-list-panel",
51325
- timestamp: Date.now(),
51326
- payload: {
51327
- id: itemId,
51328
- type: item.type,
51329
- data: item.data
51330
- }
51331
- });
51332
- }
51333
- };
51334
- const handleRefresh = async () => {
51335
- setIsRefreshing(true);
51336
- try {
51337
- if (events) {
51338
- events.emit({
51339
- type: "agents:refresh",
51340
- source: "agents-list-panel",
51341
- timestamp: Date.now(),
51342
- payload: {}
51343
- });
51344
- }
51345
- await new Promise((resolve) => setTimeout(resolve, 600));
51346
- } finally {
51347
- setIsRefreshing(false);
51348
- }
51349
- };
51350
- const agentsCount = agents.length;
51351
- const subagentsCount = subagents.length;
51352
- return /* @__PURE__ */ jsxs(
51353
- "div",
51354
- {
51355
- ref: panelRef,
51356
- tabIndex: -1,
51357
- style: {
51358
- padding: "clamp(12px, 3vw, 20px)",
51359
- fontFamily: theme2.fonts.body,
51360
- height: "100%",
51361
- boxSizing: "border-box",
51362
- display: "flex",
51363
- flexDirection: "column",
51364
- gap: "16px",
51365
- overflow: "hidden",
51366
- backgroundColor: theme2.colors.background,
51367
- color: theme2.colors.text,
51368
- outline: "none"
51369
- },
51370
- children: [
51371
- /* @__PURE__ */ jsxs(
51372
- "div",
51373
- {
51374
- style: {
51375
- flexShrink: 0,
51376
- display: "flex",
51377
- alignItems: "center",
51378
- justifyContent: "space-between",
51379
- gap: "12px",
51380
- flexWrap: "wrap"
51381
- },
51382
- children: [
51383
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px" }, children: [
51384
- /* @__PURE__ */ jsx(
51385
- "h2",
51386
- {
51387
- style: {
51388
- margin: 0,
51389
- fontSize: theme2.fontSizes[4],
51390
- color: theme2.colors.text
51391
- },
51392
- children: /* @__PURE__ */ jsx(
51393
- "a",
51394
- {
51395
- href: "https://agents.md/",
51396
- target: "_blank",
51397
- rel: "noopener noreferrer",
51398
- style: {
51399
- color: "inherit",
51400
- textDecoration: "none"
51401
- },
51402
- onMouseEnter: (e) => e.currentTarget.style.textDecoration = "underline",
51403
- onMouseLeave: (e) => e.currentTarget.style.textDecoration = "none",
51404
- children: "Agents"
51405
- }
51406
- )
51407
- }
51408
- ),
51409
- !isLoading && /* @__PURE__ */ jsxs(
51410
- "span",
51411
- {
51412
- style: {
51413
- fontSize: theme2.fontSizes[1],
51414
- color: theme2.colors.textSecondary,
51415
- background: theme2.colors.backgroundSecondary,
51416
- padding: "4px 10px",
51417
- borderRadius: theme2.radii[1]
51418
- },
51419
- children: [
51420
- filteredItems.length,
51421
- " ",
51422
- filteredItems.length === 1 ? "item" : "items"
51423
- ]
51424
- }
51425
- )
51426
- ] }),
51427
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "12px", flex: "1 1 200px", maxWidth: "400px" }, children: [
51428
- /* @__PURE__ */ jsxs(
51429
- "div",
51430
- {
51431
- style: {
51432
- position: "relative",
51433
- flex: 1,
51434
- minWidth: "150px"
51435
- },
51436
- children: [
51437
- /* @__PURE__ */ jsx(
51438
- Search,
51439
- {
51440
- size: 16,
51441
- color: theme2.colors.textSecondary,
51442
- style: {
51443
- position: "absolute",
51444
- left: "10px",
51445
- top: "50%",
51446
- transform: "translateY(-50%)",
51447
- pointerEvents: "none"
51448
- }
51449
- }
51450
- ),
51451
- /* @__PURE__ */ jsx(
51452
- "input",
51453
- {
51454
- type: "text",
51455
- placeholder: "Search agents...",
51456
- value: searchQuery,
51457
- onChange: (e) => setSearchQuery(e.target.value),
51458
- style: {
51459
- width: "100%",
51460
- padding: "8px 32px 8px 32px",
51461
- fontSize: theme2.fontSizes[1],
51462
- fontFamily: theme2.fonts.body,
51463
- border: `1px solid ${theme2.colors.border}`,
51464
- borderRadius: theme2.radii[2],
51465
- background: theme2.colors.backgroundSecondary,
51466
- color: theme2.colors.text,
51467
- outline: "none",
51468
- boxSizing: "border-box"
51469
- }
51470
- }
51471
- ),
51472
- searchQuery && /* @__PURE__ */ jsx(
51473
- "button",
51474
- {
51475
- onClick: () => setSearchQuery(""),
51476
- style: {
51477
- position: "absolute",
51478
- right: "6px",
51479
- top: "50%",
51480
- transform: "translateY(-50%)",
51481
- background: "transparent",
51482
- border: "none",
51483
- padding: "4px",
51484
- cursor: "pointer",
51485
- display: "flex",
51486
- alignItems: "center",
51487
- justifyContent: "center",
51488
- color: theme2.colors.textSecondary
51489
- },
51490
- "aria-label": "Clear search",
51491
- children: /* @__PURE__ */ jsx(X, { size: 14 })
51492
- }
51493
- )
51494
- ]
51495
- }
51496
- ),
51497
- /* @__PURE__ */ jsx(
51498
- "button",
51499
- {
51500
- onClick: handleRefresh,
51501
- disabled: isRefreshing || isLoading,
51502
- style: {
51503
- background: theme2.colors.backgroundSecondary,
51504
- border: `1px solid ${theme2.colors.border}`,
51505
- borderRadius: theme2.radii[1],
51506
- padding: "8px",
51507
- cursor: isRefreshing ? "wait" : "pointer",
51508
- display: "flex",
51509
- alignItems: "center",
51510
- justifyContent: "center",
51511
- transition: "all 0.2s ease"
51512
- },
51513
- title: "Refresh agents",
51514
- children: /* @__PURE__ */ jsx(
51515
- RefreshCw,
51516
- {
51517
- size: 16,
51518
- color: theme2.colors.textSecondary,
51519
- style: {
51520
- animation: isRefreshing ? "spin 1s linear infinite" : "none"
51521
- }
51522
- }
51523
- )
51524
- }
51525
- )
51526
- ] })
51527
- ]
51528
- }
51529
- ),
51530
- /* @__PURE__ */ jsxs(
51531
- "div",
51532
- {
51533
- style: {
51534
- flexShrink: 0,
51535
- display: "flex",
51536
- gap: "8px"
51537
- },
51538
- children: [
51539
- /* @__PURE__ */ jsxs(
51540
- "button",
51541
- {
51542
- onClick: () => setAgentFilter("all"),
51543
- style: {
51544
- padding: "8px 16px",
51545
- fontSize: theme2.fontSizes[1],
51546
- fontFamily: theme2.fonts.body,
51547
- border: `1px solid ${agentFilter === "all" ? theme2.colors.primary : theme2.colors.border}`,
51548
- borderRadius: theme2.radii[1],
51549
- background: agentFilter === "all" ? `${theme2.colors.primary}15` : theme2.colors.backgroundSecondary,
51550
- color: agentFilter === "all" ? theme2.colors.primary : theme2.colors.text,
51551
- cursor: "pointer",
51552
- display: "flex",
51553
- alignItems: "center",
51554
- gap: "6px",
51555
- fontWeight: agentFilter === "all" ? 600 : 400,
51556
- transition: "all 0.2s ease"
51557
- },
51558
- children: [
51559
- "All (",
51560
- agentsCount + subagentsCount,
51561
- ")"
51562
- ]
51563
- }
51564
- ),
51565
- /* @__PURE__ */ jsxs(
51566
- "button",
51567
- {
51568
- onClick: () => setAgentFilter("documentation"),
51569
- style: {
51570
- padding: "8px 16px",
51571
- fontSize: theme2.fontSizes[1],
51572
- fontFamily: theme2.fonts.body,
51573
- border: `1px solid ${agentFilter === "documentation" ? theme2.colors.primary : theme2.colors.border}`,
51574
- borderRadius: theme2.radii[1],
51575
- background: agentFilter === "documentation" ? `${theme2.colors.primary}15` : theme2.colors.backgroundSecondary,
51576
- color: agentFilter === "documentation" ? theme2.colors.primary : theme2.colors.text,
51577
- cursor: "pointer",
51578
- display: "flex",
51579
- alignItems: "center",
51580
- gap: "6px",
51581
- fontWeight: agentFilter === "documentation" ? 600 : 400,
51582
- transition: "all 0.2s ease"
51583
- },
51584
- children: [
51585
- /* @__PURE__ */ jsx(BookOpen, { size: 14 }),
51586
- "Docs (",
51587
- agentsCount,
51588
- ")"
51589
- ]
51590
- }
51591
- ),
51592
- /* @__PURE__ */ jsxs(
51593
- "button",
51594
- {
51595
- onClick: () => setAgentFilter("subagents"),
51596
- style: {
51597
- padding: "8px 16px",
51598
- fontSize: theme2.fontSizes[1],
51599
- fontFamily: theme2.fonts.body,
51600
- border: `1px solid ${agentFilter === "subagents" ? theme2.colors.primary : theme2.colors.border}`,
51601
- borderRadius: theme2.radii[1],
51602
- background: agentFilter === "subagents" ? `${theme2.colors.primary}15` : theme2.colors.backgroundSecondary,
51603
- color: agentFilter === "subagents" ? theme2.colors.primary : theme2.colors.text,
51604
- cursor: "pointer",
51605
- display: "flex",
51606
- alignItems: "center",
51607
- gap: "6px",
51608
- fontWeight: agentFilter === "subagents" ? 600 : 400,
51609
- transition: "all 0.2s ease"
51610
- },
51611
- children: [
51612
- /* @__PURE__ */ jsx(Bot, { size: 14 }),
51613
- "Subagents (",
51614
- subagentsCount,
51615
- ")"
51616
- ]
51617
- }
51618
- )
51619
- ]
51620
- }
51621
- ),
51622
- error && /* @__PURE__ */ jsxs(
51623
- "div",
51624
- {
51625
- style: {
51626
- flexShrink: 0,
51627
- padding: "12px",
51628
- background: `${theme2.colors.error}20`,
51629
- border: `1px solid ${theme2.colors.error}`,
51630
- borderRadius: theme2.radii[2],
51631
- display: "flex",
51632
- alignItems: "center",
51633
- gap: "8px",
51634
- color: theme2.colors.error,
51635
- fontSize: theme2.fontSizes[1]
51636
- },
51637
- children: [
51638
- /* @__PURE__ */ jsx(CircleAlert, { size: 16 }),
51639
- /* @__PURE__ */ jsx("span", { children: error })
51640
- ]
51641
- }
51642
- ),
51643
- /* @__PURE__ */ jsx(
51644
- "div",
51645
- {
51646
- style: {
51647
- flex: 1,
51648
- overflowY: "auto",
51649
- minHeight: 0
51650
- },
51651
- children: isLoading ? /* @__PURE__ */ jsx(
51652
- "div",
51653
- {
51654
- style: {
51655
- height: "100%",
51656
- display: "flex",
51657
- alignItems: "center",
51658
- justifyContent: "center",
51659
- color: theme2.colors.textSecondary,
51660
- fontSize: theme2.fontSizes[2]
51661
- },
51662
- children: "Loading agents..."
51663
- }
51664
- ) : filteredItems.length === 0 ? /* @__PURE__ */ jsxs(
51665
- "div",
51666
- {
51667
- style: {
51668
- height: "100%",
51669
- display: "flex",
51670
- flexDirection: "column",
51671
- alignItems: "center",
51672
- justifyContent: "center",
51673
- gap: "16px",
51674
- color: theme2.colors.textSecondary,
51675
- padding: "24px"
51676
- },
51677
- children: [
51678
- /* @__PURE__ */ jsx(FileCode, { size: 48, color: theme2.colors.border }),
51679
- /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
51680
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: theme2.fontSizes[2] }, children: searchQuery ? "No agents match your search" : "No agents found" }),
51681
- /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: theme2.fontSizes[1] }, children: searchQuery ? "Try a different search term" : "Add AGENTS.md or create subagents in .claude/agents/ to get started" })
51682
- ] })
51683
- ]
51684
- }
51685
- ) : /* @__PURE__ */ jsx(
51686
- "div",
51687
- {
51688
- style: {
51689
- display: "grid",
51690
- gridTemplateColumns: "repeat(auto-fill, minmax(250px, 1fr))",
51691
- gap: "16px",
51692
- padding: "4px"
51693
- },
51694
- children: filteredItems.map((item) => {
51695
- if (item.type === "agent") {
51696
- return /* @__PURE__ */ jsx(
51697
- AgentCard,
51698
- {
51699
- agent: item.data,
51700
- onClick: () => handleItemClick(item),
51701
- isSelected: selectedItemId === item.data.id
51702
- },
51703
- item.data.id
51704
- );
51705
- } else {
51706
- return /* @__PURE__ */ jsx(
51707
- SubagentCard,
51708
- {
51709
- subagent: item.data,
51710
- onClick: () => handleItemClick(item),
51711
- isSelected: selectedItemId === item.data.id
51712
- },
51713
- item.data.id
51714
- );
51715
- }
51716
- })
51717
- }
51718
- )
51719
- }
51720
- ),
51721
- /* @__PURE__ */ jsx("style", { children: `
51722
- @keyframes spin {
51723
- to { transform: rotate(360deg); }
51724
- }
51725
- ` })
51726
- ]
51727
- }
51728
- );
51729
- };
51730
50420
  const AgentDetailPanel = ({
51731
50421
  context,
51732
50422
  events
@@ -52214,6 +50904,411 @@ const AgentDetailPanel = ({
52214
50904
  }
52215
50905
  return null;
52216
50906
  };
50907
+ const getSourceBadge$1 = (source2) => {
50908
+ switch (source2) {
50909
+ case "project-root":
50910
+ return {
50911
+ label: "Root",
50912
+ icon: /* @__PURE__ */ jsx(FileText, { size: 12 }),
50913
+ color: "#10b981",
50914
+ bgColor: "#10b98120"
50915
+ };
50916
+ case "project-nested":
50917
+ return {
50918
+ label: "Nested",
50919
+ icon: /* @__PURE__ */ jsx(FolderTree, { size: 12 }),
50920
+ color: "#3b82f6",
50921
+ bgColor: "#3b82f620"
50922
+ };
50923
+ case "global-universal":
50924
+ return {
50925
+ label: "Global",
50926
+ icon: /* @__PURE__ */ jsx(Folder, { size: 12 }),
50927
+ color: "#8b5cf6",
50928
+ bgColor: "#8b5cf620"
50929
+ };
50930
+ }
50931
+ };
50932
+ const AgentCard = ({ agent, onClick, isSelected }) => {
50933
+ var _a;
50934
+ const { theme: theme2 } = useTheme();
50935
+ const sourceBadge = getSourceBadge$1(agent.source);
50936
+ const [pathCopied, setPathCopied] = React2__default.useState(false);
50937
+ const preview = ((_a = agent.content.split("\n").find((line) => line.trim() && !line.startsWith("#"))) == null ? void 0 : _a.substring(0, 150)) || "No description available";
50938
+ const handleCopyPath = async (e) => {
50939
+ e.stopPropagation();
50940
+ try {
50941
+ await navigator.clipboard.writeText(agent.path);
50942
+ setPathCopied(true);
50943
+ setTimeout(() => setPathCopied(false), 2e3);
50944
+ } catch (err) {
50945
+ console.error("Failed to copy path:", err);
50946
+ }
50947
+ };
50948
+ return /* @__PURE__ */ jsxs(
50949
+ "div",
50950
+ {
50951
+ onClick: () => onClick(agent),
50952
+ style: {
50953
+ padding: "16px",
50954
+ background: isSelected ? `${theme2.colors.primary}10` : theme2.colors.backgroundSecondary,
50955
+ border: `1px solid ${isSelected ? theme2.colors.primary : theme2.colors.border}`,
50956
+ borderRadius: theme2.radii[2],
50957
+ cursor: "pointer",
50958
+ transition: "all 0.2s ease",
50959
+ display: "flex",
50960
+ flexDirection: "column",
50961
+ gap: "12px"
50962
+ },
50963
+ onMouseEnter: (e) => {
50964
+ if (!isSelected) {
50965
+ e.currentTarget.style.borderColor = theme2.colors.textSecondary;
50966
+ }
50967
+ },
50968
+ onMouseLeave: (e) => {
50969
+ if (!isSelected) {
50970
+ e.currentTarget.style.borderColor = theme2.colors.border;
50971
+ }
50972
+ },
50973
+ children: [
50974
+ /* @__PURE__ */ jsxs(
50975
+ "div",
50976
+ {
50977
+ style: {
50978
+ display: "flex",
50979
+ alignItems: "flex-start",
50980
+ justifyContent: "space-between",
50981
+ gap: "8px"
50982
+ },
50983
+ children: [
50984
+ /* @__PURE__ */ jsx(
50985
+ "h3",
50986
+ {
50987
+ style: {
50988
+ margin: 0,
50989
+ fontSize: theme2.fontSizes[2],
50990
+ color: theme2.colors.text,
50991
+ fontWeight: 600,
50992
+ flex: 1
50993
+ },
50994
+ children: agent.name
50995
+ }
50996
+ ),
50997
+ /* @__PURE__ */ jsxs(
50998
+ "div",
50999
+ {
51000
+ style: {
51001
+ display: "flex",
51002
+ alignItems: "center",
51003
+ gap: "4px",
51004
+ padding: "4px 8px",
51005
+ fontSize: theme2.fontSizes[0],
51006
+ color: sourceBadge.color,
51007
+ background: sourceBadge.bgColor,
51008
+ border: `1px solid ${sourceBadge.color}40`,
51009
+ borderRadius: theme2.radii[1],
51010
+ flexShrink: 0
51011
+ },
51012
+ children: [
51013
+ sourceBadge.icon,
51014
+ /* @__PURE__ */ jsx("span", { children: sourceBadge.label })
51015
+ ]
51016
+ }
51017
+ )
51018
+ ]
51019
+ }
51020
+ ),
51021
+ /* @__PURE__ */ jsx(
51022
+ "div",
51023
+ {
51024
+ onClick: handleCopyPath,
51025
+ style: {
51026
+ fontSize: theme2.fontSizes[0],
51027
+ color: pathCopied ? theme2.colors.success : theme2.colors.textMuted,
51028
+ fontFamily: theme2.fonts.monospace,
51029
+ background: pathCopied ? `${theme2.colors.success}15` : theme2.colors.background,
51030
+ padding: "4px 8px",
51031
+ borderRadius: theme2.radii[1],
51032
+ overflow: "hidden",
51033
+ textOverflow: "ellipsis",
51034
+ whiteSpace: "nowrap",
51035
+ cursor: "pointer",
51036
+ transition: "all 0.2s ease",
51037
+ border: `1px solid ${pathCopied ? theme2.colors.success : "transparent"}`
51038
+ },
51039
+ title: pathCopied ? "Copied!" : `Click to copy: ${agent.path}`,
51040
+ onMouseEnter: (e) => {
51041
+ if (!pathCopied) {
51042
+ e.currentTarget.style.background = theme2.colors.backgroundTertiary || theme2.colors.border;
51043
+ }
51044
+ },
51045
+ onMouseLeave: (e) => {
51046
+ if (!pathCopied) {
51047
+ e.currentTarget.style.background = theme2.colors.background;
51048
+ }
51049
+ },
51050
+ children: pathCopied ? "Copied!" : agent.path
51051
+ }
51052
+ ),
51053
+ /* @__PURE__ */ jsx(
51054
+ "div",
51055
+ {
51056
+ style: {
51057
+ fontSize: theme2.fontSizes[1],
51058
+ color: theme2.colors.textSecondary,
51059
+ lineHeight: 1.5,
51060
+ overflow: "hidden",
51061
+ textOverflow: "ellipsis",
51062
+ display: "-webkit-box",
51063
+ WebkitLineClamp: 3,
51064
+ WebkitBoxOrient: "vertical"
51065
+ },
51066
+ children: preview
51067
+ }
51068
+ ),
51069
+ agent.sections && Object.keys(agent.sections).length > 0 && /* @__PURE__ */ jsx(
51070
+ "div",
51071
+ {
51072
+ style: {
51073
+ display: "flex",
51074
+ flexWrap: "wrap",
51075
+ gap: "6px",
51076
+ marginTop: "4px"
51077
+ },
51078
+ children: Object.keys(agent.sections).map((section) => /* @__PURE__ */ jsx(
51079
+ "span",
51080
+ {
51081
+ style: {
51082
+ fontSize: theme2.fontSizes[0],
51083
+ padding: "2px 8px",
51084
+ background: theme2.colors.background,
51085
+ border: `1px solid ${theme2.colors.border}`,
51086
+ borderRadius: theme2.radii[1],
51087
+ color: theme2.colors.textSecondary,
51088
+ textTransform: "capitalize"
51089
+ },
51090
+ children: section
51091
+ },
51092
+ section
51093
+ ))
51094
+ }
51095
+ )
51096
+ ]
51097
+ }
51098
+ );
51099
+ };
51100
+ const getSourceBadge = (source2) => {
51101
+ switch (source2) {
51102
+ case "project-claude":
51103
+ return {
51104
+ label: "Project",
51105
+ icon: /* @__PURE__ */ jsx(Folder, { size: 12 }),
51106
+ color: "#06b6d4",
51107
+ bgColor: "#06b6d420"
51108
+ };
51109
+ case "global-claude":
51110
+ return {
51111
+ label: "Global",
51112
+ icon: /* @__PURE__ */ jsx(Globe, { size: 12 }),
51113
+ color: "#8b5cf6",
51114
+ bgColor: "#8b5cf620"
51115
+ };
51116
+ }
51117
+ };
51118
+ const getModelColor = (model) => {
51119
+ switch (model) {
51120
+ case "opus":
51121
+ return "#f59e0b";
51122
+ case "sonnet":
51123
+ return "#10b981";
51124
+ case "haiku":
51125
+ return "#3b82f6";
51126
+ case "inherit":
51127
+ return "#6b7280";
51128
+ default:
51129
+ return "#10b981";
51130
+ }
51131
+ };
51132
+ const SubagentCard = ({ subagent, onClick, isSelected }) => {
51133
+ const { theme: theme2 } = useTheme();
51134
+ const sourceBadge = getSourceBadge(subagent.source);
51135
+ const modelColor = getModelColor(subagent.frontmatter.model);
51136
+ const hasTools = subagent.frontmatter.tools;
51137
+ const toolsArray = hasTools ? hasTools.split(",").map((t) => t.trim()) : null;
51138
+ return /* @__PURE__ */ jsxs(
51139
+ "div",
51140
+ {
51141
+ onClick: () => onClick(subagent),
51142
+ style: {
51143
+ padding: "16px",
51144
+ background: isSelected ? `${theme2.colors.primary}10` : theme2.colors.backgroundSecondary,
51145
+ border: `1px solid ${isSelected ? theme2.colors.primary : theme2.colors.border}`,
51146
+ borderRadius: theme2.radii[2],
51147
+ cursor: "pointer",
51148
+ transition: "all 0.2s ease",
51149
+ display: "flex",
51150
+ flexDirection: "column",
51151
+ gap: "12px"
51152
+ },
51153
+ onMouseEnter: (e) => {
51154
+ if (!isSelected) {
51155
+ e.currentTarget.style.borderColor = theme2.colors.textSecondary;
51156
+ }
51157
+ },
51158
+ onMouseLeave: (e) => {
51159
+ if (!isSelected) {
51160
+ e.currentTarget.style.borderColor = theme2.colors.border;
51161
+ }
51162
+ },
51163
+ children: [
51164
+ /* @__PURE__ */ jsxs(
51165
+ "div",
51166
+ {
51167
+ style: {
51168
+ display: "flex",
51169
+ alignItems: "flex-start",
51170
+ justifyContent: "space-between",
51171
+ gap: "8px"
51172
+ },
51173
+ children: [
51174
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", flex: 1 }, children: [
51175
+ /* @__PURE__ */ jsx(Bot, { size: 18, color: theme2.colors.primary }),
51176
+ /* @__PURE__ */ jsx(
51177
+ "h3",
51178
+ {
51179
+ style: {
51180
+ margin: 0,
51181
+ fontSize: theme2.fontSizes[2],
51182
+ color: theme2.colors.text,
51183
+ fontWeight: 600
51184
+ },
51185
+ children: subagent.name
51186
+ }
51187
+ )
51188
+ ] }),
51189
+ /* @__PURE__ */ jsxs(
51190
+ "div",
51191
+ {
51192
+ style: {
51193
+ display: "flex",
51194
+ alignItems: "center",
51195
+ gap: "4px",
51196
+ padding: "4px 8px",
51197
+ fontSize: theme2.fontSizes[0],
51198
+ color: sourceBadge.color,
51199
+ background: sourceBadge.bgColor,
51200
+ border: `1px solid ${sourceBadge.color}40`,
51201
+ borderRadius: theme2.radii[1],
51202
+ flexShrink: 0
51203
+ },
51204
+ children: [
51205
+ sourceBadge.icon,
51206
+ /* @__PURE__ */ jsx("span", { children: sourceBadge.label })
51207
+ ]
51208
+ }
51209
+ )
51210
+ ]
51211
+ }
51212
+ ),
51213
+ /* @__PURE__ */ jsx(
51214
+ "div",
51215
+ {
51216
+ style: {
51217
+ fontSize: theme2.fontSizes[1],
51218
+ color: theme2.colors.textSecondary,
51219
+ lineHeight: 1.5
51220
+ },
51221
+ children: subagent.frontmatter.description
51222
+ }
51223
+ ),
51224
+ /* @__PURE__ */ jsx(
51225
+ "div",
51226
+ {
51227
+ style: {
51228
+ fontSize: theme2.fontSizes[0],
51229
+ color: theme2.colors.textSecondary,
51230
+ fontFamily: theme2.fonts.monospace,
51231
+ wordBreak: "break-all",
51232
+ opacity: 0.7
51233
+ },
51234
+ children: subagent.path
51235
+ }
51236
+ ),
51237
+ /* @__PURE__ */ jsxs(
51238
+ "div",
51239
+ {
51240
+ style: {
51241
+ display: "flex",
51242
+ flexWrap: "wrap",
51243
+ gap: "6px",
51244
+ marginTop: "4px"
51245
+ },
51246
+ children: [
51247
+ subagent.frontmatter.model && /* @__PURE__ */ jsxs(
51248
+ "div",
51249
+ {
51250
+ style: {
51251
+ display: "flex",
51252
+ alignItems: "center",
51253
+ gap: "4px",
51254
+ fontSize: theme2.fontSizes[0],
51255
+ padding: "3px 8px",
51256
+ background: `${modelColor}20`,
51257
+ border: `1px solid ${modelColor}40`,
51258
+ borderRadius: theme2.radii[1],
51259
+ color: modelColor
51260
+ },
51261
+ children: [
51262
+ /* @__PURE__ */ jsx(Zap, { size: 11 }),
51263
+ /* @__PURE__ */ jsx("span", { children: subagent.frontmatter.model })
51264
+ ]
51265
+ }
51266
+ ),
51267
+ toolsArray && /* @__PURE__ */ jsxs(
51268
+ "div",
51269
+ {
51270
+ style: {
51271
+ display: "flex",
51272
+ alignItems: "center",
51273
+ gap: "4px",
51274
+ fontSize: theme2.fontSizes[0],
51275
+ padding: "3px 8px",
51276
+ background: theme2.colors.background,
51277
+ border: `1px solid ${theme2.colors.border}`,
51278
+ borderRadius: theme2.radii[1],
51279
+ color: theme2.colors.textSecondary
51280
+ },
51281
+ children: [
51282
+ /* @__PURE__ */ jsx(Wrench, { size: 11 }),
51283
+ /* @__PURE__ */ jsxs("span", { children: [
51284
+ toolsArray.length,
51285
+ " ",
51286
+ toolsArray.length === 1 ? "tool" : "tools"
51287
+ ] })
51288
+ ]
51289
+ }
51290
+ ),
51291
+ subagent.frontmatter.permissionMode && subagent.frontmatter.permissionMode !== "default" && /* @__PURE__ */ jsx(
51292
+ "div",
51293
+ {
51294
+ style: {
51295
+ fontSize: theme2.fontSizes[0],
51296
+ padding: "3px 8px",
51297
+ background: theme2.colors.background,
51298
+ border: `1px solid ${theme2.colors.border}`,
51299
+ borderRadius: theme2.radii[1],
51300
+ color: theme2.colors.textSecondary
51301
+ },
51302
+ children: subagent.frontmatter.permissionMode
51303
+ }
51304
+ )
51305
+ ]
51306
+ }
51307
+ )
51308
+ ]
51309
+ }
51310
+ );
51311
+ };
52217
51312
  const AgenticResourcesPanel = ({
52218
51313
  context,
52219
51314
  events
@@ -52221,6 +51316,8 @@ const AgenticResourcesPanel = ({
52221
51316
  var _a;
52222
51317
  const { theme: theme2 } = useTheme();
52223
51318
  const panelRef = useRef(null);
51319
+ const hasLoadedAgentsRef = useRef(false);
51320
+ const hasLoadedSkillsRef = useRef(false);
52224
51321
  const [mode, setMode] = useState("agents");
52225
51322
  const [selectedItemId, setSelectedItemId] = useState(null);
52226
51323
  const [searchQuery, setSearchQuery] = useState("");
@@ -52243,7 +51340,15 @@ const AgenticResourcesPanel = ({
52243
51340
  error: skillsError,
52244
51341
  refreshSkills
52245
51342
  } = useSkillsData({ context });
52246
- const isLoading = mode === "agents" ? agentsLoading || subagentsLoading : skillsLoading;
51343
+ if (!agentsLoading && !subagentsLoading && !hasLoadedAgentsRef.current) {
51344
+ hasLoadedAgentsRef.current = true;
51345
+ }
51346
+ if (!skillsLoading && !hasLoadedSkillsRef.current) {
51347
+ hasLoadedSkillsRef.current = true;
51348
+ }
51349
+ const showAgentsLoading = (agentsLoading || subagentsLoading) && !hasLoadedAgentsRef.current;
51350
+ const showSkillsLoading = skillsLoading && !hasLoadedSkillsRef.current;
51351
+ const isLoading = mode === "agents" ? showAgentsLoading : showSkillsLoading;
52247
51352
  const error = mode === "agents" ? agentsError || subagentsError : skillsError;
52248
51353
  gt("agentic-resources", events, () => {
52249
51354
  var _a2;
@@ -52872,31 +51977,6 @@ const AgenticResourcesPanel = ({
52872
51977
  );
52873
51978
  };
52874
51979
  const panels = [
52875
- {
52876
- metadata: {
52877
- id: "industry-theme.skills-list",
52878
- name: "Skills List",
52879
- icon: "⚡",
52880
- version: "0.1.0",
52881
- author: "Principal ADE",
52882
- description: "Display and manage Agent Skills from SKILL.md files",
52883
- slices: ["fileTree", "globalSkills"]
52884
- // Data slices this panel depends on
52885
- },
52886
- component: SkillsListPanel,
52887
- // Optional: Called when this specific panel is mounted
52888
- onMount: async (context) => {
52889
- var _a;
52890
- console.log(
52891
- "Skills List Panel mounted",
52892
- (_a = context.currentScope.repository) == null ? void 0 : _a.path
52893
- );
52894
- },
52895
- // Optional: Called when this specific panel is unmounted
52896
- onUnmount: async (_context) => {
52897
- console.log("Skills List Panel unmounting");
52898
- }
52899
- },
52900
51980
  {
52901
51981
  metadata: {
52902
51982
  id: "industry-theme.skills-browse",
@@ -52972,31 +52052,6 @@ const panels = [
52972
52052
  console.log("Skill Detail Panel unmounting");
52973
52053
  }
52974
52054
  },
52975
- {
52976
- metadata: {
52977
- id: "industry-theme.agents-list",
52978
- name: "Agents List",
52979
- icon: "🤖",
52980
- version: "0.1.0",
52981
- author: "Principal ADE",
52982
- description: "Display AGENTS.md documentation and Claude Code subagents",
52983
- slices: ["fileTree", "globalAgents", "globalSubagents"]
52984
- // Data slices this panel depends on
52985
- },
52986
- component: AgentsListPanel,
52987
- // Optional: Called when this specific panel is mounted
52988
- onMount: async (context) => {
52989
- var _a;
52990
- console.log(
52991
- "Agents List Panel mounted",
52992
- (_a = context.currentScope.repository) == null ? void 0 : _a.path
52993
- );
52994
- },
52995
- // Optional: Called when this specific panel is unmounted
52996
- onUnmount: async (_context) => {
52997
- console.log("Agents List Panel unmounting");
52998
- }
52999
- },
53000
52055
  {
53001
52056
  metadata: {
53002
52057
  id: "industry-theme.agent-detail",