@julianpedro/plugin-dev-ai-hub 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/api/DevAiHubClient.esm.js +10 -2
  2. package/dist/api/DevAiHubClient.esm.js.map +1 -1
  3. package/dist/components/AssetCard/AssetCard.esm.js +85 -13
  4. package/dist/components/AssetCard/AssetCard.esm.js.map +1 -1
  5. package/dist/components/AssetDetailPanel/AssetDetailPanel.esm.js +272 -85
  6. package/dist/components/AssetDetailPanel/AssetDetailPanel.esm.js.map +1 -1
  7. package/dist/components/AssetFilters/AssetFilters.esm.js +103 -44
  8. package/dist/components/AssetFilters/AssetFilters.esm.js.map +1 -1
  9. package/dist/components/AssetHelpDialog/AssetHelpDialog.esm.js +87 -0
  10. package/dist/components/AssetHelpDialog/AssetHelpDialog.esm.js.map +1 -0
  11. package/dist/components/AssetInstallDialog/AssetInstallDialog.esm.js +328 -108
  12. package/dist/components/AssetInstallDialog/AssetInstallDialog.esm.js.map +1 -1
  13. package/dist/components/DevAiHubPage/DevAiHubPage.esm.js +93 -44
  14. package/dist/components/DevAiHubPage/DevAiHubPage.esm.js.map +1 -1
  15. package/dist/components/McpConfigDialog/McpConfigDialog.esm.js +535 -234
  16. package/dist/components/McpConfigDialog/McpConfigDialog.esm.js.map +1 -1
  17. package/dist/components/ToolIcon/ToolIcon.esm.js +4 -1
  18. package/dist/components/ToolIcon/ToolIcon.esm.js.map +1 -1
  19. package/dist/hooks/index.esm.js +15 -1
  20. package/dist/hooks/index.esm.js.map +1 -1
  21. package/dist/index.d.ts +6 -3
  22. package/dist/index.esm.js +1 -0
  23. package/dist/index.esm.js.map +1 -1
  24. package/dist/locales/es.esm.js +112 -0
  25. package/dist/locales/es.esm.js.map +1 -0
  26. package/dist/locales/pt-BR.esm.js +112 -0
  27. package/dist/locales/pt-BR.esm.js.map +1 -0
  28. package/dist/translation.esm.js +135 -0
  29. package/dist/translation.esm.js.map +1 -0
  30. package/package.json +2 -2
@@ -1,10 +1,11 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useState } from 'react';
2
+ import { useState, useEffect } from 'react';
3
3
  import { useTheme } from '@mui/material/styles';
4
4
  import ReactMarkdown from 'react-markdown';
5
5
  import remarkGfm from 'remark-gfm';
6
6
  import Alert from '@mui/material/Alert';
7
7
  import Box from '@mui/material/Box';
8
+ import Collapse from '@mui/material/Collapse';
8
9
  import Button from '@mui/material/Button';
9
10
  import Chip from '@mui/material/Chip';
10
11
  import CircularProgress from '@mui/material/CircularProgress';
@@ -18,28 +19,49 @@ import Tabs from '@mui/material/Tabs';
18
19
  import Typography from '@mui/material/Typography';
19
20
  import CloseIcon from '@mui/icons-material/Close';
20
21
  import ContentCopyIcon from '@mui/icons-material/ContentCopy';
22
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
21
23
  import FolderZipIcon from '@mui/icons-material/FolderZip';
22
24
  import OpenInNewIcon from '@mui/icons-material/OpenInNew';
25
+ import Inventory2Icon from '@mui/icons-material/Inventory2';
26
+ import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
23
27
  import { useAssetDetail } from '../../hooks/index.esm.js';
28
+ import { devAiHubTranslationRef } from '../../translation.esm.js';
24
29
 
25
30
  const SyntaxHighlighter = require("react-syntax-highlighter/dist/esm/prism").default;
26
31
  const { oneLight, oneDark } = require("react-syntax-highlighter/dist/esm/styles/prism");
32
+ function parseFrontmatter(md) {
33
+ const match = md.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
34
+ if (!match) return { meta: null, body: md };
35
+ const meta = {};
36
+ for (const line of match[1].split("\n")) {
37
+ const m = line.match(/^([^:#\s][^:]*?):\s*(.+)$/);
38
+ if (m) meta[m[1].trim()] = m[2].trim().replace(/^["']|["']$/g, "");
39
+ }
40
+ return { meta: Object.keys(meta).length > 0 ? meta : null, body: match[2].trimStart() };
41
+ }
27
42
  const TYPE_COLORS = {
28
43
  instruction: "#1976d2",
29
44
  agent: "#7b1fa2",
30
45
  skill: "#388e3c",
31
- workflow: "#f57c00"
46
+ workflow: "#f57c00",
47
+ bundle: "#8B5CF6"
32
48
  };
33
49
  function AssetDetailPanel({ assetId, onClose }) {
34
50
  const [tab, setTab] = useState(0);
35
51
  const [snackbar, setSnackbar] = useState(null);
52
+ const [frontmatterOpen, setFrontmatterOpen] = useState(false);
36
53
  const { asset, loading } = useAssetDetail(assetId);
37
54
  const theme = useTheme();
55
+ const { t } = useTranslationRef(devAiHubTranslationRef);
38
56
  const syntaxTheme = theme.palette.mode === "dark" ? oneDark : oneLight;
57
+ useEffect(() => {
58
+ setFrontmatterOpen(false);
59
+ }, [assetId]);
60
+ const parsed = asset ? parseFrontmatter(asset.content) : null;
39
61
  const handleCopy = () => {
40
62
  if (!asset) return;
41
63
  navigator.clipboard.writeText(asset.content).then(
42
- () => setSnackbar("Markdown copied to clipboard!")
64
+ () => setSnackbar(t("assetDetailPanel.copiedMessage"))
43
65
  );
44
66
  };
45
67
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -65,18 +87,20 @@ function AssetDetailPanel({ assetId, onClose }) {
65
87
  children: [
66
88
  /* @__PURE__ */ jsx(Box, { sx: { flex: 1 }, children: loading || !asset ? /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
67
89
  /* @__PURE__ */ jsx(CircularProgress, { size: 16 }),
68
- /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: "Loading..." })
90
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: t("assetDetailPanel.loading") })
69
91
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
70
92
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1, mb: 0.5 }, children: [
71
- /* @__PURE__ */ jsx(Typography, { variant: "h6", fontWeight: 700, children: asset.name }),
93
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", fontWeight: 700, children: asset.label ?? asset.name }),
72
94
  /* @__PURE__ */ jsx(
73
95
  Chip,
74
96
  {
75
97
  label: asset.type,
76
98
  size: "small",
77
99
  sx: {
78
- backgroundColor: `${TYPE_COLORS[asset.type]}20`,
100
+ backgroundColor: `${TYPE_COLORS[asset.type]}22`,
79
101
  color: TYPE_COLORS[asset.type],
102
+ border: "1px solid",
103
+ borderColor: `${TYPE_COLORS[asset.type]}55`,
80
104
  fontWeight: 600
81
105
  }
82
106
  }
@@ -95,104 +119,267 @@ function AssetDetailPanel({ assetId, onClose }) {
95
119
  onChange: (_, v) => setTab(v),
96
120
  sx: { borderBottom: 1, borderColor: "divider", px: 2 },
97
121
  children: [
98
- /* @__PURE__ */ jsx(Tab, { label: "Preview" }),
99
- /* @__PURE__ */ jsx(Tab, { label: "Metadata" }),
100
- /* @__PURE__ */ jsx(Tab, { label: "Raw YAML" })
122
+ /* @__PURE__ */ jsx(Tab, { label: t("assetDetailPanel.tabPreview") }),
123
+ /* @__PURE__ */ jsx(Tab, { label: t("assetDetailPanel.tabMetadata") }),
124
+ /* @__PURE__ */ jsx(Tab, { label: t("assetDetailPanel.tabRawYaml") })
101
125
  ]
102
126
  }
103
127
  ),
104
128
  /* @__PURE__ */ jsxs(Box, { sx: { flex: 1, overflow: "auto", p: 2 }, children: [
105
129
  loading && /* @__PURE__ */ jsx(Box, { sx: { display: "flex", justifyContent: "center", pt: 4 }, children: /* @__PURE__ */ jsx(CircularProgress, {}) }),
106
130
  !loading && asset && /* @__PURE__ */ jsxs(Fragment, { children: [
107
- tab === 0 && /* @__PURE__ */ jsx(
108
- Box,
109
- {
110
- sx: {
111
- "& h1,h2,h3,h4,h5,h6": { mt: 2, mb: 1, fontWeight: 700 },
112
- "& p": { mb: 1, lineHeight: 1.7 },
113
- "& ul, & ol": { pl: 2.5, mb: 1 },
114
- "& li": { mb: 0.5 },
115
- "& blockquote": {
116
- borderLeft: "3px solid",
117
- borderColor: "primary.main",
118
- pl: 1.5,
119
- color: "text.secondary",
120
- my: 1,
121
- ml: 0
122
- },
123
- "& table": { width: "100%", borderCollapse: "collapse", mb: 1 },
124
- "& th, & td": {
131
+ tab === 0 && asset.type === "bundle" && /* @__PURE__ */ jsxs(Box, { children: [
132
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.75, mb: 1.5 }, children: [
133
+ /* @__PURE__ */ jsx(Inventory2Icon, { sx: { fontSize: "1rem", color: "#8B5CF6" } }),
134
+ /* @__PURE__ */ jsx(Typography, { variant: "subtitle2", fontWeight: 600, color: "text.secondary", children: t("assetDetailPanel.bundlePreviewTitle", { count: asset.items?.length ?? 0 }) })
135
+ ] }),
136
+ asset.description && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: asset.description }),
137
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.75 }, children: (asset.items ?? []).map((item, idx) => /* @__PURE__ */ jsx(
138
+ Box,
139
+ {
140
+ sx: {
141
+ display: "flex",
142
+ alignItems: "center",
143
+ gap: 1.5,
144
+ p: 1.25,
145
+ borderRadius: 1.5,
125
146
  border: "1px solid",
126
147
  borderColor: "divider",
127
- px: 1.5,
128
- py: 0.75,
129
- fontSize: "0.875rem"
148
+ bgcolor: "action.hover"
130
149
  },
131
- "& th": { backgroundColor: "action.hover", fontWeight: 700 },
132
- "& code": {
133
- bgcolor: "action.hover",
134
- px: 0.5,
135
- py: 0.2,
136
- borderRadius: 0.5,
137
- fontFamily: "monospace",
138
- fontSize: "0.875em"
139
- },
140
- "& pre code": { bgcolor: "transparent", px: 0, py: 0 }
141
- },
142
- children: /* @__PURE__ */ jsx(
143
- ReactMarkdown,
144
- {
145
- remarkPlugins: [remarkGfm],
146
- components: {
147
- pre: ({ children }) => /* @__PURE__ */ jsx(Box, { sx: { my: 1 }, children }),
148
- code({ className, children }) {
149
- const match = /language-(\w+)/.exec(className || "");
150
- const code = String(children).replace(/\n$/, "");
151
- const isBlock = code.includes("\n") || !!match;
152
- return isBlock ? /* @__PURE__ */ jsx(
153
- SyntaxHighlighter,
154
- {
155
- style: syntaxTheme,
156
- language: match?.[1] ?? "text",
157
- PreTag: "div",
158
- customStyle: {
159
- borderRadius: 8,
160
- fontSize: "0.8rem",
161
- margin: 0,
162
- border: `1px solid ${theme.palette.divider}`
163
- },
164
- children: code
150
+ children: /* @__PURE__ */ jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [
151
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1, mb: item.description ? 0.25 : 0 }, children: [
152
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", fontWeight: 600, noWrap: true, title: item.label ?? item.name ?? item.ref ?? void 0, children: item.label ?? item.name ?? item.ref }),
153
+ item.type && /* @__PURE__ */ jsx(
154
+ Chip,
155
+ {
156
+ label: item.type,
157
+ size: "small",
158
+ sx: {
159
+ height: 18,
160
+ fontSize: "0.65rem",
161
+ bgcolor: `${TYPE_COLORS[item.type] ?? "#666"}22`,
162
+ color: TYPE_COLORS[item.type] ?? "text.secondary",
163
+ border: "1px solid",
164
+ borderColor: `${TYPE_COLORS[item.type] ?? "#666"}55`,
165
+ fontWeight: 600,
166
+ flexShrink: 0
165
167
  }
166
- ) : /* @__PURE__ */ jsx("code", { className, children });
168
+ }
169
+ )
170
+ ] }),
171
+ item.description && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", noWrap: true, title: item.description, children: item.description }),
172
+ !item.assetId && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", sx: { display: "block" }, children: t("assetDetailPanel.bundleItemNotSynced", { ref: item.ref }) })
173
+ ] })
174
+ },
175
+ idx
176
+ )) })
177
+ ] }),
178
+ tab === 0 && asset.type !== "bundle" && /* @__PURE__ */ jsxs(Box, { children: [
179
+ parsed?.meta && /* @__PURE__ */ jsxs(
180
+ Box,
181
+ {
182
+ sx: {
183
+ mb: 1.5,
184
+ border: "1px solid",
185
+ borderColor: "divider",
186
+ borderRadius: 1.5,
187
+ overflow: "hidden"
188
+ },
189
+ children: [
190
+ /* @__PURE__ */ jsxs(
191
+ Box,
192
+ {
193
+ onClick: () => setFrontmatterOpen((v) => !v),
194
+ sx: {
195
+ display: "flex",
196
+ alignItems: "center",
197
+ justifyContent: "space-between",
198
+ px: 1.5,
199
+ py: 0.75,
200
+ cursor: "pointer",
201
+ bgcolor: "action.hover",
202
+ userSelect: "none",
203
+ "&:hover": { bgcolor: "action.selected" }
204
+ },
205
+ children: [
206
+ /* @__PURE__ */ jsx(
207
+ Typography,
208
+ {
209
+ variant: "caption",
210
+ fontWeight: 700,
211
+ color: "text.secondary",
212
+ sx: { fontFamily: "monospace", textTransform: "uppercase", letterSpacing: 0.6 },
213
+ children: "frontmatter"
214
+ }
215
+ ),
216
+ /* @__PURE__ */ jsx(
217
+ ExpandMoreIcon,
218
+ {
219
+ sx: {
220
+ fontSize: "1rem",
221
+ color: "text.secondary",
222
+ transform: frontmatterOpen ? "rotate(180deg)" : "none",
223
+ transition: "transform 0.2s ease"
224
+ }
225
+ }
226
+ )
227
+ ]
167
228
  }
229
+ ),
230
+ /* @__PURE__ */ jsx(Collapse, { in: frontmatterOpen, children: /* @__PURE__ */ jsx(Box, { sx: { px: 1.5, py: 1, display: "flex", flexDirection: "column", gap: 0.5 }, children: Object.entries(parsed.meta).map(([key, value]) => /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", gap: 1, alignItems: "baseline" }, children: [
231
+ /* @__PURE__ */ jsxs(
232
+ Typography,
233
+ {
234
+ variant: "caption",
235
+ sx: { fontFamily: "monospace", color: "primary.main", fontWeight: 600, minWidth: 90, flexShrink: 0 },
236
+ children: [
237
+ key,
238
+ ":"
239
+ ]
240
+ }
241
+ ),
242
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { fontFamily: "monospace", wordBreak: "break-all" }, children: value })
243
+ ] }, key)) }) })
244
+ ]
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsx(
248
+ Box,
249
+ {
250
+ sx: {
251
+ "& h1,h2,h3,h4,h5,h6": { mt: 2, mb: 1, fontWeight: 700 },
252
+ "& p": { mb: 1, lineHeight: 1.7 },
253
+ "& ul, & ol": { pl: 2.5, mb: 1 },
254
+ "& li": { mb: 0.5 },
255
+ "& blockquote": {
256
+ borderLeft: "3px solid",
257
+ borderColor: "primary.main",
258
+ pl: 1.5,
259
+ color: "text.secondary",
260
+ my: 1,
261
+ ml: 0
168
262
  },
169
- children: asset.content
170
- }
171
- )
172
- }
173
- ),
263
+ "& table": { width: "100%", borderCollapse: "collapse", mb: 1 },
264
+ "& th, & td": {
265
+ border: "1px solid",
266
+ borderColor: "divider",
267
+ px: 1.5,
268
+ py: 0.75,
269
+ fontSize: "0.875rem"
270
+ },
271
+ "& th": { backgroundColor: "action.hover", fontWeight: 700 },
272
+ "& code": {
273
+ bgcolor: "action.hover",
274
+ px: 0.5,
275
+ py: 0.2,
276
+ borderRadius: 0.5,
277
+ fontFamily: "monospace",
278
+ fontSize: "0.875em"
279
+ },
280
+ "& pre code": { bgcolor: "transparent", px: 0, py: 0 }
281
+ },
282
+ children: /* @__PURE__ */ jsx(
283
+ ReactMarkdown,
284
+ {
285
+ remarkPlugins: [remarkGfm],
286
+ components: {
287
+ pre: ({ children }) => /* @__PURE__ */ jsx(Box, { sx: { my: 1 }, children }),
288
+ code({ className, children }) {
289
+ const match = /language-(\w+)/.exec(className || "");
290
+ const code = String(children).replace(/\n$/, "");
291
+ const isBlock = code.includes("\n") || !!match;
292
+ return isBlock ? /* @__PURE__ */ jsx(
293
+ SyntaxHighlighter,
294
+ {
295
+ style: syntaxTheme,
296
+ language: match?.[1] ?? "text",
297
+ PreTag: "div",
298
+ customStyle: {
299
+ borderRadius: 8,
300
+ fontSize: "0.8rem",
301
+ margin: 0,
302
+ border: `1px solid ${theme.palette.divider}`
303
+ },
304
+ children: code
305
+ }
306
+ ) : /* @__PURE__ */ jsx("code", { className, children });
307
+ }
308
+ },
309
+ children: parsed?.body ?? asset.content
310
+ }
311
+ )
312
+ }
313
+ )
314
+ ] }),
174
315
  tab === 1 && /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 2 }, children: [
175
- /* @__PURE__ */ jsx(MetaRow, { label: "Author", value: asset.author }),
176
- /* @__PURE__ */ jsx(MetaRow, { label: "Version", value: asset.version }),
177
- /* @__PURE__ */ jsx(MetaRow, { label: "Provider", value: asset.providerId }),
178
- asset.commitSha && /* @__PURE__ */ jsx(MetaRow, { label: "Commit", value: asset.commitSha.slice(0, 8) }),
179
- /* @__PURE__ */ jsx(MetaRow, { label: "Last synced", value: new Date(asset.syncedAt).toLocaleString() }),
180
- /* @__PURE__ */ jsx(MetaRow, { label: "Branch", value: asset.branch }),
316
+ /* @__PURE__ */ jsx(MetaRow, { label: t("assetDetailPanel.metaAuthor"), value: asset.author }),
317
+ /* @__PURE__ */ jsx(MetaRow, { label: t("assetDetailPanel.metaVersion"), value: asset.version }),
318
+ /* @__PURE__ */ jsx(MetaRow, { label: t("assetDetailPanel.metaProvider"), value: asset.providerId }),
319
+ asset.commitSha && /* @__PURE__ */ jsx(MetaRow, { label: t("assetDetailPanel.metaCommit"), value: asset.commitSha.slice(0, 8) }),
320
+ /* @__PURE__ */ jsx(MetaRow, { label: t("assetDetailPanel.metaLastSynced"), value: new Date(asset.syncedAt).toLocaleString() }),
321
+ /* @__PURE__ */ jsx(MetaRow, { label: t("assetDetailPanel.metaBranch"), value: asset.branch }),
181
322
  /* @__PURE__ */ jsx(Divider, {}),
182
323
  /* @__PURE__ */ jsxs(Box, { children: [
183
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: "Compatible tools" }),
184
- /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 1, mt: 0.5 }, children: asset.tools.map((t) => /* @__PURE__ */ jsx(Chip, { label: t, size: "small" }, t)) })
324
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("assetDetailPanel.compatibleTools") }),
325
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 1, mt: 0.5 }, children: asset.tools.map((tool) => /* @__PURE__ */ jsx(Chip, { label: tool, size: "small" }, tool)) })
185
326
  ] }),
186
327
  asset.tags.length > 0 && /* @__PURE__ */ jsxs(Box, { children: [
187
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: "Tags" }),
188
- /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap", mt: 0.5 }, children: asset.tags.map((t) => /* @__PURE__ */ jsx(Chip, { label: t, size: "small", variant: "outlined" }, t)) })
328
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("assetDetailPanel.tagsLabel") }),
329
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap", mt: 0.5 }, children: asset.tags.map((tag) => /* @__PURE__ */ jsx(Chip, { label: tag, size: "small", variant: "outlined" }, tag)) })
330
+ ] }),
331
+ asset.type === "bundle" && asset.items && asset.items.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
332
+ /* @__PURE__ */ jsx(Divider, {}),
333
+ /* @__PURE__ */ jsxs(Box, { children: [
334
+ /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.75, mb: 1 }, children: [
335
+ /* @__PURE__ */ jsx(Inventory2Icon, { sx: { fontSize: "0.85rem", color: "#8B5CF6" } }),
336
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", fontWeight: 600, children: t("assetDetailPanel.bundleContents", { count: asset.items.length }) })
337
+ ] }),
338
+ /* @__PURE__ */ jsx(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.75 }, children: asset.items.map((item, idx) => /* @__PURE__ */ jsx(
339
+ Box,
340
+ {
341
+ sx: {
342
+ display: "flex",
343
+ alignItems: "center",
344
+ gap: 1,
345
+ p: 1,
346
+ borderRadius: 1,
347
+ border: "1px solid",
348
+ borderColor: "divider",
349
+ bgcolor: "action.hover"
350
+ },
351
+ children: /* @__PURE__ */ jsxs(Box, { sx: { flex: 1, minWidth: 0 }, children: [
352
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", fontWeight: 600, noWrap: true, title: item.label ?? item.name ?? item.ref ?? void 0, children: item.label ?? item.name ?? item.ref }),
353
+ item.type && /* @__PURE__ */ jsx(
354
+ Chip,
355
+ {
356
+ label: item.type,
357
+ size: "small",
358
+ sx: {
359
+ height: 16,
360
+ fontSize: "0.6rem",
361
+ bgcolor: `${TYPE_COLORS[item.type] ?? "#666"}22`,
362
+ color: TYPE_COLORS[item.type] ?? "text.secondary",
363
+ border: "1px solid",
364
+ borderColor: `${TYPE_COLORS[item.type] ?? "#666"}55`,
365
+ fontWeight: 600,
366
+ mt: 0.25
367
+ }
368
+ }
369
+ ),
370
+ !item.assetId && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", sx: { display: "block" }, children: t("assetDetailPanel.bundleItemNotSyncedYet", { ref: item.ref }) })
371
+ ] })
372
+ },
373
+ idx
374
+ )) })
375
+ ] })
189
376
  ] }),
190
377
  asset.type === "skill" && /* @__PURE__ */ jsxs(Fragment, { children: [
191
378
  /* @__PURE__ */ jsx(Divider, {}),
192
379
  /* @__PURE__ */ jsxs(Box, { children: [
193
380
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 0.75, mb: 0.5 }, children: [
194
381
  /* @__PURE__ */ jsx(FolderZipIcon, { sx: { fontSize: "0.85rem", color: "text.secondary" } }),
195
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: "Bundled files" })
382
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("assetDetailPanel.bundledFiles") })
196
383
  ] }),
197
384
  asset.resourcesContent && Object.keys(asset.resourcesContent).length > 0 ? /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", flexDirection: "column", gap: 0.5, mt: 0.5 }, children: [
198
385
  /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap" }, children: [
@@ -215,7 +402,7 @@ function AssetDetailPanel({ assetId, onClose }) {
215
402
  p
216
403
  ))
217
404
  ] }),
218
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", children: "Downloads as .zip containing all files above." })
405
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.disabled", children: t("assetDetailPanel.zipDescription") })
219
406
  ] }) : /* @__PURE__ */ jsx(Box, { sx: { display: "flex", gap: 0.5, flexWrap: "wrap", mt: 0.5 }, children: /* @__PURE__ */ jsx(
220
407
  Chip,
221
408
  {
@@ -228,7 +415,7 @@ function AssetDetailPanel({ assetId, onClose }) {
228
415
  ] }),
229
416
  /* @__PURE__ */ jsx(Divider, {}),
230
417
  /* @__PURE__ */ jsxs(Box, { children: [
231
- /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: "Repository" }),
418
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("assetDetailPanel.repository") }),
232
419
  /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(
233
420
  Link,
234
421
  {
@@ -285,7 +472,7 @@ function AssetDetailPanel({ assetId, onClose }) {
285
472
  startIcon: /* @__PURE__ */ jsx(ContentCopyIcon, {}),
286
473
  onClick: handleCopy,
287
474
  disabled: !asset,
288
- children: "Copy Markdown"
475
+ children: t("assetDetailPanel.copyMarkdown")
289
476
  }
290
477
  ),
291
478
  /* @__PURE__ */ jsx(
@@ -295,7 +482,7 @@ function AssetDetailPanel({ assetId, onClose }) {
295
482
  startIcon: /* @__PURE__ */ jsx(OpenInNewIcon, {}),
296
483
  onClick: () => asset && window.open(asset.repoUrl, "_blank"),
297
484
  disabled: !asset,
298
- children: "Open in Repo"
485
+ children: t("assetDetailPanel.openInRepo")
299
486
  }
300
487
  )
301
488
  ]