@industry-theme/agent-panels 0.2.14 → 0.2.15

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.
@@ -2723,6 +2723,76 @@ const parseSkillContent = async (content2, path2, fileTree, fileSystemAdapter, i
2723
2723
  frontmatterValidation
2724
2724
  };
2725
2725
  };
2726
+ const getDeduplicationKey = (skill) => {
2727
+ var _a, _b, _c;
2728
+ 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)) {
2729
+ return `github:${skill.metadata.owner}/${skill.metadata.repo}/${skill.metadata.skillPath}`;
2730
+ }
2731
+ const normalizedName = skill.name.toLowerCase().replace(/\s+/g, "-");
2732
+ return `name:${normalizedName}`;
2733
+ };
2734
+ const comparePriority = (skill1, skill2) => {
2735
+ var _a, _b;
2736
+ if (skill1.priority !== skill2.priority) {
2737
+ return skill1.priority < skill2.priority;
2738
+ }
2739
+ const time1 = ((_a = skill1.metadata) == null ? void 0 : _a.installedAt) ? new Date(skill1.metadata.installedAt).getTime() : 0;
2740
+ const time2 = ((_b = skill2.metadata) == null ? void 0 : _b.installedAt) ? new Date(skill2.metadata.installedAt).getTime() : 0;
2741
+ return time1 > time2;
2742
+ };
2743
+ const skillToInstallation = (skill) => ({
2744
+ path: skill.path,
2745
+ source: skill.source,
2746
+ priority: skill.priority,
2747
+ skillFolderPath: skill.skillFolderPath,
2748
+ metadata: skill.metadata
2749
+ });
2750
+ const deduplicateSkills = (skills, isBrowserMode = false) => {
2751
+ if (isBrowserMode) {
2752
+ console.log("[useSkillsData] Browser mode detected, skipping deduplication");
2753
+ return skills;
2754
+ }
2755
+ if (skills.length === 0) {
2756
+ return skills;
2757
+ }
2758
+ const skillGroups = /* @__PURE__ */ new Map();
2759
+ for (const skill of skills) {
2760
+ const key = getDeduplicationKey(skill);
2761
+ const group = skillGroups.get(key) || [];
2762
+ group.push(skill);
2763
+ skillGroups.set(key, group);
2764
+ }
2765
+ console.log("[useSkillsData] Deduplication found", skillGroups.size, "unique skills from", skills.length, "total");
2766
+ const deduplicatedSkills = [];
2767
+ for (const [key, group] of skillGroups.entries()) {
2768
+ if (group.length === 1) {
2769
+ deduplicatedSkills.push({
2770
+ ...group[0],
2771
+ installedLocations: [skillToInstallation(group[0])]
2772
+ });
2773
+ continue;
2774
+ }
2775
+ const sortedByPriority = [...group].sort(
2776
+ (a, b) => comparePriority(a, b) ? -1 : 1
2777
+ );
2778
+ const primary = sortedByPriority[0];
2779
+ const installations = group.map(skillToInstallation);
2780
+ installations.sort((a, b) => a.priority - b.priority);
2781
+ console.log(
2782
+ "[useSkillsData] Deduplicated skill:",
2783
+ primary.name,
2784
+ "from",
2785
+ group.length,
2786
+ "installations. Primary:",
2787
+ primary.source
2788
+ );
2789
+ deduplicatedSkills.push({
2790
+ ...primary,
2791
+ installedLocations: installations
2792
+ });
2793
+ }
2794
+ return deduplicatedSkills;
2795
+ };
2726
2796
  const useSkillsData = ({
2727
2797
  context
2728
2798
  }) => {
@@ -2750,8 +2820,9 @@ const useSkillsData = ({
2750
2820
  setError(null);
2751
2821
  try {
2752
2822
  let localSkills = [];
2823
+ let isBrowserMode = false;
2753
2824
  if (fileTree && (fileSystem == null ? void 0 : fileSystem.readFile) && repoPath) {
2754
- const isBrowserMode = !repoPath.startsWith("/");
2825
+ isBrowserMode = !repoPath.startsWith("/");
2755
2826
  console.log("[useSkillsData] fileTree:", fileTree);
2756
2827
  console.log("[useSkillsData] typeof fileTree:", typeof fileTree);
2757
2828
  console.log("[useSkillsData] fileTree keys:", Object.keys(fileTree));
@@ -2774,8 +2845,10 @@ const useSkillsData = ({
2774
2845
  }
2775
2846
  console.log("[useSkillsData] Global skills:", globalSkills);
2776
2847
  const allSkills = [...localSkills, ...globalSkills];
2777
- console.log("[useSkillsData] Total skills:", allSkills.length);
2778
- setSkills(allSkills);
2848
+ console.log("[useSkillsData] Total skills before deduplication:", allSkills.length);
2849
+ const deduplicatedSkills = deduplicateSkills(allSkills, isBrowserMode);
2850
+ console.log("[useSkillsData] Total skills after deduplication:", deduplicatedSkills.length);
2851
+ setSkills(deduplicatedSkills);
2779
2852
  lastLoadedSha.current = fileTreeSha;
2780
2853
  lastGlobalSkillsCount.current = globalSkillsCount;
2781
2854
  } catch (err) {
@@ -2801,7 +2874,7 @@ const useSkillsData = ({
2801
2874
  refreshSkills
2802
2875
  };
2803
2876
  };
2804
- const getSourceConfig = (source2) => {
2877
+ const getSourceConfig$1 = (source2) => {
2805
2878
  switch (source2) {
2806
2879
  case "global-universal":
2807
2880
  return {
@@ -2850,6 +2923,20 @@ const getSourceConfig = (source2) => {
2850
2923
  };
2851
2924
  }
2852
2925
  };
2926
+ const abbreviateSourceName = (source2) => {
2927
+ switch (source2) {
2928
+ case "project-universal":
2929
+ return "Project";
2930
+ case "global-universal":
2931
+ return "Global";
2932
+ case "project-claude":
2933
+ return "Project (Claude)";
2934
+ case "global-claude":
2935
+ return "Global (Claude)";
2936
+ case "project-other":
2937
+ return "Project";
2938
+ }
2939
+ };
2853
2940
  const SkillCard = ({
2854
2941
  skill,
2855
2942
  onClick,
@@ -2857,7 +2944,7 @@ const SkillCard = ({
2857
2944
  }) => {
2858
2945
  var _a, _b, _c, _d, _e2, _f, _g, _h;
2859
2946
  const { theme: theme2 } = useTheme();
2860
- const sourceConfig = getSourceConfig(skill.source);
2947
+ const sourceConfig = getSourceConfig$1(skill.source);
2861
2948
  const [pathCopied, setPathCopied] = React2__default.useState(false);
2862
2949
  const handleCopyPath = async (e) => {
2863
2950
  e.stopPropagation();
@@ -2994,7 +3081,39 @@ Installed: ${skill.metadata.installedAt ? new Date(skill.metadata.installedAt).t
2994
3081
  /* @__PURE__ */ jsx("span", { children: skill.frontmatterValidation.hasStructure ? skill.frontmatterValidation.missingFields.length > 0 ? `Missing: ${skill.frontmatterValidation.missingFields.join(", ")}` : "Invalid Frontmatter" : "No Frontmatter" })
2995
3082
  ]
2996
3083
  }
2997
- )
3084
+ ),
3085
+ skill.installedLocations && skill.installedLocations.length > 1 && (() => {
3086
+ const otherLocations = skill.installedLocations.filter((loc) => loc.path !== skill.path).map((loc) => abbreviateSourceName(loc.source));
3087
+ const uniqueLocations = Array.from(new Set(otherLocations));
3088
+ const locationText = uniqueLocations.join(", ");
3089
+ return /* @__PURE__ */ jsxs(
3090
+ "div",
3091
+ {
3092
+ style: {
3093
+ display: "inline-flex",
3094
+ alignItems: "center",
3095
+ gap: "4px",
3096
+ padding: "2px 6px",
3097
+ borderRadius: theme2.radii[1],
3098
+ backgroundColor: `${theme2.colors.accent}15`,
3099
+ border: `1px solid ${theme2.colors.accent}30`,
3100
+ fontSize: theme2.fontSizes[0],
3101
+ color: theme2.colors.accent,
3102
+ fontWeight: 500,
3103
+ width: "fit-content"
3104
+ },
3105
+ title: `Also installed in:
3106
+ ${skill.installedLocations.filter((loc) => loc.path !== skill.path).map((loc) => `${abbreviateSourceName(loc.source)}: ${loc.path}`).join("\n")}`,
3107
+ children: [
3108
+ /* @__PURE__ */ jsx(Package, { size: 10 }),
3109
+ /* @__PURE__ */ jsxs("span", { children: [
3110
+ "Also in: ",
3111
+ locationText
3112
+ ] })
3113
+ ]
3114
+ }
3115
+ );
3116
+ })()
2998
3117
  ] })
2999
3118
  ] }),
3000
3119
  (skill.hasScripts || skill.hasReferences || skill.hasAssets) && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", flexShrink: 0 }, children: [
@@ -3219,6 +3338,15 @@ const SkillsListPanel = ({
3219
3338
  };
3220
3339
  const handleRefresh = async () => {
3221
3340
  setIsRefreshing(true);
3341
+ if (events) {
3342
+ events.emit({
3343
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3344
+ type: "skills:refresh",
3345
+ source: "skills-list-panel",
3346
+ timestamp: Date.now(),
3347
+ payload: {}
3348
+ });
3349
+ }
3222
3350
  try {
3223
3351
  await refreshSkills();
3224
3352
  } finally {
@@ -47723,6 +47851,325 @@ var DocumentView = ({
47723
47851
  editable
47724
47852
  })));
47725
47853
  };
47854
+ function extractHeaders(markdown2) {
47855
+ const headerRegex = /^(#{1,6})\s+(.+)$/gm;
47856
+ const headers = [];
47857
+ let match;
47858
+ while ((match = headerRegex.exec(markdown2)) !== null) {
47859
+ const level = match[1].length;
47860
+ const text2 = match[2].trim();
47861
+ const id = text2.toLowerCase().replace(/\s+/g, "-").replace(/[^\w-]/g, "");
47862
+ headers.push({ level, text: text2, id });
47863
+ }
47864
+ return headers;
47865
+ }
47866
+ const TableOfContents = ({
47867
+ headers,
47868
+ theme: theme2,
47869
+ className = "",
47870
+ onHeaderClick
47871
+ }) => {
47872
+ const [activeId, setActiveId] = React2__default.useState(null);
47873
+ const handleClick = (header) => {
47874
+ setActiveId(header.id);
47875
+ onHeaderClick == null ? void 0 : onHeaderClick(header);
47876
+ const element2 = document.getElementById(header.id);
47877
+ if (element2) {
47878
+ element2.scrollIntoView({ behavior: "smooth", block: "start" });
47879
+ }
47880
+ };
47881
+ if (headers.length === 0) {
47882
+ return null;
47883
+ }
47884
+ return /* @__PURE__ */ jsx(
47885
+ "nav",
47886
+ {
47887
+ className,
47888
+ style: {
47889
+ flex: 1,
47890
+ overflowY: "auto",
47891
+ minHeight: 0,
47892
+ padding: theme2.space[3]
47893
+ },
47894
+ children: /* @__PURE__ */ jsx(
47895
+ "ul",
47896
+ {
47897
+ style: {
47898
+ listStyle: "none",
47899
+ margin: 0,
47900
+ padding: 0
47901
+ },
47902
+ children: headers.map((header, index2) => {
47903
+ const isActive = activeId === header.id;
47904
+ const indentLevel = Math.max(0, header.level - 1);
47905
+ return /* @__PURE__ */ jsx(
47906
+ "li",
47907
+ {
47908
+ style: {
47909
+ marginBottom: theme2.space[1],
47910
+ marginLeft: `${indentLevel * 20}px`
47911
+ },
47912
+ children: /* @__PURE__ */ jsx(
47913
+ "button",
47914
+ {
47915
+ onClick: () => handleClick(header),
47916
+ style: {
47917
+ display: "block",
47918
+ width: "100%",
47919
+ textAlign: "left",
47920
+ background: "none",
47921
+ border: "none",
47922
+ padding: `${theme2.space[1]} ${theme2.space[2]}`,
47923
+ fontSize: header.level === 1 ? theme2.fontSizes[2] : header.level === 2 ? theme2.fontSizes[1] : theme2.fontSizes[0],
47924
+ fontFamily: theme2.fonts.body,
47925
+ color: isActive ? theme2.colors.primary : theme2.colors.text,
47926
+ cursor: "pointer",
47927
+ borderRadius: "4px",
47928
+ transition: "all 0.2s",
47929
+ fontWeight: isActive ? 600 : header.level === 1 ? 600 : header.level === 2 ? 500 : 400,
47930
+ backgroundColor: isActive ? `${theme2.colors.primary}15` : "transparent",
47931
+ borderLeft: isActive ? `2px solid ${theme2.colors.primary}` : "2px solid transparent",
47932
+ opacity: header.level > 3 ? 0.8 : 1
47933
+ },
47934
+ onMouseEnter: (e) => {
47935
+ if (!isActive) {
47936
+ e.currentTarget.style.backgroundColor = `${theme2.colors.border}50`;
47937
+ }
47938
+ },
47939
+ onMouseLeave: (e) => {
47940
+ if (!isActive) {
47941
+ e.currentTarget.style.backgroundColor = "transparent";
47942
+ }
47943
+ },
47944
+ children: header.text
47945
+ }
47946
+ )
47947
+ },
47948
+ `${header.id}-${index2}`
47949
+ );
47950
+ })
47951
+ }
47952
+ )
47953
+ }
47954
+ );
47955
+ };
47956
+ const SkillSidebar = ({
47957
+ headers,
47958
+ metadata,
47959
+ theme: theme2,
47960
+ className = "",
47961
+ onHeaderClick
47962
+ }) => {
47963
+ const [activeTab, setActiveTab] = React2__default.useState("toc");
47964
+ const hasMetadata = metadata.compatibility || metadata["allowed-tools"] && metadata["allowed-tools"].length > 0 || metadata.metadata && Object.keys(metadata.metadata).length > 0;
47965
+ React2__default.useEffect(() => {
47966
+ if (headers.length === 0 && hasMetadata) {
47967
+ setActiveTab("metadata");
47968
+ }
47969
+ }, [headers.length, hasMetadata]);
47970
+ if (headers.length === 0 && !hasMetadata) {
47971
+ return null;
47972
+ }
47973
+ return /* @__PURE__ */ jsxs(
47974
+ "div",
47975
+ {
47976
+ className,
47977
+ style: {
47978
+ width: "250px",
47979
+ flexShrink: 0,
47980
+ display: "flex",
47981
+ flexDirection: "column",
47982
+ borderRight: `1px solid ${theme2.colors.border}`
47983
+ },
47984
+ children: [
47985
+ /* @__PURE__ */ jsxs(
47986
+ "div",
47987
+ {
47988
+ style: {
47989
+ display: "flex",
47990
+ borderBottom: `1px solid ${theme2.colors.border}`,
47991
+ backgroundColor: theme2.colors.background
47992
+ },
47993
+ children: [
47994
+ headers.length > 0 && /* @__PURE__ */ jsx(
47995
+ "button",
47996
+ {
47997
+ onClick: () => setActiveTab("toc"),
47998
+ style: {
47999
+ flex: 1,
48000
+ padding: theme2.space[2],
48001
+ background: activeTab === "toc" ? theme2.colors.background : "transparent",
48002
+ border: "none",
48003
+ borderBottom: activeTab === "toc" ? `2px solid ${theme2.colors.primary}` : "2px solid transparent",
48004
+ color: activeTab === "toc" ? theme2.colors.primary : theme2.colors.textSecondary,
48005
+ fontFamily: theme2.fonts.heading,
48006
+ fontSize: theme2.fontSizes[1],
48007
+ fontWeight: activeTab === "toc" ? 600 : 500,
48008
+ cursor: "pointer",
48009
+ transition: "all 0.2s"
48010
+ },
48011
+ onMouseEnter: (e) => {
48012
+ if (activeTab !== "toc") {
48013
+ e.currentTarget.style.color = theme2.colors.text;
48014
+ }
48015
+ },
48016
+ onMouseLeave: (e) => {
48017
+ if (activeTab !== "toc") {
48018
+ e.currentTarget.style.color = theme2.colors.textSecondary;
48019
+ }
48020
+ },
48021
+ children: "Contents"
48022
+ }
48023
+ ),
48024
+ hasMetadata && /* @__PURE__ */ jsx(
48025
+ "button",
48026
+ {
48027
+ onClick: () => setActiveTab("metadata"),
48028
+ style: {
48029
+ flex: 1,
48030
+ padding: theme2.space[2],
48031
+ background: activeTab === "metadata" ? theme2.colors.background : "transparent",
48032
+ border: "none",
48033
+ borderBottom: activeTab === "metadata" ? `2px solid ${theme2.colors.primary}` : "2px solid transparent",
48034
+ color: activeTab === "metadata" ? theme2.colors.primary : theme2.colors.textSecondary,
48035
+ fontFamily: theme2.fonts.heading,
48036
+ fontSize: theme2.fontSizes[1],
48037
+ fontWeight: activeTab === "metadata" ? 600 : 500,
48038
+ cursor: "pointer",
48039
+ transition: "all 0.2s"
48040
+ },
48041
+ onMouseEnter: (e) => {
48042
+ if (activeTab !== "metadata") {
48043
+ e.currentTarget.style.color = theme2.colors.text;
48044
+ }
48045
+ },
48046
+ onMouseLeave: (e) => {
48047
+ if (activeTab !== "metadata") {
48048
+ e.currentTarget.style.color = theme2.colors.textSecondary;
48049
+ }
48050
+ },
48051
+ children: "Metadata"
48052
+ }
48053
+ )
48054
+ ]
48055
+ }
48056
+ ),
48057
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, overflowY: "auto", minHeight: 0 }, children: [
48058
+ activeTab === "toc" && headers.length > 0 && /* @__PURE__ */ jsx(
48059
+ TableOfContents,
48060
+ {
48061
+ headers,
48062
+ theme: theme2,
48063
+ onHeaderClick
48064
+ }
48065
+ ),
48066
+ activeTab === "metadata" && hasMetadata && /* @__PURE__ */ jsxs("div", { style: { padding: theme2.space[3] }, children: [
48067
+ metadata.compatibility && /* @__PURE__ */ jsxs("div", { style: { marginBottom: theme2.space[3] }, children: [
48068
+ /* @__PURE__ */ jsx(
48069
+ "div",
48070
+ {
48071
+ style: {
48072
+ fontFamily: theme2.fonts.heading,
48073
+ fontWeight: 600,
48074
+ fontSize: theme2.fontSizes[0],
48075
+ textTransform: "uppercase",
48076
+ letterSpacing: "0.5px",
48077
+ color: theme2.colors.textSecondary,
48078
+ marginBottom: theme2.space[1]
48079
+ },
48080
+ children: "Compatibility"
48081
+ }
48082
+ ),
48083
+ /* @__PURE__ */ jsx("div", { style: { fontSize: theme2.fontSizes[1], color: theme2.colors.text, fontFamily: theme2.fonts.body }, children: metadata.compatibility })
48084
+ ] }),
48085
+ metadata["allowed-tools"] && metadata["allowed-tools"].length > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: theme2.space[3] }, children: [
48086
+ /* @__PURE__ */ jsx(
48087
+ "div",
48088
+ {
48089
+ style: {
48090
+ fontFamily: theme2.fonts.heading,
48091
+ fontWeight: 600,
48092
+ fontSize: theme2.fontSizes[0],
48093
+ textTransform: "uppercase",
48094
+ letterSpacing: "0.5px",
48095
+ color: theme2.colors.textSecondary,
48096
+ marginBottom: theme2.space[1]
48097
+ },
48098
+ children: "Allowed Tools"
48099
+ }
48100
+ ),
48101
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: theme2.space[1] }, children: metadata["allowed-tools"].map((tool, index2) => /* @__PURE__ */ jsx(
48102
+ "span",
48103
+ {
48104
+ style: {
48105
+ display: "inline-block",
48106
+ paddingTop: theme2.space[2],
48107
+ paddingBottom: theme2.space[2],
48108
+ paddingLeft: theme2.space[3],
48109
+ paddingRight: theme2.space[3],
48110
+ background: theme2.colors.primary,
48111
+ color: theme2.colors.background,
48112
+ borderRadius: "4px",
48113
+ fontSize: theme2.fontSizes[0],
48114
+ fontWeight: 500,
48115
+ fontFamily: theme2.fonts.monospace
48116
+ },
48117
+ children: tool
48118
+ },
48119
+ index2
48120
+ )) })
48121
+ ] }),
48122
+ metadata.metadata && Object.keys(metadata.metadata).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48123
+ /* @__PURE__ */ jsx(
48124
+ "div",
48125
+ {
48126
+ style: {
48127
+ fontFamily: theme2.fonts.heading,
48128
+ fontWeight: 600,
48129
+ fontSize: theme2.fontSizes[0],
48130
+ textTransform: "uppercase",
48131
+ letterSpacing: "0.5px",
48132
+ color: theme2.colors.textSecondary,
48133
+ marginBottom: theme2.space[1]
48134
+ },
48135
+ children: "Metadata"
48136
+ }
48137
+ ),
48138
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: theme2.space[1] }, children: Object.entries(metadata.metadata).filter(([key]) => key !== "last-updated").map(([key, value]) => /* @__PURE__ */ jsxs("div", { children: [
48139
+ /* @__PURE__ */ jsxs(
48140
+ "div",
48141
+ {
48142
+ style: {
48143
+ fontSize: theme2.fontSizes[0],
48144
+ fontWeight: 600,
48145
+ color: theme2.colors.textSecondary,
48146
+ fontFamily: theme2.fonts.body
48147
+ },
48148
+ children: [
48149
+ key,
48150
+ ":"
48151
+ ]
48152
+ }
48153
+ ),
48154
+ /* @__PURE__ */ jsx(
48155
+ "div",
48156
+ {
48157
+ style: {
48158
+ fontSize: theme2.fontSizes[1],
48159
+ color: theme2.colors.text,
48160
+ fontFamily: theme2.fonts.monospace
48161
+ },
48162
+ children: value
48163
+ }
48164
+ )
48165
+ ] }, key)) })
48166
+ ] })
48167
+ ] })
48168
+ ] })
48169
+ ]
48170
+ }
48171
+ );
48172
+ };
47726
48173
  const formatRelativeTime = (dateString) => {
47727
48174
  try {
47728
48175
  const date = new Date(dateString);
@@ -47746,10 +48193,60 @@ const formatRelativeTime = (dateString) => {
47746
48193
  return dateString;
47747
48194
  }
47748
48195
  };
48196
+ const getSourceConfig = (source2) => {
48197
+ switch (source2) {
48198
+ case "global-universal":
48199
+ return {
48200
+ label: "Global",
48201
+ icon: Globe,
48202
+ color: "#7c3aed",
48203
+ // purple
48204
+ bgColor: "#7c3aed15",
48205
+ borderColor: "#7c3aed30"
48206
+ };
48207
+ case "global-claude":
48208
+ return {
48209
+ label: "Global Claude",
48210
+ icon: Globe,
48211
+ color: "#0891b2",
48212
+ // cyan
48213
+ bgColor: "#0891b215",
48214
+ borderColor: "#0891b230"
48215
+ };
48216
+ case "project-universal":
48217
+ return {
48218
+ label: "Project",
48219
+ icon: Folder,
48220
+ color: "#16a34a",
48221
+ // green
48222
+ bgColor: "#16a34a15",
48223
+ borderColor: "#16a34a30"
48224
+ };
48225
+ case "project-claude":
48226
+ return {
48227
+ label: "Project Claude",
48228
+ icon: Folder,
48229
+ color: "#0284c7",
48230
+ // blue
48231
+ bgColor: "#0284c715",
48232
+ borderColor: "#0284c730"
48233
+ };
48234
+ case "project-other":
48235
+ return {
48236
+ label: "Project",
48237
+ icon: Folder,
48238
+ color: "#64748b",
48239
+ // slate
48240
+ bgColor: "#64748b15",
48241
+ borderColor: "#64748b30"
48242
+ };
48243
+ }
48244
+ };
47749
48245
  const SkillMetadataSection = ({
47750
48246
  metadata,
47751
48247
  theme: theme2,
47752
- structure
48248
+ structure,
48249
+ skill
47753
48250
  }) => {
47754
48251
  var _a, _b, _c, _d, _e2;
47755
48252
  const [expandedSections, setExpandedSections] = React2__default.useState({
@@ -48026,6 +48523,110 @@ const SkillMetadataSection = ({
48026
48523
  file
48027
48524
  ] }, idx)) })
48028
48525
  ] })
48526
+ ] }),
48527
+ (skill == null ? void 0 : skill.installedLocations) && skill.installedLocations.length > 1 && /* @__PURE__ */ jsxs("div", { style: {
48528
+ marginTop: theme2.space[3],
48529
+ paddingTop: theme2.space[3],
48530
+ borderTop: `1px solid ${theme2.colors.border}`
48531
+ }, children: [
48532
+ /* @__PURE__ */ jsxs("div", { style: {
48533
+ fontSize: theme2.fontSizes[1],
48534
+ fontWeight: 600,
48535
+ color: theme2.colors.text,
48536
+ marginBottom: theme2.space[2],
48537
+ fontFamily: theme2.fonts.heading
48538
+ }, children: [
48539
+ "Installed Locations (",
48540
+ skill.installedLocations.length,
48541
+ ")"
48542
+ ] }),
48543
+ /* @__PURE__ */ jsx("div", { style: {
48544
+ display: "flex",
48545
+ flexDirection: "column",
48546
+ gap: theme2.space[2]
48547
+ }, children: skill.installedLocations.map((location2, idx) => {
48548
+ var _a2, _b2, _c2;
48549
+ const isPrimary = location2.path === skill.path;
48550
+ const sourceConfig = getSourceConfig(location2.source);
48551
+ return /* @__PURE__ */ jsxs(
48552
+ "div",
48553
+ {
48554
+ style: {
48555
+ padding: theme2.space[2],
48556
+ backgroundColor: isPrimary ? `${theme2.colors.primary}08` : theme2.colors.backgroundSecondary,
48557
+ borderRadius: "6px",
48558
+ border: `1px solid ${isPrimary ? theme2.colors.primary + "40" : theme2.colors.border}`,
48559
+ display: "flex",
48560
+ flexDirection: "column",
48561
+ gap: theme2.space[1]
48562
+ },
48563
+ children: [
48564
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: theme2.space[2] }, children: [
48565
+ /* @__PURE__ */ jsxs(
48566
+ "div",
48567
+ {
48568
+ style: {
48569
+ display: "inline-flex",
48570
+ alignItems: "center",
48571
+ gap: "4px",
48572
+ padding: "2px 6px",
48573
+ borderRadius: theme2.radii[1],
48574
+ backgroundColor: sourceConfig.bgColor,
48575
+ border: `1px solid ${sourceConfig.borderColor}`,
48576
+ fontSize: theme2.fontSizes[0],
48577
+ color: sourceConfig.color,
48578
+ fontWeight: 500
48579
+ },
48580
+ children: [
48581
+ /* @__PURE__ */ jsx(sourceConfig.icon, { size: 10 }),
48582
+ /* @__PURE__ */ jsx("span", { children: sourceConfig.label })
48583
+ ]
48584
+ }
48585
+ ),
48586
+ isPrimary && /* @__PURE__ */ jsx("span", { style: {
48587
+ fontSize: theme2.fontSizes[0],
48588
+ color: theme2.colors.primary,
48589
+ fontWeight: 600,
48590
+ fontFamily: theme2.fonts.body
48591
+ }, children: "(Active)" })
48592
+ ] }),
48593
+ /* @__PURE__ */ jsx("div", { style: {
48594
+ fontSize: theme2.fontSizes[0],
48595
+ color: theme2.colors.textSecondary,
48596
+ fontFamily: theme2.fonts.monospace,
48597
+ overflow: "hidden",
48598
+ textOverflow: "ellipsis",
48599
+ whiteSpace: "nowrap"
48600
+ }, children: location2.path }),
48601
+ ((_a2 = location2.metadata) == null ? void 0 : _a2.installedAt) && /* @__PURE__ */ jsxs("div", { style: {
48602
+ fontSize: theme2.fontSizes[0],
48603
+ color: theme2.colors.textMuted,
48604
+ fontFamily: theme2.fonts.body
48605
+ }, children: [
48606
+ "Installed: ",
48607
+ formatRelativeTime(location2.metadata.installedAt)
48608
+ ] }),
48609
+ ((_b2 = location2.metadata) == null ? void 0 : _b2.sha) && ((_c2 = skill.metadata) == null ? void 0 : _c2.sha) && location2.metadata.sha !== skill.metadata.sha && /* @__PURE__ */ jsxs("div", { style: {
48610
+ fontSize: theme2.fontSizes[0],
48611
+ color: "#f59e0b",
48612
+ // warning color
48613
+ fontFamily: theme2.fonts.monospace,
48614
+ display: "flex",
48615
+ alignItems: "center",
48616
+ gap: "4px"
48617
+ }, children: [
48618
+ /* @__PURE__ */ jsx(TriangleAlert, { size: 10 }),
48619
+ /* @__PURE__ */ jsxs("span", { children: [
48620
+ "Different version (SHA: ",
48621
+ location2.metadata.sha.substring(0, 7),
48622
+ ")"
48623
+ ] })
48624
+ ] })
48625
+ ]
48626
+ },
48627
+ idx
48628
+ );
48629
+ }) })
48029
48630
  ] })
48030
48631
  ] });
48031
48632
  };
@@ -48037,16 +48638,20 @@ const SkillMarkdown = ({
48037
48638
  onWarnings,
48038
48639
  showRawOnError = false,
48039
48640
  containerWidth,
48040
- structure
48641
+ structure,
48642
+ skill
48041
48643
  }) => {
48042
48644
  const [parsed, setParsed] = React2__default.useState(null);
48645
+ const [headers, setHeaders] = React2__default.useState([]);
48043
48646
  React2__default.useEffect(() => {
48044
- const skill = parseSkillMarkdownGraceful(content2);
48045
- setParsed(skill);
48046
- onParsed == null ? void 0 : onParsed(skill);
48047
- if (skill.warnings.length > 0) {
48048
- onWarnings == null ? void 0 : onWarnings(skill.warnings);
48049
- }
48647
+ const skill2 = parseSkillMarkdownGraceful(content2);
48648
+ setParsed(skill2);
48649
+ onParsed == null ? void 0 : onParsed(skill2);
48650
+ if (skill2.warnings.length > 0) {
48651
+ onWarnings == null ? void 0 : onWarnings(skill2.warnings);
48652
+ }
48653
+ const extractedHeaders = extractHeaders(skill2.body);
48654
+ setHeaders(extractedHeaders);
48050
48655
  }, [content2, onParsed, onWarnings]);
48051
48656
  if (!theme2 || !theme2.space) {
48052
48657
  return /* @__PURE__ */ jsx("div", { className, style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsx("div", { style: { padding: "2rem", textAlign: "center", color: "#856404" }, children: "Error: Theme not available. Wrap component in ThemeProvider." }) });
@@ -48083,9 +48688,17 @@ const SkillMarkdown = ({
48083
48688
  background: theme2.colors.background
48084
48689
  },
48085
48690
  children: [
48086
- /* @__PURE__ */ jsx("div", { style: { padding: theme2.space[3], paddingBottom: 0 }, children: /* @__PURE__ */ jsx(SkillMetadataSection, { metadata: parsed.metadata, theme: theme2, structure }) }),
48087
- /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "auto", padding: theme2.space[3], paddingTop: 0 }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: theme2.space[4], alignItems: "flex-start" }, children: [
48088
- /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx(
48691
+ /* @__PURE__ */ jsx("div", { style: { padding: theme2.space[3], paddingBottom: 0 }, children: /* @__PURE__ */ jsx(SkillMetadataSection, { metadata: parsed.metadata, theme: theme2, structure, skill }) }),
48692
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, display: "flex", overflow: "hidden" }, children: [
48693
+ /* @__PURE__ */ jsx(
48694
+ SkillSidebar,
48695
+ {
48696
+ headers,
48697
+ metadata: parsed.metadata,
48698
+ theme: theme2
48699
+ }
48700
+ ),
48701
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "auto", padding: theme2.space[3], paddingTop: 0 }, children: /* @__PURE__ */ jsx(
48089
48702
  IndustryMarkdownSlide,
48090
48703
  {
48091
48704
  content: parsed.body,
@@ -48095,123 +48708,8 @@ const SkillMarkdown = ({
48095
48708
  isVisible: true,
48096
48709
  containerWidth
48097
48710
  }
48098
- ) }),
48099
- (parsed.metadata.compatibility || parsed.metadata["allowed-tools"] || parsed.metadata.metadata) && /* @__PURE__ */ jsxs(
48100
- "div",
48101
- {
48102
- style: {
48103
- width: "300px",
48104
- flexShrink: 0,
48105
- padding: theme2.space[3],
48106
- background: theme2.colors.background,
48107
- position: "sticky",
48108
- top: theme2.space[3]
48109
- },
48110
- children: [
48111
- parsed.metadata.compatibility && /* @__PURE__ */ jsxs("div", { style: { marginBottom: theme2.space[3] }, children: [
48112
- /* @__PURE__ */ jsx(
48113
- "div",
48114
- {
48115
- style: {
48116
- fontFamily: theme2.fonts.heading,
48117
- fontWeight: 600,
48118
- fontSize: theme2.fontSizes[0],
48119
- textTransform: "uppercase",
48120
- letterSpacing: "0.5px",
48121
- color: theme2.colors.textSecondary,
48122
- marginBottom: theme2.space[1]
48123
- },
48124
- children: "Compatibility"
48125
- }
48126
- ),
48127
- /* @__PURE__ */ jsx("div", { style: { fontSize: theme2.fontSizes[1], color: theme2.colors.text, fontFamily: theme2.fonts.body }, children: parsed.metadata.compatibility })
48128
- ] }),
48129
- parsed.metadata["allowed-tools"] && parsed.metadata["allowed-tools"].length > 0 && /* @__PURE__ */ jsxs("div", { style: { marginBottom: theme2.space[3] }, children: [
48130
- /* @__PURE__ */ jsx(
48131
- "div",
48132
- {
48133
- style: {
48134
- fontFamily: theme2.fonts.heading,
48135
- fontWeight: 600,
48136
- fontSize: theme2.fontSizes[0],
48137
- textTransform: "uppercase",
48138
- letterSpacing: "0.5px",
48139
- color: theme2.colors.textSecondary,
48140
- marginBottom: theme2.space[1]
48141
- },
48142
- children: "Allowed Tools"
48143
- }
48144
- ),
48145
- /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: theme2.space[1] }, children: parsed.metadata["allowed-tools"].map((tool, index2) => /* @__PURE__ */ jsx(
48146
- "span",
48147
- {
48148
- style: {
48149
- display: "inline-block",
48150
- paddingTop: theme2.space[2],
48151
- paddingBottom: theme2.space[2],
48152
- paddingLeft: theme2.space[3],
48153
- paddingRight: theme2.space[3],
48154
- background: theme2.colors.primary,
48155
- color: theme2.colors.background,
48156
- borderRadius: "4px",
48157
- fontSize: theme2.fontSizes[0],
48158
- fontWeight: 500,
48159
- fontFamily: theme2.fonts.monospace
48160
- },
48161
- children: tool
48162
- },
48163
- index2
48164
- )) })
48165
- ] }),
48166
- parsed.metadata.metadata && Object.keys(parsed.metadata.metadata).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
48167
- /* @__PURE__ */ jsx(
48168
- "div",
48169
- {
48170
- style: {
48171
- fontFamily: theme2.fonts.heading,
48172
- fontWeight: 600,
48173
- fontSize: theme2.fontSizes[0],
48174
- textTransform: "uppercase",
48175
- letterSpacing: "0.5px",
48176
- color: theme2.colors.textSecondary,
48177
- marginBottom: theme2.space[1]
48178
- },
48179
- children: "Metadata"
48180
- }
48181
- ),
48182
- /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: theme2.space[1] }, children: Object.entries(parsed.metadata.metadata).filter(([key]) => key !== "last-updated").map(([key, value]) => /* @__PURE__ */ jsxs("div", { children: [
48183
- /* @__PURE__ */ jsxs(
48184
- "div",
48185
- {
48186
- style: {
48187
- fontSize: theme2.fontSizes[0],
48188
- fontWeight: 600,
48189
- color: theme2.colors.textSecondary,
48190
- fontFamily: theme2.fonts.body
48191
- },
48192
- children: [
48193
- key,
48194
- ":"
48195
- ]
48196
- }
48197
- ),
48198
- /* @__PURE__ */ jsx(
48199
- "div",
48200
- {
48201
- style: {
48202
- fontSize: theme2.fontSizes[1],
48203
- color: theme2.colors.text,
48204
- fontFamily: theme2.fonts.monospace
48205
- },
48206
- children: value
48207
- }
48208
- )
48209
- ] }, key)) })
48210
- ] })
48211
- ]
48212
- }
48213
- )
48214
- ] }) })
48711
+ ) })
48712
+ ] })
48215
48713
  ]
48216
48714
  }
48217
48715
  );
@@ -48366,7 +48864,8 @@ const SkillDetailPanel = ({
48366
48864
  scriptFiles: skill.scriptFiles,
48367
48865
  referenceFiles: skill.referenceFiles,
48368
48866
  assetFiles: skill.assetFiles
48369
- }
48867
+ },
48868
+ skill
48370
48869
  }
48371
48870
  ) }) }) : /* @__PURE__ */ jsx(
48372
48871
  "div",