@mastra/playground-ui 12.0.0 → 13.0.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 (50) hide show
  1. package/CHANGELOG.md +112 -0
  2. package/dist/index.cjs.js +2300 -811
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +2293 -813
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/domains/agents/components/agent-cms-form-shell.d.ts +2 -1
  7. package/dist/src/domains/agents/components/agent-cms-layout/agent-cms-layout.d.ts +2 -1
  8. package/dist/src/domains/agents/components/agent-cms-pages/index.d.ts +1 -0
  9. package/dist/src/domains/agents/components/agent-cms-pages/skill-edit-dialog.d.ts +8 -0
  10. package/dist/src/domains/agents/components/agent-cms-pages/skill-file-tree.d.ts +15 -0
  11. package/dist/src/domains/agents/components/agent-cms-pages/skill-folder.d.ts +14 -0
  12. package/dist/src/domains/agents/components/agent-cms-pages/skills-page.d.ts +1 -0
  13. package/dist/src/domains/agents/components/agent-cms-sidebar/use-sidebar-descriptions.d.ts +4 -0
  14. package/dist/src/domains/agents/components/agent-edit-page/use-agent-edit-form.d.ts +32 -0
  15. package/dist/src/domains/agents/components/agent-edit-page/utils/form-validation.d.ts +43 -0
  16. package/dist/src/domains/agents/components/agent-version-panel.d.ts +7 -0
  17. package/dist/src/domains/agents/hooks/use-agent-cms-form.d.ts +33 -0
  18. package/dist/src/domains/agents/hooks/use-agent-skills.d.ts +12 -0
  19. package/dist/src/domains/agents/hooks/use-agent-workspace.d.ts +13 -0
  20. package/dist/src/domains/agents/hooks/use-create-skill.d.ts +10 -0
  21. package/dist/src/domains/agents/hooks/use-stored-skills.d.ts +1 -0
  22. package/dist/src/domains/agents/index.d.ts +3 -0
  23. package/dist/src/domains/agents/utils/agent-form-mappers.d.ts +6 -1
  24. package/dist/src/domains/agents/utils/compute-agent-initial-values.d.ts +3 -0
  25. package/dist/src/domains/datasets/components/dataset-combobox.d.ts +11 -0
  26. package/dist/src/domains/datasets/hooks/use-dataset-item-versions.d.ts +1 -1
  27. package/dist/src/domains/datasets/index.d.ts +2 -0
  28. package/dist/src/domains/experiments/hooks/use-experiment-trace.d.ts +1 -1
  29. package/dist/src/domains/mcps/components/mcp-client-create/mcp-client-create-content.d.ts +7 -1
  30. package/dist/src/domains/mcps/components/mcp-client-create/mcp-client-form-sidebar.d.ts +2 -1
  31. package/dist/src/domains/mcps/components/mcp-client-create/mcp-client-tool-preview.d.ts +6 -1
  32. package/dist/src/ds/components/Breadcrumb/Breadcrumb.d.ts +1 -1
  33. package/dist/src/ds/components/CodeDiff/code-diff.d.ts +5 -0
  34. package/dist/src/ds/components/CodeDiff/code-diff.stories.d.ts +9 -0
  35. package/dist/src/ds/components/CodeDiff/index.d.ts +2 -0
  36. package/dist/src/ds/components/FormFields/select-field.d.ts +1 -0
  37. package/dist/src/ds/components/Tree/index.d.ts +1 -0
  38. package/dist/src/ds/components/Tree/tree-context.d.ts +15 -0
  39. package/dist/src/ds/components/Tree/tree-file.d.ts +7 -0
  40. package/dist/src/ds/components/Tree/tree-folder-content.d.ts +6 -0
  41. package/dist/src/ds/components/Tree/tree-folder-trigger.d.ts +7 -0
  42. package/dist/src/ds/components/Tree/tree-folder.d.ts +9 -0
  43. package/dist/src/ds/components/Tree/tree-icon.d.ts +6 -0
  44. package/dist/src/ds/components/Tree/tree-input.d.ts +11 -0
  45. package/dist/src/ds/components/Tree/tree-label.d.ts +6 -0
  46. package/dist/src/ds/components/Tree/tree-root.d.ts +8 -0
  47. package/dist/src/ds/components/Tree/tree.d.ts +9 -0
  48. package/dist/src/ds/components/Tree/tree.stories.d.ts +10 -0
  49. package/dist/src/index.d.ts +2 -0
  50. package/package.json +14 -13
package/dist/index.cjs.js CHANGED
@@ -72,14 +72,16 @@ const dnd = require('@hello-pangea/dnd');
72
72
  const SwitchPrimitives = require('@radix-ui/react-switch');
73
73
  const codemirrorThemeGithub = require('@uiw/codemirror-theme-github');
74
74
  const AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
75
+ const features = require('@mastra/core/features');
75
76
  const format = require('date-fns/format');
76
77
  const observability = require('@mastra/core/observability');
77
78
  const Papa = require('papaparse');
78
79
  const DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
79
80
  const reactDom = require('react-dom');
80
81
  const cmdk = require('cmdk');
82
+ const state = require('@codemirror/state');
83
+ const merge = require('@codemirror/merge');
81
84
  const reactSyntaxHighlighter$1 = require('react-syntax-highlighter');
82
- const features = require('@mastra/core/features');
83
85
  const compatibility = require('./compatibility-BSJHu6pD.cjs');
84
86
 
85
87
  function _interopNamespaceDefault(e) {
@@ -609,7 +611,7 @@ const fromTheme = key => {
609
611
  };
610
612
  const arbitraryValueRegex = /^\[(?:(\w[\w-]*):)?(.+)\]$/i;
611
613
  const arbitraryVariableRegex = /^\((?:(\w[\w-]*):)?(.+)\)$/i;
612
- const fractionRegex = /^\d+\/\d+$/;
614
+ const fractionRegex = /^\d+(?:\.\d+)?\/\d+(?:\.\d+)?$/;
613
615
  const tshirtUnitRegex = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/;
614
616
  const lengthUnitRegex = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/;
615
617
  const colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/;
@@ -635,6 +637,8 @@ const isArbitrarySize = value => getIsArbitraryValue(value, isLabelSize, isNever
635
637
  const isArbitraryValue = value => arbitraryValueRegex.test(value);
636
638
  const isArbitraryLength = value => getIsArbitraryValue(value, isLabelLength, isLengthOnly);
637
639
  const isArbitraryNumber = value => getIsArbitraryValue(value, isLabelNumber, isNumber);
640
+ const isArbitraryWeight = value => getIsArbitraryValue(value, isLabelWeight, isAny);
641
+ const isArbitraryFamilyName = value => getIsArbitraryValue(value, isLabelFamilyName, isNever);
638
642
  const isArbitraryPosition = value => getIsArbitraryValue(value, isLabelPosition, isNever);
639
643
  const isArbitraryImage = value => getIsArbitraryValue(value, isLabelImage, isImage);
640
644
  const isArbitraryShadow = value => getIsArbitraryValue(value, isLabelShadow, isShadow);
@@ -645,6 +649,7 @@ const isArbitraryVariablePosition = value => getIsArbitraryVariable(value, isLab
645
649
  const isArbitraryVariableSize = value => getIsArbitraryVariable(value, isLabelSize);
646
650
  const isArbitraryVariableImage = value => getIsArbitraryVariable(value, isLabelImage);
647
651
  const isArbitraryVariableShadow = value => getIsArbitraryVariable(value, isLabelShadow, true);
652
+ const isArbitraryVariableWeight = value => getIsArbitraryVariable(value, isLabelWeight, true);
648
653
  // Helpers
649
654
  const getIsArbitraryValue = (value, testLabel, testValue) => {
650
655
  const result = arbitraryValueRegex.exec(value);
@@ -673,6 +678,7 @@ const isLabelSize = label => label === 'length' || label === 'size' || label ===
673
678
  const isLabelLength = label => label === 'length';
674
679
  const isLabelNumber = label => label === 'number';
675
680
  const isLabelFamilyName = label => label === 'family-name';
681
+ const isLabelWeight = label => label === 'number' || label === 'weight';
676
682
  const isLabelShadow = label => label === 'shadow';
677
683
  const getDefaultConfig = () => {
678
684
  /**
@@ -731,6 +737,8 @@ const getDefaultConfig = () => {
731
737
  const scaleAlignSecondaryAxis = () => ['start', 'end', 'center', 'stretch', 'center-safe', 'end-safe'];
732
738
  const scaleMargin = () => ['auto', ...scaleUnambiguousSpacing()];
733
739
  const scaleSizing = () => [isFraction, 'auto', 'full', 'dvw', 'dvh', 'lvw', 'lvh', 'svw', 'svh', 'min', 'max', 'fit', ...scaleUnambiguousSpacing()];
740
+ const scaleSizingInline = () => [isFraction, 'screen', 'full', 'dvw', 'lvw', 'svw', 'min', 'max', 'fit', ...scaleUnambiguousSpacing()];
741
+ const scaleSizingBlock = () => [isFraction, 'screen', 'full', 'lh', 'dvh', 'lvh', 'svh', 'min', 'max', 'fit', ...scaleUnambiguousSpacing()];
734
742
  const scaleColor = () => [themeColor, isArbitraryVariable, isArbitraryValue];
735
743
  const scaleBgPosition = () => [...scalePosition(), isArbitraryVariablePosition, isArbitraryPosition, {
736
744
  position: [isArbitraryVariable, isArbitraryValue]
@@ -929,40 +937,66 @@ const getDefaultConfig = () => {
929
937
  */
930
938
  position: ['static', 'fixed', 'absolute', 'relative', 'sticky'],
931
939
  /**
932
- * Top / Right / Bottom / Left
940
+ * Inset
933
941
  * @see https://tailwindcss.com/docs/top-right-bottom-left
934
942
  */
935
943
  inset: [{
936
944
  inset: scaleInset()
937
945
  }],
938
946
  /**
939
- * Right / Left
947
+ * Inset Inline
940
948
  * @see https://tailwindcss.com/docs/top-right-bottom-left
941
949
  */
942
950
  'inset-x': [{
943
951
  'inset-x': scaleInset()
944
952
  }],
945
953
  /**
946
- * Top / Bottom
954
+ * Inset Block
947
955
  * @see https://tailwindcss.com/docs/top-right-bottom-left
948
956
  */
949
957
  'inset-y': [{
950
958
  'inset-y': scaleInset()
951
959
  }],
952
960
  /**
953
- * Start
961
+ * Inset Inline Start
954
962
  * @see https://tailwindcss.com/docs/top-right-bottom-left
963
+ * @todo class group will be renamed to `inset-s` in next major release
955
964
  */
956
965
  start: [{
966
+ 'inset-s': scaleInset(),
967
+ /**
968
+ * @deprecated since Tailwind CSS v4.2.0 in favor of `inset-s-*` utilities.
969
+ * @see https://github.com/tailwindlabs/tailwindcss/pull/19613
970
+ */
957
971
  start: scaleInset()
958
972
  }],
959
973
  /**
960
- * End
974
+ * Inset Inline End
961
975
  * @see https://tailwindcss.com/docs/top-right-bottom-left
976
+ * @todo class group will be renamed to `inset-e` in next major release
962
977
  */
963
978
  end: [{
979
+ 'inset-e': scaleInset(),
980
+ /**
981
+ * @deprecated since Tailwind CSS v4.2.0 in favor of `inset-e-*` utilities.
982
+ * @see https://github.com/tailwindlabs/tailwindcss/pull/19613
983
+ */
964
984
  end: scaleInset()
965
985
  }],
986
+ /**
987
+ * Inset Block Start
988
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
989
+ */
990
+ 'inset-bs': [{
991
+ 'inset-bs': scaleInset()
992
+ }],
993
+ /**
994
+ * Inset Block End
995
+ * @see https://tailwindcss.com/docs/top-right-bottom-left
996
+ */
997
+ 'inset-be': [{
998
+ 'inset-be': scaleInset()
999
+ }],
966
1000
  /**
967
1001
  * Top
968
1002
  * @see https://tailwindcss.com/docs/top-right-bottom-left
@@ -1229,33 +1263,47 @@ const getDefaultConfig = () => {
1229
1263
  p: scaleUnambiguousSpacing()
1230
1264
  }],
1231
1265
  /**
1232
- * Padding X
1266
+ * Padding Inline
1233
1267
  * @see https://tailwindcss.com/docs/padding
1234
1268
  */
1235
1269
  px: [{
1236
1270
  px: scaleUnambiguousSpacing()
1237
1271
  }],
1238
1272
  /**
1239
- * Padding Y
1273
+ * Padding Block
1240
1274
  * @see https://tailwindcss.com/docs/padding
1241
1275
  */
1242
1276
  py: [{
1243
1277
  py: scaleUnambiguousSpacing()
1244
1278
  }],
1245
1279
  /**
1246
- * Padding Start
1280
+ * Padding Inline Start
1247
1281
  * @see https://tailwindcss.com/docs/padding
1248
1282
  */
1249
1283
  ps: [{
1250
1284
  ps: scaleUnambiguousSpacing()
1251
1285
  }],
1252
1286
  /**
1253
- * Padding End
1287
+ * Padding Inline End
1254
1288
  * @see https://tailwindcss.com/docs/padding
1255
1289
  */
1256
1290
  pe: [{
1257
1291
  pe: scaleUnambiguousSpacing()
1258
1292
  }],
1293
+ /**
1294
+ * Padding Block Start
1295
+ * @see https://tailwindcss.com/docs/padding
1296
+ */
1297
+ pbs: [{
1298
+ pbs: scaleUnambiguousSpacing()
1299
+ }],
1300
+ /**
1301
+ * Padding Block End
1302
+ * @see https://tailwindcss.com/docs/padding
1303
+ */
1304
+ pbe: [{
1305
+ pbe: scaleUnambiguousSpacing()
1306
+ }],
1259
1307
  /**
1260
1308
  * Padding Top
1261
1309
  * @see https://tailwindcss.com/docs/padding
@@ -1292,33 +1340,47 @@ const getDefaultConfig = () => {
1292
1340
  m: scaleMargin()
1293
1341
  }],
1294
1342
  /**
1295
- * Margin X
1343
+ * Margin Inline
1296
1344
  * @see https://tailwindcss.com/docs/margin
1297
1345
  */
1298
1346
  mx: [{
1299
1347
  mx: scaleMargin()
1300
1348
  }],
1301
1349
  /**
1302
- * Margin Y
1350
+ * Margin Block
1303
1351
  * @see https://tailwindcss.com/docs/margin
1304
1352
  */
1305
1353
  my: [{
1306
1354
  my: scaleMargin()
1307
1355
  }],
1308
1356
  /**
1309
- * Margin Start
1357
+ * Margin Inline Start
1310
1358
  * @see https://tailwindcss.com/docs/margin
1311
1359
  */
1312
1360
  ms: [{
1313
1361
  ms: scaleMargin()
1314
1362
  }],
1315
1363
  /**
1316
- * Margin End
1364
+ * Margin Inline End
1317
1365
  * @see https://tailwindcss.com/docs/margin
1318
1366
  */
1319
1367
  me: [{
1320
1368
  me: scaleMargin()
1321
1369
  }],
1370
+ /**
1371
+ * Margin Block Start
1372
+ * @see https://tailwindcss.com/docs/margin
1373
+ */
1374
+ mbs: [{
1375
+ mbs: scaleMargin()
1376
+ }],
1377
+ /**
1378
+ * Margin Block End
1379
+ * @see https://tailwindcss.com/docs/margin
1380
+ */
1381
+ mbe: [{
1382
+ mbe: scaleMargin()
1383
+ }],
1322
1384
  /**
1323
1385
  * Margin Top
1324
1386
  * @see https://tailwindcss.com/docs/margin
@@ -1381,6 +1443,48 @@ const getDefaultConfig = () => {
1381
1443
  size: [{
1382
1444
  size: scaleSizing()
1383
1445
  }],
1446
+ /**
1447
+ * Inline Size
1448
+ * @see https://tailwindcss.com/docs/width
1449
+ */
1450
+ 'inline-size': [{
1451
+ inline: ['auto', ...scaleSizingInline()]
1452
+ }],
1453
+ /**
1454
+ * Min-Inline Size
1455
+ * @see https://tailwindcss.com/docs/min-width
1456
+ */
1457
+ 'min-inline-size': [{
1458
+ 'min-inline': ['auto', ...scaleSizingInline()]
1459
+ }],
1460
+ /**
1461
+ * Max-Inline Size
1462
+ * @see https://tailwindcss.com/docs/max-width
1463
+ */
1464
+ 'max-inline-size': [{
1465
+ 'max-inline': ['none', ...scaleSizingInline()]
1466
+ }],
1467
+ /**
1468
+ * Block Size
1469
+ * @see https://tailwindcss.com/docs/height
1470
+ */
1471
+ 'block-size': [{
1472
+ block: ['auto', ...scaleSizingBlock()]
1473
+ }],
1474
+ /**
1475
+ * Min-Block Size
1476
+ * @see https://tailwindcss.com/docs/min-height
1477
+ */
1478
+ 'min-block-size': [{
1479
+ 'min-block': ['auto', ...scaleSizingBlock()]
1480
+ }],
1481
+ /**
1482
+ * Max-Block Size
1483
+ * @see https://tailwindcss.com/docs/max-height
1484
+ */
1485
+ 'max-block-size': [{
1486
+ 'max-block': ['none', ...scaleSizingBlock()]
1487
+ }],
1384
1488
  /**
1385
1489
  * Width
1386
1490
  * @see https://tailwindcss.com/docs/width
@@ -1453,7 +1557,7 @@ const getDefaultConfig = () => {
1453
1557
  * @see https://tailwindcss.com/docs/font-weight
1454
1558
  */
1455
1559
  'font-weight': [{
1456
- font: [themeFontWeight, isArbitraryVariable, isArbitraryNumber]
1560
+ font: [themeFontWeight, isArbitraryVariableWeight, isArbitraryWeight]
1457
1561
  }],
1458
1562
  /**
1459
1563
  * Font Stretch
@@ -1467,7 +1571,14 @@ const getDefaultConfig = () => {
1467
1571
  * @see https://tailwindcss.com/docs/font-family
1468
1572
  */
1469
1573
  'font-family': [{
1470
- font: [isArbitraryVariableFamilyName, isArbitraryValue, themeFont]
1574
+ font: [isArbitraryVariableFamilyName, isArbitraryFamilyName, themeFont]
1575
+ }],
1576
+ /**
1577
+ * Font Feature Settings
1578
+ * @see https://tailwindcss.com/docs/font-feature-settings
1579
+ */
1580
+ 'font-features': [{
1581
+ 'font-features': [isArbitraryValue]
1471
1582
  }],
1472
1583
  /**
1473
1584
  * Font Variant Numeric
@@ -1886,33 +1997,47 @@ const getDefaultConfig = () => {
1886
1997
  border: scaleBorderWidth()
1887
1998
  }],
1888
1999
  /**
1889
- * Border Width X
2000
+ * Border Width Inline
1890
2001
  * @see https://tailwindcss.com/docs/border-width
1891
2002
  */
1892
2003
  'border-w-x': [{
1893
2004
  'border-x': scaleBorderWidth()
1894
2005
  }],
1895
2006
  /**
1896
- * Border Width Y
2007
+ * Border Width Block
1897
2008
  * @see https://tailwindcss.com/docs/border-width
1898
2009
  */
1899
2010
  'border-w-y': [{
1900
2011
  'border-y': scaleBorderWidth()
1901
2012
  }],
1902
2013
  /**
1903
- * Border Width Start
2014
+ * Border Width Inline Start
1904
2015
  * @see https://tailwindcss.com/docs/border-width
1905
2016
  */
1906
2017
  'border-w-s': [{
1907
2018
  'border-s': scaleBorderWidth()
1908
2019
  }],
1909
2020
  /**
1910
- * Border Width End
2021
+ * Border Width Inline End
1911
2022
  * @see https://tailwindcss.com/docs/border-width
1912
2023
  */
1913
2024
  'border-w-e': [{
1914
2025
  'border-e': scaleBorderWidth()
1915
2026
  }],
2027
+ /**
2028
+ * Border Width Block Start
2029
+ * @see https://tailwindcss.com/docs/border-width
2030
+ */
2031
+ 'border-w-bs': [{
2032
+ 'border-bs': scaleBorderWidth()
2033
+ }],
2034
+ /**
2035
+ * Border Width Block End
2036
+ * @see https://tailwindcss.com/docs/border-width
2037
+ */
2038
+ 'border-w-be': [{
2039
+ 'border-be': scaleBorderWidth()
2040
+ }],
1916
2041
  /**
1917
2042
  * Border Width Top
1918
2043
  * @see https://tailwindcss.com/docs/border-width
@@ -1987,33 +2112,47 @@ const getDefaultConfig = () => {
1987
2112
  border: scaleColor()
1988
2113
  }],
1989
2114
  /**
1990
- * Border Color X
2115
+ * Border Color Inline
1991
2116
  * @see https://tailwindcss.com/docs/border-color
1992
2117
  */
1993
2118
  'border-color-x': [{
1994
2119
  'border-x': scaleColor()
1995
2120
  }],
1996
2121
  /**
1997
- * Border Color Y
2122
+ * Border Color Block
1998
2123
  * @see https://tailwindcss.com/docs/border-color
1999
2124
  */
2000
2125
  'border-color-y': [{
2001
2126
  'border-y': scaleColor()
2002
2127
  }],
2003
2128
  /**
2004
- * Border Color S
2129
+ * Border Color Inline Start
2005
2130
  * @see https://tailwindcss.com/docs/border-color
2006
2131
  */
2007
2132
  'border-color-s': [{
2008
2133
  'border-s': scaleColor()
2009
2134
  }],
2010
2135
  /**
2011
- * Border Color E
2136
+ * Border Color Inline End
2012
2137
  * @see https://tailwindcss.com/docs/border-color
2013
2138
  */
2014
2139
  'border-color-e': [{
2015
2140
  'border-e': scaleColor()
2016
2141
  }],
2142
+ /**
2143
+ * Border Color Block Start
2144
+ * @see https://tailwindcss.com/docs/border-color
2145
+ */
2146
+ 'border-color-bs': [{
2147
+ 'border-bs': scaleColor()
2148
+ }],
2149
+ /**
2150
+ * Border Color Block End
2151
+ * @see https://tailwindcss.com/docs/border-color
2152
+ */
2153
+ 'border-color-be': [{
2154
+ 'border-be': scaleColor()
2155
+ }],
2017
2156
  /**
2018
2157
  * Border Color Top
2019
2158
  * @see https://tailwindcss.com/docs/border-color
@@ -2874,33 +3013,47 @@ const getDefaultConfig = () => {
2874
3013
  'scroll-m': scaleUnambiguousSpacing()
2875
3014
  }],
2876
3015
  /**
2877
- * Scroll Margin X
3016
+ * Scroll Margin Inline
2878
3017
  * @see https://tailwindcss.com/docs/scroll-margin
2879
3018
  */
2880
3019
  'scroll-mx': [{
2881
3020
  'scroll-mx': scaleUnambiguousSpacing()
2882
3021
  }],
2883
3022
  /**
2884
- * Scroll Margin Y
3023
+ * Scroll Margin Block
2885
3024
  * @see https://tailwindcss.com/docs/scroll-margin
2886
3025
  */
2887
3026
  'scroll-my': [{
2888
3027
  'scroll-my': scaleUnambiguousSpacing()
2889
3028
  }],
2890
3029
  /**
2891
- * Scroll Margin Start
3030
+ * Scroll Margin Inline Start
2892
3031
  * @see https://tailwindcss.com/docs/scroll-margin
2893
3032
  */
2894
3033
  'scroll-ms': [{
2895
3034
  'scroll-ms': scaleUnambiguousSpacing()
2896
3035
  }],
2897
3036
  /**
2898
- * Scroll Margin End
3037
+ * Scroll Margin Inline End
2899
3038
  * @see https://tailwindcss.com/docs/scroll-margin
2900
3039
  */
2901
3040
  'scroll-me': [{
2902
3041
  'scroll-me': scaleUnambiguousSpacing()
2903
3042
  }],
3043
+ /**
3044
+ * Scroll Margin Block Start
3045
+ * @see https://tailwindcss.com/docs/scroll-margin
3046
+ */
3047
+ 'scroll-mbs': [{
3048
+ 'scroll-mbs': scaleUnambiguousSpacing()
3049
+ }],
3050
+ /**
3051
+ * Scroll Margin Block End
3052
+ * @see https://tailwindcss.com/docs/scroll-margin
3053
+ */
3054
+ 'scroll-mbe': [{
3055
+ 'scroll-mbe': scaleUnambiguousSpacing()
3056
+ }],
2904
3057
  /**
2905
3058
  * Scroll Margin Top
2906
3059
  * @see https://tailwindcss.com/docs/scroll-margin
@@ -2937,33 +3090,47 @@ const getDefaultConfig = () => {
2937
3090
  'scroll-p': scaleUnambiguousSpacing()
2938
3091
  }],
2939
3092
  /**
2940
- * Scroll Padding X
3093
+ * Scroll Padding Inline
2941
3094
  * @see https://tailwindcss.com/docs/scroll-padding
2942
3095
  */
2943
3096
  'scroll-px': [{
2944
3097
  'scroll-px': scaleUnambiguousSpacing()
2945
3098
  }],
2946
3099
  /**
2947
- * Scroll Padding Y
3100
+ * Scroll Padding Block
2948
3101
  * @see https://tailwindcss.com/docs/scroll-padding
2949
3102
  */
2950
3103
  'scroll-py': [{
2951
3104
  'scroll-py': scaleUnambiguousSpacing()
2952
3105
  }],
2953
3106
  /**
2954
- * Scroll Padding Start
3107
+ * Scroll Padding Inline Start
2955
3108
  * @see https://tailwindcss.com/docs/scroll-padding
2956
3109
  */
2957
3110
  'scroll-ps': [{
2958
3111
  'scroll-ps': scaleUnambiguousSpacing()
2959
3112
  }],
2960
3113
  /**
2961
- * Scroll Padding End
3114
+ * Scroll Padding Inline End
2962
3115
  * @see https://tailwindcss.com/docs/scroll-padding
2963
3116
  */
2964
3117
  'scroll-pe': [{
2965
3118
  'scroll-pe': scaleUnambiguousSpacing()
2966
3119
  }],
3120
+ /**
3121
+ * Scroll Padding Block Start
3122
+ * @see https://tailwindcss.com/docs/scroll-padding
3123
+ */
3124
+ 'scroll-pbs': [{
3125
+ 'scroll-pbs': scaleUnambiguousSpacing()
3126
+ }],
3127
+ /**
3128
+ * Scroll Padding Block End
3129
+ * @see https://tailwindcss.com/docs/scroll-padding
3130
+ */
3131
+ 'scroll-pbe': [{
3132
+ 'scroll-pbe': scaleUnambiguousSpacing()
3133
+ }],
2967
3134
  /**
2968
3135
  * Scroll Padding Top
2969
3136
  * @see https://tailwindcss.com/docs/scroll-padding
@@ -3098,15 +3265,15 @@ const getDefaultConfig = () => {
3098
3265
  conflictingClassGroups: {
3099
3266
  overflow: ['overflow-x', 'overflow-y'],
3100
3267
  overscroll: ['overscroll-x', 'overscroll-y'],
3101
- inset: ['inset-x', 'inset-y', 'start', 'end', 'top', 'right', 'bottom', 'left'],
3268
+ inset: ['inset-x', 'inset-y', 'inset-bs', 'inset-be', 'start', 'end', 'top', 'right', 'bottom', 'left'],
3102
3269
  'inset-x': ['right', 'left'],
3103
3270
  'inset-y': ['top', 'bottom'],
3104
3271
  flex: ['basis', 'grow', 'shrink'],
3105
3272
  gap: ['gap-x', 'gap-y'],
3106
- p: ['px', 'py', 'ps', 'pe', 'pt', 'pr', 'pb', 'pl'],
3273
+ p: ['px', 'py', 'ps', 'pe', 'pbs', 'pbe', 'pt', 'pr', 'pb', 'pl'],
3107
3274
  px: ['pr', 'pl'],
3108
3275
  py: ['pt', 'pb'],
3109
- m: ['mx', 'my', 'ms', 'me', 'mt', 'mr', 'mb', 'ml'],
3276
+ m: ['mx', 'my', 'ms', 'me', 'mbs', 'mbe', 'mt', 'mr', 'mb', 'ml'],
3110
3277
  mx: ['mr', 'ml'],
3111
3278
  my: ['mt', 'mb'],
3112
3279
  size: ['w', 'h'],
@@ -3126,18 +3293,18 @@ const getDefaultConfig = () => {
3126
3293
  'rounded-b': ['rounded-br', 'rounded-bl'],
3127
3294
  'rounded-l': ['rounded-tl', 'rounded-bl'],
3128
3295
  'border-spacing': ['border-spacing-x', 'border-spacing-y'],
3129
- 'border-w': ['border-w-x', 'border-w-y', 'border-w-s', 'border-w-e', 'border-w-t', 'border-w-r', 'border-w-b', 'border-w-l'],
3296
+ 'border-w': ['border-w-x', 'border-w-y', 'border-w-s', 'border-w-e', 'border-w-bs', 'border-w-be', 'border-w-t', 'border-w-r', 'border-w-b', 'border-w-l'],
3130
3297
  'border-w-x': ['border-w-r', 'border-w-l'],
3131
3298
  'border-w-y': ['border-w-t', 'border-w-b'],
3132
- 'border-color': ['border-color-x', 'border-color-y', 'border-color-s', 'border-color-e', 'border-color-t', 'border-color-r', 'border-color-b', 'border-color-l'],
3299
+ 'border-color': ['border-color-x', 'border-color-y', 'border-color-s', 'border-color-e', 'border-color-bs', 'border-color-be', 'border-color-t', 'border-color-r', 'border-color-b', 'border-color-l'],
3133
3300
  'border-color-x': ['border-color-r', 'border-color-l'],
3134
3301
  'border-color-y': ['border-color-t', 'border-color-b'],
3135
3302
  translate: ['translate-x', 'translate-y', 'translate-none'],
3136
3303
  'translate-none': ['translate', 'translate-x', 'translate-y', 'translate-z'],
3137
- 'scroll-m': ['scroll-mx', 'scroll-my', 'scroll-ms', 'scroll-me', 'scroll-mt', 'scroll-mr', 'scroll-mb', 'scroll-ml'],
3304
+ 'scroll-m': ['scroll-mx', 'scroll-my', 'scroll-ms', 'scroll-me', 'scroll-mbs', 'scroll-mbe', 'scroll-mt', 'scroll-mr', 'scroll-mb', 'scroll-ml'],
3138
3305
  'scroll-mx': ['scroll-mr', 'scroll-ml'],
3139
3306
  'scroll-my': ['scroll-mt', 'scroll-mb'],
3140
- 'scroll-p': ['scroll-px', 'scroll-py', 'scroll-ps', 'scroll-pe', 'scroll-pt', 'scroll-pr', 'scroll-pb', 'scroll-pl'],
3307
+ 'scroll-p': ['scroll-px', 'scroll-py', 'scroll-ps', 'scroll-pe', 'scroll-pbs', 'scroll-pbe', 'scroll-pt', 'scroll-pr', 'scroll-pb', 'scroll-pl'],
3141
3308
  'scroll-px': ['scroll-pr', 'scroll-pl'],
3142
3309
  'scroll-py': ['scroll-pt', 'scroll-pb'],
3143
3310
  touch: ['touch-x', 'touch-y', 'touch-pz'],
@@ -7475,8 +7642,17 @@ function SelectField$1({
7475
7642
  required && /* @__PURE__ */ jsxRuntime.jsx("i", { className: "text-neutral2", children: "(required)" })
7476
7643
  ] }) }),
7477
7644
  /* @__PURE__ */ jsxRuntime.jsxs(Select, { name, value, onValueChange, disabled, children: [
7478
- /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { id: `select-${name}`, size, variant, children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder }) }),
7479
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.value, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "whitespace-nowrap truncate flex items-center gap-2", children: [
7645
+ /* @__PURE__ */ jsxRuntime.jsx(
7646
+ SelectTrigger,
7647
+ {
7648
+ id: `select-${name}`,
7649
+ size,
7650
+ variant,
7651
+ className: "grid grid-cols-[1fr_auto] [&>span]:truncate",
7652
+ children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder })
7653
+ }
7654
+ ),
7655
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.value, disabled: option.disabled, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "whitespace-nowrap truncate flex items-center gap-2", children: [
7480
7656
  option.icon,
7481
7657
  option.label
7482
7658
  ] }) }, option.label)) })
@@ -18874,7 +19050,7 @@ function SideDialogHeading({ children, className, as = "h1" }) {
18874
19050
  }
18875
19051
 
18876
19052
  function SideDialogContent({ children, className }) {
18877
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 pl-9 overflow-y-scroll grid gap-6 content-start", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-6 mb-8"), children }) });
19053
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-6 pl-9 overflow-y-scroll grid gap-6 content-start pb-8", className), children });
18878
19054
  }
18879
19055
 
18880
19056
  function SideDialogHeader({ children, className }) {
@@ -19888,7 +20064,7 @@ const useCompareScorerVersions = ({
19888
20064
  });
19889
20065
  };
19890
20066
 
19891
- function formatTimestamp$1(isoString) {
20067
+ function formatTimestamp$2(isoString) {
19892
20068
  const date = new Date(isoString);
19893
20069
  return date.toLocaleDateString(void 0, {
19894
20070
  month: "short",
@@ -19922,7 +20098,7 @@ function ScorerVersionCombobox({
19922
20098
  return {
19923
20099
  label: `v${version.versionNumber}`,
19924
20100
  value: version.id,
19925
- description: formatTimestamp$1(version.createdAt),
20101
+ description: formatTimestamp$2(version.createdAt),
19926
20102
  end: isPublished ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "success", children: "Published" }) : isDraft ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", children: "Draft" }) : void 0
19927
20103
  };
19928
20104
  })
@@ -22503,6 +22679,12 @@ const entityConfigSchema = z.z.object({
22503
22679
  description: z.z.string().max(500).optional(),
22504
22680
  rules: ruleGroupSchema.optional()
22505
22681
  });
22682
+ const skillConfigSchema = z.z.object({
22683
+ description: z.z.string().optional(),
22684
+ instructions: z.z.string().optional(),
22685
+ pin: z.z.string().optional(),
22686
+ strategy: z.z.enum(["latest", "live"]).optional()
22687
+ });
22506
22688
  const scorerConfigSchema = z.z.object({
22507
22689
  description: z.z.string().max(500).optional(),
22508
22690
  sampling: scoringSamplingConfigSchema.optional(),
@@ -22556,6 +22738,22 @@ const memoryConfigSchema = z.z.object({
22556
22738
  path: ["semanticRecall"]
22557
22739
  }
22558
22740
  );
22741
+ const inMemoryFileNodeSchema = z.z.lazy(
22742
+ () => z.z.object({
22743
+ id: z.z.string(),
22744
+ name: z.z.string(),
22745
+ type: z.z.enum(["file", "folder"]),
22746
+ content: z.z.string().optional(),
22747
+ children: z.z.array(inMemoryFileNodeSchema).optional()
22748
+ })
22749
+ );
22750
+ z.z.object({
22751
+ localId: z.z.string(),
22752
+ name: z.z.string().min(1, "Skill name is required"),
22753
+ description: z.z.string(),
22754
+ workspaceId: z.z.string().min(1, "Workspace is required"),
22755
+ files: z.z.array(inMemoryFileNodeSchema)
22756
+ });
22559
22757
  const agentFormSchema = z.z.object({
22560
22758
  name: z.z.string().min(1, "Name is required").max(100, "Name must be 100 characters or less"),
22561
22759
  description: z.z.string().max(500, "Description must be 500 characters or less").optional(),
@@ -22577,10 +22775,21 @@ const agentFormSchema = z.z.object({
22577
22775
  id: z.z.string().optional(),
22578
22776
  name: z.z.string().min(1),
22579
22777
  description: z.z.string().optional(),
22580
- servers: z.z.record(z.z.string(), z.z.any())
22778
+ servers: z.z.record(z.z.string(), z.z.any()),
22779
+ selectedTools: z.z.record(
22780
+ z.z.string(),
22781
+ z.z.object({
22782
+ description: z.z.string().optional()
22783
+ })
22784
+ ).optional().default({})
22581
22785
  })
22582
22786
  ).optional().default([]),
22583
- mcpClientsToDelete: z.z.array(z.z.string()).optional().default([])
22787
+ mcpClientsToDelete: z.z.array(z.z.string()).optional().default([]),
22788
+ skills: z.z.record(z.z.string(), skillConfigSchema).optional().default({}),
22789
+ workspace: z.z.discriminatedUnion("type", [
22790
+ z.z.object({ type: z.z.literal("id"), workspaceId: z.z.string() }),
22791
+ z.z.object({ type: z.z.literal("inline"), config: z.z.record(z.z.string(), z.z.unknown()) })
22792
+ ]).optional()
22584
22793
  });
22585
22794
 
22586
22795
  const AgentCMSBlocks = ({ items, onChange, className, placeholder, schema }) => {
@@ -22669,7 +22878,8 @@ function useAgentEditForm(options = {}) {
22669
22878
  variables: initialValues?.variables ?? {},
22670
22879
  instructionBlocks: initialValues?.instructionBlocks ?? [createInstructionBlock()],
22671
22880
  mcpClients: initialValues?.mcpClients ?? [],
22672
- mcpClientsToDelete: []
22881
+ mcpClientsToDelete: [],
22882
+ skills: initialValues?.skills ?? {}
22673
22883
  }
22674
22884
  });
22675
22885
  return { form };
@@ -23807,7 +24017,7 @@ function MemorySection({ control, setValue, readOnly = false }) {
23807
24017
  ] }) });
23808
24018
  }
23809
24019
 
23810
- function formatTimestamp(isoString) {
24020
+ function formatTimestamp$1(isoString) {
23811
24021
  const date = new Date(isoString);
23812
24022
  return date.toLocaleDateString(void 0, {
23813
24023
  month: "short",
@@ -23841,7 +24051,7 @@ function AgentVersionCombobox({
23841
24051
  return {
23842
24052
  label: `v${version.versionNumber}`,
23843
24053
  value: version.id,
23844
- description: formatTimestamp(version.createdAt),
24054
+ description: formatTimestamp$1(version.createdAt),
23845
24055
  end: isPublished ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "success", children: "Published" }) : isDraft ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", children: "Draft" }) : void 0
23846
24056
  };
23847
24057
  })
@@ -23880,6 +24090,8 @@ function useSidebarDescriptions(control) {
23880
24090
  const workflowCount = Object.keys(values.workflows ?? {}).length;
23881
24091
  const workflows = workflowCount === 0 ? "None selected" : pluralize(workflowCount, "workflow");
23882
24092
  const memory = values.memory?.enabled ? "Enabled" : "Disabled";
24093
+ const skillCount = Object.keys(values.skills ?? {}).length;
24094
+ const skills = skillCount === 0 ? "None selected" : pluralize(skillCount, "skill");
23883
24095
  const variableCount = Object.keys(values.variables?.properties ?? {}).length;
23884
24096
  const variables = variableCount === 0 ? "None defined" : pluralize(variableCount, "variable");
23885
24097
  return {
@@ -23889,6 +24101,7 @@ function useSidebarDescriptions(control) {
23889
24101
  agents: { description: agents, done: agentCount > 0 },
23890
24102
  scorers: { description: scorers, done: scorerCount > 0 },
23891
24103
  workflows: { description: workflows, done: workflowCount > 0 },
24104
+ skills: { description: skills, done: skillCount > 0 },
23892
24105
  memory: { description: memory, done: !!values.memory?.enabled },
23893
24106
  variables: { description: variables, done: variableCount > 0 }
23894
24107
  };
@@ -23902,6 +24115,7 @@ const AGENT_CMS_SECTIONS = [
23902
24115
  { name: "Agents", pathSuffix: "/agents", descriptionKey: "agents", required: false },
23903
24116
  { name: "Scorers", pathSuffix: "/scorers", descriptionKey: "scorers", required: false },
23904
24117
  { name: "Workflows", pathSuffix: "/workflows", descriptionKey: "workflows", required: false },
24118
+ { name: "Skills", pathSuffix: "/skills", descriptionKey: "skills", required: false },
23905
24119
  { name: "Memory", pathSuffix: "/memory", descriptionKey: "memory", required: false },
23906
24120
  { name: "Variables", pathSuffix: "/variables", descriptionKey: "variables", required: false }
23907
24121
  ];
@@ -24015,14 +24229,24 @@ function AgentCmsBottomBar({ basePath, currentPath }) {
24015
24229
  ] });
24016
24230
  }
24017
24231
 
24018
- function AgentsCmsLayout({ children, currentPath, basePath, versionId }) {
24019
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid overflow-y-auto h-full bg-surface1 grid-cols-[240px_1fr]", children: [
24020
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto h-full border-r border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(AgentCmsSidebar, { basePath, currentPath, versionId }) }),
24021
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full overflow-hidden", children: [
24022
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto flex-1 p-8 max-w-5xl w-full", children }),
24023
- /* @__PURE__ */ jsxRuntime.jsx(AgentCmsBottomBar, { basePath, currentPath })
24024
- ] })
24025
- ] });
24232
+ function AgentsCmsLayout({ children, currentPath, basePath, versionId, rightPanel }) {
24233
+ return /* @__PURE__ */ jsxRuntime.jsxs(
24234
+ "div",
24235
+ {
24236
+ className: cn(
24237
+ "grid overflow-y-auto h-full bg-surface1",
24238
+ rightPanel ? "grid-cols-[240px_1fr_240px]" : "grid-cols-[240px_1fr]"
24239
+ ),
24240
+ children: [
24241
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto h-full border-r border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(AgentCmsSidebar, { basePath, currentPath, versionId }) }),
24242
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full overflow-hidden", children: [
24243
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto flex-1 p-8 max-w-5xl w-full", children }),
24244
+ /* @__PURE__ */ jsxRuntime.jsx(AgentCmsBottomBar, { basePath, currentPath })
24245
+ ] }),
24246
+ rightPanel && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto h-full border-l border-border1", children: rightPanel })
24247
+ ]
24248
+ }
24249
+ );
24026
24250
  }
24027
24251
 
24028
24252
  function InformationPage() {
@@ -24646,6 +24870,7 @@ function MCPClientFormSidebar({
24646
24870
  onPreFillFromServer,
24647
24871
  containerRef,
24648
24872
  readOnly,
24873
+ showSubmit,
24649
24874
  submitLabel = "Create MCP Client",
24650
24875
  onTryConnect,
24651
24876
  isTryingConnect
@@ -24859,8 +25084,8 @@ function MCPClientFormSidebar({
24859
25084
  ] })
24860
25085
  ] })
24861
25086
  ] }) }),
24862
- !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 p-4 flex flex-col gap-2", children: [
24863
- (() => {
25087
+ (showSubmit ?? !readOnly) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 p-4 flex flex-col gap-2", children: [
25088
+ !readOnly && (() => {
24864
25089
  const isDisabled = serverType !== "http" || !url.trim() || isTryingConnect;
24865
25090
  const tooltipContent = serverType !== "http" ? "Only available for HTTP servers" : !url.trim() ? "Enter a URL first" : void 0;
24866
25091
  return tooltipContent ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -24892,7 +25117,14 @@ function MCPClientFormSidebar({
24892
25117
  ] });
24893
25118
  }
24894
25119
 
24895
- function MCPClientToolPreview({ serverType, url, tryConnect }) {
25120
+ function MCPClientToolPreview({
25121
+ serverType,
25122
+ url,
25123
+ tryConnect,
25124
+ selectedTools,
25125
+ onToggleTool,
25126
+ onDescriptionChange
25127
+ }) {
24896
25128
  if (serverType === "stdio") {
24897
25129
  return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { className: "text-neutral3", children: "Tool preview is available for HTTP servers. Stdio servers cannot be previewed." }) });
24898
25130
  }
@@ -24909,37 +25141,79 @@ function MCPClientToolPreview({ serverType, url, tryConnect }) {
24909
25141
  ] }),
24910
25142
  tryConnect.isError && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-accent2", children: tryConnect.error instanceof Error ? tryConnect.error.message : "Connection failed" }),
24911
25143
  tryConnect.isSuccess && tryConnect.data.tools.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(Txt, { className: "text-neutral3", children: "Connected successfully but no tools were found." }),
24912
- tryConnect.isSuccess && tryConnect.data.tools.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ToolList, { tools: tryConnect.data.tools })
25144
+ tryConnect.isSuccess && tryConnect.data.tools.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
25145
+ ToolList,
25146
+ {
25147
+ tools: tryConnect.data.tools,
25148
+ selectedTools,
25149
+ onToggleTool,
25150
+ onDescriptionChange
25151
+ }
25152
+ )
24913
25153
  ] });
24914
25154
  }
24915
25155
  function EmptyState({ children }) {
24916
25156
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full p-8 text-center", children });
24917
25157
  }
24918
- function ToolList({ tools }) {
25158
+ function ToolList({
25159
+ tools,
25160
+ selectedTools = {},
25161
+ onToggleTool,
25162
+ onDescriptionChange
25163
+ }) {
25164
+ const selectedCount = Object.keys(selectedTools).length;
24919
25165
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5 overflow-y-auto", children: [
24920
25166
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-neutral6 flex gap-2 items-center", children: [
24921
25167
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "lg", className: "bg-surface4 rounded-md p-1", children: /* @__PURE__ */ jsxRuntime.jsx(McpServerIcon, {}) }),
24922
25168
  /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "header-md", as: "h2", className: "font-medium", children: [
24923
25169
  "Available Tools (",
25170
+ selectedCount,
25171
+ "/",
24924
25172
  tools.length,
24925
- ")"
25173
+ " selected)"
24926
25174
  ] })
24927
25175
  ] }),
24928
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 pt-6", children: tools.map((tool) => /* @__PURE__ */ jsxRuntime.jsxs(Entity, { children: [
24929
- /* @__PURE__ */ jsxRuntime.jsx(EntityIcon, { children: /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, { className: "group-hover/entity:text-accent6" }) }),
24930
- /* @__PURE__ */ jsxRuntime.jsxs(EntityContent, { children: [
24931
- /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: tool.name }),
24932
- tool.description && /* @__PURE__ */ jsxRuntime.jsx(EntityDescription, { children: tool.description })
24933
- ] })
24934
- ] }, tool.name)) })
25176
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2 pt-6", children: tools.map((tool) => {
25177
+ const isSelected = tool.name in selectedTools;
25178
+ const isDisabled = !onDescriptionChange || !isSelected;
25179
+ return /* @__PURE__ */ jsxRuntime.jsxs(Entity, { children: [
25180
+ /* @__PURE__ */ jsxRuntime.jsx(EntityIcon, { children: /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, { className: "group-hover/entity:text-accent6" }) }),
25181
+ /* @__PURE__ */ jsxRuntime.jsxs(EntityContent, { children: [
25182
+ /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: tool.name }),
25183
+ /* @__PURE__ */ jsxRuntime.jsx(EntityDescription, { children: /* @__PURE__ */ jsxRuntime.jsx(
25184
+ "input",
25185
+ {
25186
+ type: "text",
25187
+ disabled: isDisabled,
25188
+ className: cn(
25189
+ "border border-transparent appearance-none block w-full text-neutral3 bg-transparent",
25190
+ !isDisabled && "border-border1 border-dashed"
25191
+ ),
25192
+ value: isSelected ? selectedTools[tool.name]?.description ?? tool.description ?? "" : tool.description ?? "",
25193
+ onChange: (e) => onDescriptionChange?.(tool.name, e.target.value)
25194
+ }
25195
+ ) })
25196
+ ] }),
25197
+ onToggleTool && /* @__PURE__ */ jsxRuntime.jsx(Switch, { checked: isSelected, onCheckedChange: () => onToggleTool(tool.name, tool.description) })
25198
+ ] }, tool.name);
25199
+ }) })
24935
25200
  ] });
24936
25201
  }
24937
25202
 
24938
- function MCPClientCreateContent({ onAdd, readOnly, initialValues, submitLabel }) {
25203
+ function MCPClientCreateContent({
25204
+ onAdd,
25205
+ readOnly,
25206
+ initialValues,
25207
+ initialSelectedTools,
25208
+ submitLabel
25209
+ }) {
24939
25210
  const { form } = useMCPClientForm(initialValues);
24940
25211
  const containerRef = React.useRef(null);
24941
25212
  const serverType = reactHookForm.useWatch({ control: form.control, name: "serverType" });
24942
25213
  const url = reactHookForm.useWatch({ control: form.control, name: "url" });
25214
+ const [selectedTools, setSelectedTools] = React.useState(
25215
+ initialSelectedTools ?? {}
25216
+ );
24943
25217
  const tryConnect = useTryConnectMcp();
24944
25218
  const hasAutoConnected = React.useRef(false);
24945
25219
  React.useEffect(() => {
@@ -24953,6 +25227,22 @@ function MCPClientCreateContent({ onAdd, readOnly, initialValues, submitLabel })
24953
25227
  tryConnect.mutate(url);
24954
25228
  }
24955
25229
  }, [serverType, url, tryConnect]);
25230
+ const handleToggleTool = React.useCallback((toolName, description) => {
25231
+ setSelectedTools((prev) => {
25232
+ if (toolName in prev) {
25233
+ const next = { ...prev };
25234
+ delete next[toolName];
25235
+ return next;
25236
+ }
25237
+ return { ...prev, [toolName]: { description } };
25238
+ });
25239
+ }, []);
25240
+ const handleDescriptionChange = React.useCallback((toolName, description) => {
25241
+ setSelectedTools((prev) => ({
25242
+ ...prev,
25243
+ [toolName]: { ...prev[toolName], description }
25244
+ }));
25245
+ }, []);
24956
25246
  const handlePreFillFromServer = (serverId) => {
24957
25247
  const host = window.MASTRA_SERVER_HOST;
24958
25248
  const port = window.MASTRA_SERVER_PORT;
@@ -24994,7 +25284,8 @@ function MCPClientCreateContent({ onAdd, readOnly, initialValues, submitLabel })
24994
25284
  onAdd({
24995
25285
  name: values.name,
24996
25286
  description: values.description || void 0,
24997
- servers: serverConfig
25287
+ servers: serverConfig,
25288
+ selectedTools
24998
25289
  });
24999
25290
  };
25000
25291
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "h-full min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -25009,12 +25300,23 @@ function MCPClientCreateContent({ onAdd, readOnly, initialValues, submitLabel })
25009
25300
  onPreFillFromServer: handlePreFillFromServer,
25010
25301
  containerRef,
25011
25302
  readOnly,
25303
+ showSubmit: !!onAdd,
25012
25304
  submitLabel,
25013
25305
  onTryConnect: handleTryConnect,
25014
25306
  isTryingConnect: tryConnect.isPending
25015
25307
  }
25016
25308
  ),
25017
- children: /* @__PURE__ */ jsxRuntime.jsx(MCPClientToolPreview, { serverType, url, tryConnect })
25309
+ children: /* @__PURE__ */ jsxRuntime.jsx(
25310
+ MCPClientToolPreview,
25311
+ {
25312
+ serverType,
25313
+ url,
25314
+ tryConnect,
25315
+ selectedTools,
25316
+ onToggleTool: onAdd ? handleToggleTool : void 0,
25317
+ onDescriptionChange: onAdd ? handleDescriptionChange : void 0
25318
+ }
25319
+ )
25018
25320
  }
25019
25321
  ) });
25020
25322
  }
@@ -25048,11 +25350,29 @@ function MCPClientList() {
25048
25350
  const handleAdd = (config) => {
25049
25351
  const current = form.getValues("mcpClients") ?? [];
25050
25352
  form.setValue("mcpClients", [...current, config]);
25353
+ if (Object.keys(config.selectedTools).length > 0) {
25354
+ const currentTools = form.getValues("tools") ?? {};
25355
+ const next = { ...currentTools };
25356
+ for (const [name, toolConfig] of Object.entries(config.selectedTools)) {
25357
+ next[name] = { description: toolConfig.description };
25358
+ }
25359
+ form.setValue("tools", next);
25360
+ }
25051
25361
  setIsCreateOpen(false);
25052
25362
  };
25053
25363
  const handleUpdate = (config) => {
25054
25364
  if (viewIndex === null) return;
25055
25365
  const current = form.getValues("mcpClients") ?? [];
25366
+ const oldClient = current[viewIndex];
25367
+ const currentTools = form.getValues("tools") ?? {};
25368
+ const next = { ...currentTools };
25369
+ for (const name of Object.keys(oldClient?.selectedTools ?? {})) {
25370
+ delete next[name];
25371
+ }
25372
+ for (const [name, toolConfig] of Object.entries(config.selectedTools)) {
25373
+ next[name] = { description: toolConfig.description };
25374
+ }
25375
+ form.setValue("tools", next);
25056
25376
  const updated = [...current];
25057
25377
  updated[viewIndex] = { ...updated[viewIndex], ...config };
25058
25378
  form.setValue("mcpClients", updated);
@@ -25061,6 +25381,14 @@ function MCPClientList() {
25061
25381
  const handleRemove = (index) => {
25062
25382
  const current = form.getValues("mcpClients") ?? [];
25063
25383
  const removed = current[index];
25384
+ if (removed?.selectedTools) {
25385
+ const currentTools = form.getValues("tools") ?? {};
25386
+ const next = { ...currentTools };
25387
+ for (const name of Object.keys(removed.selectedTools)) {
25388
+ delete next[name];
25389
+ }
25390
+ form.setValue("tools", next);
25391
+ }
25064
25392
  if (removed?.id) {
25065
25393
  const toDelete = form.getValues("mcpClientsToDelete") ?? [];
25066
25394
  form.setValue("mcpClientsToDelete", [...toDelete, removed.id]);
@@ -25162,8 +25490,9 @@ function MCPClientList() {
25162
25490
  {
25163
25491
  readOnly: isViewingPersisted,
25164
25492
  initialValues: viewFormValues,
25165
- onAdd: isViewingPersisted ? void 0 : handleUpdate,
25166
- submitLabel: isViewingPersisted ? void 0 : "Update MCP Client"
25493
+ initialSelectedTools: viewingClient?.selectedTools,
25494
+ onAdd: readOnly ? void 0 : handleUpdate,
25495
+ submitLabel: isViewingPersisted ? "Update tool selection" : "Update MCP Client"
25167
25496
  }
25168
25497
  )
25169
25498
  ]
@@ -25205,25 +25534,37 @@ function ToolsPage() {
25205
25534
  if (isSet) {
25206
25535
  const next = { ...selectedTools };
25207
25536
  delete next[toolId];
25208
- form.setValue("tools", next);
25537
+ form.setValue("tools", next, { shouldDirty: true });
25209
25538
  } else {
25210
- form.setValue("tools", {
25211
- ...selectedTools,
25212
- [toolId]: { ...selectedTools?.[toolId], description: getOriginalDescription(toolId) }
25213
- });
25539
+ form.setValue(
25540
+ "tools",
25541
+ {
25542
+ ...selectedTools,
25543
+ [toolId]: { ...selectedTools?.[toolId], description: getOriginalDescription(toolId) }
25544
+ },
25545
+ { shouldDirty: true }
25546
+ );
25214
25547
  }
25215
25548
  };
25216
25549
  const handleDescriptionChange = (toolId, description) => {
25217
- form.setValue("tools", {
25218
- ...selectedTools,
25219
- [toolId]: { ...selectedTools?.[toolId], description }
25220
- });
25550
+ form.setValue(
25551
+ "tools",
25552
+ {
25553
+ ...selectedTools,
25554
+ [toolId]: { ...selectedTools?.[toolId], description }
25555
+ },
25556
+ { shouldDirty: true }
25557
+ );
25221
25558
  };
25222
25559
  const handleRulesChange = (toolId, rules) => {
25223
- form.setValue("tools", {
25224
- ...selectedTools,
25225
- [toolId]: { ...selectedTools?.[toolId], rules }
25226
- });
25560
+ form.setValue(
25561
+ "tools",
25562
+ {
25563
+ ...selectedTools,
25564
+ [toolId]: { ...selectedTools?.[toolId], rules }
25565
+ },
25566
+ { shouldDirty: true }
25567
+ );
25227
25568
  };
25228
25569
  const handleIntegrationToolsSubmit = React.useCallback(
25229
25570
  (providerId, tools2) => {
@@ -25236,7 +25577,7 @@ function ToolsPage() {
25236
25577
  for (const [id, description] of tools2) {
25237
25578
  next[id] = selectedIntegrationTools?.[id] || { description };
25238
25579
  }
25239
- form.setValue("integrationTools", next);
25580
+ form.setValue("integrationTools", next, { shouldDirty: true });
25240
25581
  },
25241
25582
  [form, selectedIntegrationTools]
25242
25583
  );
@@ -25335,25 +25676,37 @@ function AgentsPage() {
25335
25676
  if (isSet) {
25336
25677
  const next = { ...selectedAgents };
25337
25678
  delete next[agentId];
25338
- form.setValue("agents", next);
25679
+ form.setValue("agents", next, { shouldDirty: true });
25339
25680
  } else {
25340
- form.setValue("agents", {
25341
- ...selectedAgents,
25342
- [agentId]: { ...selectedAgents?.[agentId], description: getOriginalDescription(agentId) }
25343
- });
25681
+ form.setValue(
25682
+ "agents",
25683
+ {
25684
+ ...selectedAgents,
25685
+ [agentId]: { ...selectedAgents?.[agentId], description: getOriginalDescription(agentId) }
25686
+ },
25687
+ { shouldDirty: true }
25688
+ );
25344
25689
  }
25345
25690
  };
25346
25691
  const handleDescriptionChange = (agentId, description) => {
25347
- form.setValue("agents", {
25348
- ...selectedAgents,
25349
- [agentId]: { ...selectedAgents?.[agentId], description }
25350
- });
25692
+ form.setValue(
25693
+ "agents",
25694
+ {
25695
+ ...selectedAgents,
25696
+ [agentId]: { ...selectedAgents?.[agentId], description }
25697
+ },
25698
+ { shouldDirty: true }
25699
+ );
25351
25700
  };
25352
25701
  const handleRulesChange = (agentId, rules) => {
25353
- form.setValue("agents", {
25354
- ...selectedAgents,
25355
- [agentId]: { ...selectedAgents?.[agentId], rules }
25356
- });
25702
+ form.setValue(
25703
+ "agents",
25704
+ {
25705
+ ...selectedAgents,
25706
+ [agentId]: { ...selectedAgents?.[agentId], rules }
25707
+ },
25708
+ { shouldDirty: true }
25709
+ );
25357
25710
  };
25358
25711
  const filteredOptions = React.useMemo(() => {
25359
25712
  return options.filter((option) => option.label.toLowerCase().includes(search.toLowerCase()));
@@ -25437,31 +25790,47 @@ function ScorersPage() {
25437
25790
  if (isSet) {
25438
25791
  const next = { ...selectedScorers };
25439
25792
  delete next[scorerId];
25440
- form.setValue("scorers", next);
25793
+ form.setValue("scorers", next, { shouldDirty: true });
25441
25794
  } else {
25442
- form.setValue("scorers", {
25443
- ...selectedScorers,
25444
- [scorerId]: { ...selectedScorers?.[scorerId], description: getOriginalDescription(scorerId) }
25445
- });
25795
+ form.setValue(
25796
+ "scorers",
25797
+ {
25798
+ ...selectedScorers,
25799
+ [scorerId]: { ...selectedScorers?.[scorerId], description: getOriginalDescription(scorerId) }
25800
+ },
25801
+ { shouldDirty: true }
25802
+ );
25446
25803
  }
25447
25804
  };
25448
25805
  const handleDescriptionChange = (scorerId, description) => {
25449
- form.setValue("scorers", {
25450
- ...selectedScorers,
25451
- [scorerId]: { ...selectedScorers?.[scorerId], description }
25452
- });
25806
+ form.setValue(
25807
+ "scorers",
25808
+ {
25809
+ ...selectedScorers,
25810
+ [scorerId]: { ...selectedScorers?.[scorerId], description }
25811
+ },
25812
+ { shouldDirty: true }
25813
+ );
25453
25814
  };
25454
25815
  const handleSamplingChange = (scorerId, samplingConfig) => {
25455
- form.setValue("scorers", {
25456
- ...selectedScorers,
25457
- [scorerId]: { ...selectedScorers?.[scorerId], sampling: samplingConfig }
25458
- });
25816
+ form.setValue(
25817
+ "scorers",
25818
+ {
25819
+ ...selectedScorers,
25820
+ [scorerId]: { ...selectedScorers?.[scorerId], sampling: samplingConfig }
25821
+ },
25822
+ { shouldDirty: true }
25823
+ );
25459
25824
  };
25460
25825
  const handleRulesChange = (scorerId, rules) => {
25461
- form.setValue("scorers", {
25462
- ...selectedScorers,
25463
- [scorerId]: { ...selectedScorers?.[scorerId], rules }
25464
- });
25826
+ form.setValue(
25827
+ "scorers",
25828
+ {
25829
+ ...selectedScorers,
25830
+ [scorerId]: { ...selectedScorers?.[scorerId], rules }
25831
+ },
25832
+ { shouldDirty: true }
25833
+ );
25465
25834
  };
25466
25835
  const filteredOptions = React.useMemo(() => {
25467
25836
  return options.filter((option) => option.label.toLowerCase().includes(search.toLowerCase()));
@@ -25605,25 +25974,37 @@ function WorkflowsPage() {
25605
25974
  if (isSet) {
25606
25975
  const next = { ...selectedWorkflows };
25607
25976
  delete next[workflowId];
25608
- form.setValue("workflows", next);
25977
+ form.setValue("workflows", next, { shouldDirty: true });
25609
25978
  } else {
25610
- form.setValue("workflows", {
25611
- ...selectedWorkflows,
25612
- [workflowId]: { ...selectedWorkflows?.[workflowId], description: getOriginalDescription(workflowId) }
25613
- });
25979
+ form.setValue(
25980
+ "workflows",
25981
+ {
25982
+ ...selectedWorkflows,
25983
+ [workflowId]: { ...selectedWorkflows?.[workflowId], description: getOriginalDescription(workflowId) }
25984
+ },
25985
+ { shouldDirty: true }
25986
+ );
25614
25987
  }
25615
25988
  };
25616
25989
  const handleDescriptionChange = (workflowId, description) => {
25617
- form.setValue("workflows", {
25618
- ...selectedWorkflows,
25619
- [workflowId]: { ...selectedWorkflows?.[workflowId], description }
25620
- });
25990
+ form.setValue(
25991
+ "workflows",
25992
+ {
25993
+ ...selectedWorkflows,
25994
+ [workflowId]: { ...selectedWorkflows?.[workflowId], description }
25995
+ },
25996
+ { shouldDirty: true }
25997
+ );
25621
25998
  };
25622
25999
  const handleRulesChange = (workflowId, rules) => {
25623
- form.setValue("workflows", {
25624
- ...selectedWorkflows,
25625
- [workflowId]: { ...selectedWorkflows?.[workflowId], rules }
25626
- });
26000
+ form.setValue(
26001
+ "workflows",
26002
+ {
26003
+ ...selectedWorkflows,
26004
+ [workflowId]: { ...selectedWorkflows?.[workflowId], rules }
26005
+ },
26006
+ { shouldDirty: true }
26007
+ );
25627
26008
  };
25628
26009
  const filteredOptions = React.useMemo(() => {
25629
26010
  return options.filter((option) => option.label.toLowerCase().includes(search.toLowerCase()));
@@ -25720,22 +26101,45 @@ function MemoryPage() {
25720
26101
  }
25721
26102
  ) }),
25722
26103
  isEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
26104
+ /* @__PURE__ */ jsxRuntime.jsx(ObservationalMemoryEntity, {}),
25723
26105
  /* @__PURE__ */ jsxRuntime.jsx(LastMessagesEntity, {}),
25724
26106
  /* @__PURE__ */ jsxRuntime.jsx(SemanticRecallEntity, {}),
25725
- /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyEntity, {}),
25726
- /* @__PURE__ */ jsxRuntime.jsx(ObservationalMemoryEntity, {})
26107
+ /* @__PURE__ */ jsxRuntime.jsx(ReadOnlyEntity, {})
25727
26108
  ] })
25728
26109
  ] }) });
25729
26110
  }
25730
26111
  function LastMessagesEntity() {
25731
26112
  const { form, readOnly } = useAgentEditFormContext();
25732
26113
  const { control } = form;
26114
+ const lastMessages = reactHookForm.useWatch({ control, name: "memory.lastMessages" });
26115
+ const lastMessagesEnabled = lastMessages !== false;
25733
26116
  return /* @__PURE__ */ jsxRuntime.jsxs(Entity, { className: "flex-col gap-0 p-0 overflow-hidden", children: [
25734
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3 py-3 px-4", children: /* @__PURE__ */ jsxRuntime.jsxs(EntityContent, { children: [
25735
- /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: "Last Messages" }),
25736
- /* @__PURE__ */ jsxRuntime.jsx(EntityDescription, { children: "Number of recent messages to include in context" })
25737
- ] }) }),
25738
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface2 border-t border-border1 p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
26117
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 py-3 px-4", children: [
26118
+ /* @__PURE__ */ jsxRuntime.jsxs(EntityContent, { children: [
26119
+ /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: "Message History" }),
26120
+ /* @__PURE__ */ jsxRuntime.jsx(EntityDescription, { children: "Number of recent messages to include in context" })
26121
+ ] }),
26122
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
26123
+ reactHookForm.Controller,
26124
+ {
26125
+ name: "memory.lastMessages",
26126
+ control,
26127
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(
26128
+ Switch,
26129
+ {
26130
+ checked: lastMessagesEnabled,
26131
+ onCheckedChange: (checked) => {
26132
+ field.onChange(checked ? 40 : false);
26133
+ if (checked) {
26134
+ form.setValue("memory.observationalMemory.enabled", false, { shouldDirty: true });
26135
+ }
26136
+ }
26137
+ }
26138
+ )
26139
+ }
26140
+ )
26141
+ ] }),
26142
+ lastMessagesEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface2 border-t border-border1 p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
25739
26143
  reactHookForm.Controller,
25740
26144
  {
25741
26145
  name: "memory.lastMessages",
@@ -25856,7 +26260,18 @@ function ObservationalMemoryEntity() {
25856
26260
  {
25857
26261
  name: "memory.observationalMemory.enabled",
25858
26262
  control,
25859
- render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(Switch, { checked: field.value ?? false, onCheckedChange: field.onChange })
26263
+ render: ({ field }) => /* @__PURE__ */ jsxRuntime.jsx(
26264
+ Switch,
26265
+ {
26266
+ checked: field.value ?? false,
26267
+ onCheckedChange: (checked) => {
26268
+ field.onChange(checked);
26269
+ if (checked) {
26270
+ form.setValue("memory.lastMessages", false, { shouldDirty: true });
26271
+ }
26272
+ }
26273
+ }
26274
+ )
25860
26275
  }
25861
26276
  )
25862
26277
  ] }),
@@ -25885,7 +26300,7 @@ function ObservationalMemoryFields() {
25885
26300
  value: field.value ?? "",
25886
26301
  onValueChange: (v) => {
25887
26302
  field.onChange(v);
25888
- setValue("memory.observationalMemory.model.name", "");
26303
+ setValue("memory.observationalMemory.model.name", "", { shouldDirty: true });
25889
26304
  },
25890
26305
  variant: "light"
25891
26306
  }
@@ -25976,7 +26391,7 @@ function ObserverFields({ observerProvider }) {
25976
26391
  value: field.value ?? "",
25977
26392
  onValueChange: (v) => {
25978
26393
  field.onChange(v);
25979
- setValue("memory.observationalMemory.observation.model.name", "");
26394
+ setValue("memory.observationalMemory.observation.model.name", "", { shouldDirty: true });
25980
26395
  },
25981
26396
  variant: "light"
25982
26397
  }
@@ -26173,7 +26588,7 @@ function ReflectorFields({ reflectorProvider }) {
26173
26588
  value: field.value ?? "",
26174
26589
  onValueChange: (v) => {
26175
26590
  field.onChange(v);
26176
- setValue("memory.observationalMemory.reflection.model.name", "");
26591
+ setValue("memory.observationalMemory.reflection.model.name", "", { shouldDirty: true });
26177
26592
  },
26178
26593
  variant: "light"
26179
26594
  }
@@ -26842,118 +27257,1466 @@ function VariablesPage() {
26842
27257
  ] }) });
26843
27258
  }
26844
27259
 
26845
- const arrayToRecord = (arr) => {
26846
- const record = {};
26847
- for (const id of arr) {
26848
- record[id] = { description: void 0 };
26849
- }
26850
- return record;
27260
+ function useStoredSkills() {
27261
+ const client = react$1.useMastraClient();
27262
+ return reactQuery.useQuery({
27263
+ queryKey: ["stored-skills"],
27264
+ queryFn: () => client.listStoredSkills()
27265
+ });
27266
+ }
27267
+
27268
+ const useWorkspaceInfo = (workspaceId) => {
27269
+ const client = react$1.useMastraClient();
27270
+ return reactQuery.useQuery({
27271
+ queryKey: ["workspace", "info", workspaceId],
27272
+ queryFn: async () => {
27273
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27274
+ throw new Error("Workspace v1 not supported by core or client");
27275
+ }
27276
+ if (!workspaceId) {
27277
+ throw new Error("workspaceId is required");
27278
+ }
27279
+ const workspace = client.getWorkspace(workspaceId);
27280
+ return workspace.info();
27281
+ },
27282
+ enabled: !!workspaceId && compatibility.isWorkspaceV1Supported(client),
27283
+ retry: compatibility.shouldRetryWorkspaceQuery
27284
+ });
26851
27285
  };
26852
- const normalizeToolsToRecord = (tools) => {
26853
- if (!tools) return {};
26854
- if (!Array.isArray(tools)) return { ...tools };
26855
- const result = {};
26856
- for (const item of tools) {
26857
- if (typeof item === "string") {
26858
- result[item] = { description: void 0 };
26859
- } else {
26860
- Object.assign(result, item.value);
26861
- }
26862
- }
26863
- return result;
27286
+ const useWorkspaces = () => {
27287
+ const client = react$1.useMastraClient();
27288
+ return reactQuery.useQuery({
27289
+ queryKey: ["workspaces"],
27290
+ queryFn: async () => {
27291
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27292
+ throw new Error("Workspace v1 not supported by core or client");
27293
+ }
27294
+ return client.listWorkspaces();
27295
+ },
27296
+ retry: compatibility.shouldRetryWorkspaceQuery
27297
+ });
26864
27298
  };
26865
- const splitModelId = (id) => {
26866
- if (!id) return void 0;
26867
- const [p, ...rest] = id.split("/");
26868
- const n = rest.join("/");
26869
- return p && n ? { provider: p, name: n } : void 0;
27299
+ const useWorkspaceFiles = (path, options) => {
27300
+ const client = react$1.useMastraClient();
27301
+ return reactQuery.useQuery({
27302
+ queryKey: ["workspace", "files", path, options?.recursive, options?.workspaceId],
27303
+ queryFn: async () => {
27304
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27305
+ throw new Error("Workspace v1 not supported by core or client");
27306
+ }
27307
+ if (!options?.workspaceId) {
27308
+ throw new Error("workspaceId is required");
27309
+ }
27310
+ const workspace = client.getWorkspace(options.workspaceId);
27311
+ return workspace.listFiles(path, options?.recursive);
27312
+ },
27313
+ enabled: options?.enabled !== false && !!path && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27314
+ retry: compatibility.shouldRetryWorkspaceQuery
27315
+ });
26870
27316
  };
26871
- const joinModelId = (m) => m?.provider && m?.name ? `${m.provider}/${m.name}` : void 0;
26872
- const transformIntegrationToolsForApi = (integrationTools) => {
26873
- if (!integrationTools || Object.keys(integrationTools).length === 0) return void 0;
26874
- const result = {};
26875
- for (const [compositeKey, config] of Object.entries(integrationTools)) {
26876
- const separatorIndex = compositeKey.indexOf(":");
26877
- if (separatorIndex === -1) continue;
26878
- const providerId = compositeKey.slice(0, separatorIndex);
26879
- const toolSlug = compositeKey.slice(separatorIndex + 1);
26880
- if (!result[providerId]) {
26881
- result[providerId] = { tools: {} };
26882
- }
26883
- result[providerId].tools[toolSlug] = { description: config.description, rules: config.rules };
26884
- }
26885
- return result;
27317
+ const useWorkspaceFile = (path, options) => {
27318
+ const client = react$1.useMastraClient();
27319
+ return reactQuery.useQuery({
27320
+ queryKey: ["workspace", "file", path, options?.workspaceId],
27321
+ queryFn: async () => {
27322
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27323
+ throw new Error("Workspace v1 not supported by core or client");
27324
+ }
27325
+ if (!options?.workspaceId) {
27326
+ throw new Error("workspaceId is required");
27327
+ }
27328
+ const workspace = client.getWorkspace(options.workspaceId);
27329
+ return workspace.readFile(path, options?.encoding);
27330
+ },
27331
+ enabled: options?.enabled !== false && !!path && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27332
+ retry: compatibility.shouldRetryWorkspaceQuery
27333
+ });
26886
27334
  };
26887
- const normalizeIntegrationToolsToRecord = (integrationTools) => {
26888
- if (!integrationTools) return {};
26889
- const result = {};
26890
- for (const [providerId, providerConfig] of Object.entries(integrationTools)) {
26891
- if (providerConfig.tools) {
26892
- for (const [toolSlug, toolConfig] of Object.entries(providerConfig.tools)) {
26893
- result[`${providerId}:${toolSlug}`] = { description: toolConfig.description, rules: toolConfig.rules };
27335
+ const useWorkspaceFileStat = (path, options) => {
27336
+ const client = react$1.useMastraClient();
27337
+ return reactQuery.useQuery({
27338
+ queryKey: ["workspace", "stat", path, options?.workspaceId],
27339
+ queryFn: async () => {
27340
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27341
+ throw new Error("Workspace v1 not supported by core or client");
27342
+ }
27343
+ if (!options?.workspaceId) {
27344
+ throw new Error("workspaceId is required");
27345
+ }
27346
+ const workspace = client.getWorkspace(options.workspaceId);
27347
+ return workspace.stat(path);
27348
+ },
27349
+ enabled: options?.enabled !== false && !!path && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27350
+ retry: compatibility.shouldRetryWorkspaceQuery
27351
+ });
27352
+ };
27353
+ const useWriteWorkspaceFile = () => {
27354
+ const client = react$1.useMastraClient();
27355
+ const queryClient = reactQuery.useQueryClient();
27356
+ return reactQuery.useMutation({
27357
+ mutationFn: async (params) => {
27358
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27359
+ throw new Error("Workspace v1 not supported by core or client");
26894
27360
  }
27361
+ const workspace = client.getWorkspace(params.workspaceId);
27362
+ return workspace.writeFile(params.path, params.content, {
27363
+ encoding: params.encoding,
27364
+ recursive: params.recursive ?? true
27365
+ });
27366
+ },
27367
+ onSuccess: (_, variables) => {
27368
+ const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
27369
+ queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
27370
+ queryClient.invalidateQueries({ queryKey: ["workspace", "file", variables.path] });
26895
27371
  }
26896
- }
26897
- return result;
27372
+ });
26898
27373
  };
26899
- const mapInstructionBlocksToApi = (blocks) => (blocks ?? []).map((block) => ({
26900
- type: block.type,
26901
- content: block.content,
26902
- rules: block.rules
26903
- }));
26904
- const mapInstructionBlocksFromApi = (instructionsRaw) => {
26905
- const instructionsString = Array.isArray(instructionsRaw) ? instructionsRaw.map((b) => b.type === "prompt_block" ? b.content : "").filter(Boolean).join("\n\n") : instructionsRaw || "";
26906
- const instructionBlocks = Array.isArray(instructionsRaw) ? instructionsRaw.filter(
26907
- (b) => b.type === "prompt_block"
26908
- ).map((b) => createInstructionBlock(b.content, b.rules)) : [createInstructionBlock(instructionsRaw || "")];
26909
- return { instructionsString, instructionBlocks };
27374
+ const useWriteWorkspaceFileFromFile = () => {
27375
+ const client = react$1.useMastraClient();
27376
+ const queryClient = reactQuery.useQueryClient();
27377
+ return reactQuery.useMutation({
27378
+ mutationFn: async (params) => {
27379
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27380
+ throw new Error("Workspace v1 not supported by core or client");
27381
+ }
27382
+ const arrayBuffer = await params.file.arrayBuffer();
27383
+ const base64 = btoa(new Uint8Array(arrayBuffer).reduce((data, byte) => data + String.fromCharCode(byte), ""));
27384
+ const workspace = client.getWorkspace(params.workspaceId);
27385
+ return workspace.writeFile(params.path, base64, {
27386
+ encoding: "base64",
27387
+ recursive: params.recursive ?? true
27388
+ });
27389
+ },
27390
+ onSuccess: (_, variables) => {
27391
+ const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
27392
+ queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
27393
+ queryClient.invalidateQueries({ queryKey: ["workspace", "file", variables.path] });
27394
+ }
27395
+ });
26910
27396
  };
26911
- const mapScorersToApi = (scorers) => {
26912
- const entries = scorers ? Object.entries(scorers) : void 0;
26913
- if (!entries) return void 0;
26914
- return Object.fromEntries(
26915
- entries.map(([key, value]) => [
26916
- key,
26917
- {
26918
- description: value.description,
26919
- sampling: value.sampling ? {
26920
- type: value.sampling.type,
26921
- rate: value.sampling.rate || 0
26922
- } : void 0,
26923
- rules: value.rules
27397
+ const useDeleteWorkspaceFile = () => {
27398
+ const client = react$1.useMastraClient();
27399
+ const queryClient = reactQuery.useQueryClient();
27400
+ return reactQuery.useMutation({
27401
+ mutationFn: async (params) => {
27402
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27403
+ throw new Error("Workspace v1 not supported by core or client");
26924
27404
  }
26925
- ])
26926
- );
27405
+ const workspace = client.getWorkspace(params.workspaceId);
27406
+ return workspace.delete(params.path, {
27407
+ recursive: params.recursive,
27408
+ force: params.force
27409
+ });
27410
+ },
27411
+ onSuccess: (_, variables) => {
27412
+ const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
27413
+ queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
27414
+ queryClient.invalidateQueries({ queryKey: ["workspace", "file", variables.path] });
27415
+ }
27416
+ });
26927
27417
  };
26928
- const normalizeScorersFromApi = (scorers) => {
26929
- if (!scorers) return {};
26930
- let record;
26931
- if (Array.isArray(scorers)) {
26932
- record = {};
26933
- for (const variant of scorers) {
26934
- Object.assign(record, variant.value);
27418
+ const useCreateWorkspaceDirectory = () => {
27419
+ const client = react$1.useMastraClient();
27420
+ const queryClient = reactQuery.useQueryClient();
27421
+ return reactQuery.useMutation({
27422
+ mutationFn: async (params) => {
27423
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27424
+ throw new Error("Workspace v1 not supported by core or client");
27425
+ }
27426
+ const workspace = client.getWorkspace(params.workspaceId);
27427
+ return workspace.mkdir(params.path, params.recursive);
27428
+ },
27429
+ onSuccess: (_, variables) => {
27430
+ const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
27431
+ queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
26935
27432
  }
26936
- } else {
26937
- record = scorers;
26938
- }
26939
- const result = {};
26940
- for (const [key, value] of Object.entries(record)) {
26941
- result[key] = {
26942
- description: value.description,
26943
- sampling: value.sampling?.type === "ratio" ? { type: "ratio", rate: value.sampling.rate } : void 0,
26944
- rules: value.rules
26945
- };
26946
- }
26947
- return result;
27433
+ });
26948
27434
  };
26949
- const buildObservationalMemoryForApi = (om) => {
26950
- if (!om?.enabled) return void 0;
26951
- const modelId = joinModelId(om.model);
26952
- const obsModelId = joinModelId(om.observation?.model);
26953
- const observation = obsModelId || om.observation?.messageTokens || om.observation?.maxTokensPerBatch || om.observation?.bufferTokens !== void 0 || om.observation?.bufferActivation !== void 0 || om.observation?.blockAfter !== void 0 ? {
26954
- model: obsModelId,
26955
- messageTokens: om.observation?.messageTokens,
26956
- maxTokensPerBatch: om.observation?.maxTokensPerBatch,
27435
+ const useSearchWorkspace = () => {
27436
+ const client = react$1.useMastraClient();
27437
+ return reactQuery.useMutation({
27438
+ mutationFn: async (params) => {
27439
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27440
+ throw new Error("Workspace v1 not supported by core or client");
27441
+ }
27442
+ const workspace = client.getWorkspace(params.workspaceId);
27443
+ return workspace.search({
27444
+ query: params.query,
27445
+ topK: params.topK,
27446
+ mode: params.mode,
27447
+ minScore: params.minScore
27448
+ });
27449
+ }
27450
+ });
27451
+ };
27452
+ const useIndexWorkspaceContent = () => {
27453
+ const client = react$1.useMastraClient();
27454
+ return reactQuery.useMutation({
27455
+ mutationFn: async (params) => {
27456
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27457
+ throw new Error("Workspace v1 not supported by core or client");
27458
+ }
27459
+ const workspace = client.getWorkspace(params.workspaceId);
27460
+ return workspace.index({
27461
+ path: params.path,
27462
+ content: params.content,
27463
+ metadata: params.metadata
27464
+ });
27465
+ }
27466
+ });
27467
+ };
27468
+
27469
+ const useWorkspaceSkills = (options) => {
27470
+ const client = react$1.useMastraClient();
27471
+ return reactQuery.useQuery({
27472
+ queryKey: ["workspace", "skills", options?.workspaceId],
27473
+ queryFn: async () => {
27474
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27475
+ throw new Error("Workspace v1 not supported by core or client");
27476
+ }
27477
+ if (!options?.workspaceId) {
27478
+ throw new Error("workspaceId is required");
27479
+ }
27480
+ const workspace = client.getWorkspace(options.workspaceId);
27481
+ return workspace.listSkills();
27482
+ },
27483
+ enabled: !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27484
+ retry: compatibility.shouldRetryWorkspaceQuery
27485
+ });
27486
+ };
27487
+ const useWorkspaceSkill = (skillName, options) => {
27488
+ const client = react$1.useMastraClient();
27489
+ return reactQuery.useQuery({
27490
+ queryKey: ["workspace", "skills", skillName, options?.workspaceId],
27491
+ queryFn: async () => {
27492
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27493
+ throw new Error("Workspace v1 not supported by core or client");
27494
+ }
27495
+ if (!options?.workspaceId) {
27496
+ throw new Error("workspaceId is required");
27497
+ }
27498
+ const workspace = client.getWorkspace(options.workspaceId);
27499
+ const skill = workspace.getSkill(skillName);
27500
+ return skill.details();
27501
+ },
27502
+ enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27503
+ retry: compatibility.shouldRetryWorkspaceQuery
27504
+ });
27505
+ };
27506
+ const useWorkspaceSkillReferences = (skillName, options) => {
27507
+ const client = react$1.useMastraClient();
27508
+ return reactQuery.useQuery({
27509
+ queryKey: ["workspace", "skills", skillName, "references", options?.workspaceId],
27510
+ queryFn: async () => {
27511
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27512
+ throw new Error("Workspace v1 not supported by core or client");
27513
+ }
27514
+ if (!options?.workspaceId) {
27515
+ throw new Error("workspaceId is required");
27516
+ }
27517
+ const workspace = client.getWorkspace(options.workspaceId);
27518
+ const skill = workspace.getSkill(skillName);
27519
+ return skill.listReferences();
27520
+ },
27521
+ enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27522
+ retry: compatibility.shouldRetryWorkspaceQuery
27523
+ });
27524
+ };
27525
+ const useWorkspaceSkillReference = (skillName, referencePath, options) => {
27526
+ const client = react$1.useMastraClient();
27527
+ return reactQuery.useQuery({
27528
+ queryKey: ["workspace", "skills", skillName, "references", referencePath, options?.workspaceId],
27529
+ queryFn: async () => {
27530
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27531
+ throw new Error("Workspace v1 not supported by core or client");
27532
+ }
27533
+ if (!options?.workspaceId) {
27534
+ throw new Error("workspaceId is required");
27535
+ }
27536
+ const workspace = client.getWorkspace(options.workspaceId);
27537
+ const skill = workspace.getSkill(skillName);
27538
+ return skill.getReference(referencePath);
27539
+ },
27540
+ enabled: options?.enabled !== false && !!skillName && !!referencePath && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27541
+ retry: compatibility.shouldRetryWorkspaceQuery
27542
+ });
27543
+ };
27544
+ const useSearchWorkspaceSkills = () => {
27545
+ const client = react$1.useMastraClient();
27546
+ return reactQuery.useMutation({
27547
+ mutationFn: async (params) => {
27548
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27549
+ throw new Error("Workspace v1 not supported by core or client");
27550
+ }
27551
+ const workspace = client.getWorkspace(params.workspaceId);
27552
+ return workspace.searchSkills(params);
27553
+ }
27554
+ });
27555
+ };
27556
+ const useAgentSkill = (agentId, skillName, options) => {
27557
+ const client = react$1.useMastraClient();
27558
+ return reactQuery.useQuery({
27559
+ queryKey: ["agents", agentId, "skills", skillName, options?.workspaceId],
27560
+ queryFn: async () => {
27561
+ if (!compatibility.isWorkspaceV1Supported(client)) {
27562
+ throw new Error("Workspace v1 not supported by core or client");
27563
+ }
27564
+ if (!options?.workspaceId) {
27565
+ throw new Error("workspaceId is required");
27566
+ }
27567
+ const workspace = client.getWorkspace(options.workspaceId);
27568
+ const skill = workspace.getSkill(skillName);
27569
+ return skill.details();
27570
+ },
27571
+ enabled: options?.enabled !== false && !!agentId && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
27572
+ retry: compatibility.shouldRetryWorkspaceQuery
27573
+ });
27574
+ };
27575
+
27576
+ const useSearchSkillsSh = (workspaceId) => {
27577
+ const client = react$1.useMastraClient();
27578
+ return reactQuery.useMutation({
27579
+ mutationFn: async (query) => {
27580
+ if (!workspaceId) {
27581
+ throw new Error("Workspace ID is required");
27582
+ }
27583
+ const baseUrl = client.options.baseUrl || "";
27584
+ const url = `${baseUrl}/api/workspaces/${workspaceId}/skills-sh/search?q=${encodeURIComponent(query)}&limit=10`;
27585
+ const response = await fetch(url);
27586
+ if (!response.ok) {
27587
+ throw new Error(`Failed to search skills: ${response.statusText}`);
27588
+ }
27589
+ return response.json().catch(() => {
27590
+ throw new Error("Invalid response from server");
27591
+ });
27592
+ }
27593
+ });
27594
+ };
27595
+ const usePopularSkillsSh = (workspaceId) => {
27596
+ const client = react$1.useMastraClient();
27597
+ return reactQuery.useQuery({
27598
+ queryKey: ["skills-sh", "popular", workspaceId],
27599
+ queryFn: async () => {
27600
+ if (!workspaceId) {
27601
+ throw new Error("Workspace ID is required");
27602
+ }
27603
+ const baseUrl = client.options.baseUrl || "";
27604
+ const url = `${baseUrl}/api/workspaces/${workspaceId}/skills-sh/popular?limit=10&offset=0`;
27605
+ const response = await fetch(url);
27606
+ if (!response.ok) {
27607
+ throw new Error(`Failed to fetch popular skills: ${response.statusText}`);
27608
+ }
27609
+ return response.json().catch(() => {
27610
+ throw new Error("Invalid response from server");
27611
+ });
27612
+ },
27613
+ staleTime: 5 * 60 * 1e3,
27614
+ // 5 minutes
27615
+ enabled: !!workspaceId
27616
+ });
27617
+ };
27618
+ const useSkillPreview = (workspaceId, owner, repo, skillPath, options) => {
27619
+ const client = react$1.useMastraClient();
27620
+ return reactQuery.useQuery({
27621
+ queryKey: ["skills-sh", "preview", workspaceId, owner, repo, skillPath],
27622
+ queryFn: async () => {
27623
+ if (!workspaceId || !owner || !repo || !skillPath) {
27624
+ throw new Error("workspaceId, owner, repo, and skillPath are required");
27625
+ }
27626
+ const baseUrl = client.options.baseUrl || "";
27627
+ const params = new URLSearchParams({ owner, repo, path: skillPath });
27628
+ const url = `${baseUrl}/api/workspaces/${workspaceId}/skills-sh/preview?${params}`;
27629
+ const response = await fetch(url);
27630
+ if (!response.ok) {
27631
+ throw new Error(`Failed to fetch preview: ${response.statusText}`);
27632
+ }
27633
+ const data = await response.json().catch(() => {
27634
+ throw new Error("Invalid response from server");
27635
+ });
27636
+ return data.content;
27637
+ },
27638
+ enabled: options?.enabled !== false && !!workspaceId && !!owner && !!repo && !!skillPath,
27639
+ retry: false
27640
+ });
27641
+ };
27642
+ const useInstallSkill = () => {
27643
+ const client = react$1.useMastraClient();
27644
+ const queryClient = reactQuery.useQueryClient();
27645
+ return reactQuery.useMutation({
27646
+ mutationFn: async (params) => {
27647
+ const [owner, repo] = params.repository.split("/");
27648
+ if (!owner || !repo) {
27649
+ throw new Error("Invalid repository format. Expected owner/repo");
27650
+ }
27651
+ const baseUrl = client.options.baseUrl || "";
27652
+ const url = `${baseUrl}/api/workspaces/${params.workspaceId}/skills-sh/install`;
27653
+ const body = { owner, repo, skillName: params.skillName };
27654
+ if (params.mount) {
27655
+ body.mount = params.mount;
27656
+ }
27657
+ const response = await fetch(url, {
27658
+ method: "POST",
27659
+ headers: { "Content-Type": "application/json" },
27660
+ body: JSON.stringify(body)
27661
+ });
27662
+ if (!response.ok) {
27663
+ const error = await response.json().catch(() => ({}));
27664
+ throw new Error(error.error || error.message || `Failed to install skill: ${response.statusText}`);
27665
+ }
27666
+ return response.json().catch(() => {
27667
+ throw new Error("Invalid response from server");
27668
+ });
27669
+ },
27670
+ onSuccess: (_, variables) => {
27671
+ queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
27672
+ }
27673
+ });
27674
+ };
27675
+ const useUpdateSkills = () => {
27676
+ const client = react$1.useMastraClient();
27677
+ const queryClient = reactQuery.useQueryClient();
27678
+ return reactQuery.useMutation({
27679
+ mutationFn: async (params) => {
27680
+ const baseUrl = client.options.baseUrl || "";
27681
+ const url = `${baseUrl}/api/workspaces/${params.workspaceId}/skills-sh/update`;
27682
+ const response = await fetch(url, {
27683
+ method: "POST",
27684
+ headers: { "Content-Type": "application/json" },
27685
+ body: JSON.stringify({ skillName: params.skillName })
27686
+ });
27687
+ if (!response.ok) {
27688
+ const error = await response.json().catch(() => ({}));
27689
+ throw new Error(error.error || error.message || `Failed to update skill: ${response.statusText}`);
27690
+ }
27691
+ return response.json().catch(() => {
27692
+ throw new Error("Invalid response from server");
27693
+ });
27694
+ },
27695
+ onSuccess: (_, variables) => {
27696
+ queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
27697
+ }
27698
+ });
27699
+ };
27700
+ const useRemoveSkill = () => {
27701
+ const client = react$1.useMastraClient();
27702
+ const queryClient = reactQuery.useQueryClient();
27703
+ return reactQuery.useMutation({
27704
+ mutationFn: async (params) => {
27705
+ const baseUrl = client.options.baseUrl || "";
27706
+ const url = `${baseUrl}/api/workspaces/${params.workspaceId}/skills-sh/remove`;
27707
+ const response = await fetch(url, {
27708
+ method: "POST",
27709
+ headers: { "Content-Type": "application/json" },
27710
+ body: JSON.stringify({ skillName: params.skillName })
27711
+ });
27712
+ if (!response.ok) {
27713
+ const error = await response.json().catch(() => ({}));
27714
+ throw new Error(error.error || error.message || `Failed to remove skill: ${response.statusText}`);
27715
+ }
27716
+ return response.json().catch(() => {
27717
+ throw new Error("Invalid response from server");
27718
+ });
27719
+ },
27720
+ onSuccess: (_, variables) => {
27721
+ queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
27722
+ }
27723
+ });
27724
+ };
27725
+ function parseSkillSource(topSource, skillName) {
27726
+ let cleanSource = topSource.replace(/^https?:\/\//, "");
27727
+ cleanSource = cleanSource.replace(/^github\.com\//, "");
27728
+ cleanSource = cleanSource.replace(/\/$/, "");
27729
+ const parts = cleanSource.split("/").filter(Boolean);
27730
+ if (parts.length < 2) {
27731
+ return null;
27732
+ }
27733
+ const owner = parts[0];
27734
+ const repo = parts[1];
27735
+ let skillPath;
27736
+ if (parts.length > 2) {
27737
+ skillPath = parts.slice(2).join("/");
27738
+ } else if (skillName) {
27739
+ skillPath = skillName;
27740
+ } else {
27741
+ return null;
27742
+ }
27743
+ return {
27744
+ owner,
27745
+ repo,
27746
+ skillPath
27747
+ };
27748
+ }
27749
+
27750
+ const TreeContext = React__namespace.createContext(null);
27751
+ function TreeProvider({ children, value }) {
27752
+ return /* @__PURE__ */ jsxRuntime.jsx(TreeContext.Provider, { value, children });
27753
+ }
27754
+ function useTreeContext() {
27755
+ return React__namespace.useContext(TreeContext);
27756
+ }
27757
+ const TreeDepthContext = React__namespace.createContext(0);
27758
+ function TreeDepthProvider({ children, depth }) {
27759
+ return /* @__PURE__ */ jsxRuntime.jsx(TreeDepthContext.Provider, { value: depth, children });
27760
+ }
27761
+ function useTreeDepth() {
27762
+ return React__namespace.useContext(TreeDepthContext);
27763
+ }
27764
+
27765
+ const TreeRoot = React__namespace.forwardRef(
27766
+ ({ selectedId, onSelect, className, children }, ref) => {
27767
+ const contextValue = React__namespace.useMemo(() => ({ selectedId, onSelect }), [selectedId, onSelect]);
27768
+ return /* @__PURE__ */ jsxRuntime.jsx(TreeProvider, { value: contextValue, children: /* @__PURE__ */ jsxRuntime.jsx(TreeDepthProvider, { depth: 0, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { ref, role: "tree", className: cn("flex flex-col text-xs", className), children }) }) });
27769
+ }
27770
+ );
27771
+ TreeRoot.displayName = "Tree";
27772
+
27773
+ const TreeFolder = React__namespace.forwardRef(
27774
+ ({ defaultOpen, open, onOpenChange, className, children }, ref) => {
27775
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { ref, role: "treeitem", className: cn("flex flex-col", className), children: /* @__PURE__ */ jsxRuntime.jsx(Collapsible, { defaultOpen, open, onOpenChange, children }) });
27776
+ }
27777
+ );
27778
+ TreeFolder.displayName = "Tree.Folder";
27779
+
27780
+ const TreeFolderTrigger = React__namespace.forwardRef(
27781
+ ({ className, children, actions }, ref) => {
27782
+ const depth = useTreeDepth();
27783
+ return /* @__PURE__ */ jsxRuntime.jsxs(
27784
+ "div",
27785
+ {
27786
+ ref,
27787
+ className: cn(
27788
+ "group flex h-7 min-w-0 w-full items-center rounded-sm hover:bg-surface4",
27789
+ transitions.colors,
27790
+ className
27791
+ ),
27792
+ children: [
27793
+ /* @__PURE__ */ jsxRuntime.jsxs(
27794
+ CollapsibleTrigger,
27795
+ {
27796
+ className: cn(
27797
+ "flex h-7 min-w-0 flex-1 cursor-pointer items-center gap-1.5 rounded-sm px-1",
27798
+ focusRing.visible
27799
+ ),
27800
+ style: { paddingLeft: depth * 12 },
27801
+ children: [
27802
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "size-3 shrink-0 text-neutral3" }),
27803
+ children
27804
+ ]
27805
+ }
27806
+ ),
27807
+ actions && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 pr-1", onClick: (e) => e.stopPropagation(), children: actions })
27808
+ ]
27809
+ }
27810
+ );
27811
+ }
27812
+ );
27813
+ TreeFolderTrigger.displayName = "Tree.FolderTrigger";
27814
+
27815
+ const TreeFolderContent = React__namespace.forwardRef(
27816
+ ({ className, children }, ref) => {
27817
+ const depth = useTreeDepth();
27818
+ return /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent, { ref, className: cn(className), children: /* @__PURE__ */ jsxRuntime.jsx(TreeDepthProvider, { depth: depth + 1, children: /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "group", className: "flex flex-col", children }) }) });
27819
+ }
27820
+ );
27821
+ TreeFolderContent.displayName = "Tree.FolderContent";
27822
+
27823
+ const TreeFile = React__namespace.forwardRef(({ id, className, children }, ref) => {
27824
+ const treeCtx = useTreeContext();
27825
+ const depth = useTreeDepth();
27826
+ const isSelected = id != null && treeCtx?.selectedId === id;
27827
+ const handleClick = () => {
27828
+ if (id != null && treeCtx?.onSelect) {
27829
+ treeCtx.onSelect(id);
27830
+ }
27831
+ };
27832
+ const handleKeyDown = (e) => {
27833
+ if ((e.key === "Enter" || e.key === " ") && id != null && treeCtx?.onSelect) {
27834
+ e.preventDefault();
27835
+ treeCtx.onSelect(id);
27836
+ }
27837
+ };
27838
+ return /* @__PURE__ */ jsxRuntime.jsx(
27839
+ "li",
27840
+ {
27841
+ ref,
27842
+ role: "treeitem",
27843
+ "aria-selected": isSelected || void 0,
27844
+ tabIndex: 0,
27845
+ className: cn(
27846
+ "group flex h-7 min-w-0 cursor-pointer items-center gap-1.5 rounded-sm px-1",
27847
+ transitions.colors,
27848
+ focusRing.visible,
27849
+ "hover:bg-surface4",
27850
+ isSelected && "bg-surface4 text-neutral6",
27851
+ className
27852
+ ),
27853
+ style: { paddingLeft: depth * 12 + 18 },
27854
+ onClick: handleClick,
27855
+ onKeyDown: handleKeyDown,
27856
+ children
27857
+ }
27858
+ );
27859
+ });
27860
+ TreeFile.displayName = "Tree.File";
27861
+
27862
+ const TreeIcon = React__namespace.forwardRef(({ className, children }, ref) => /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("flex shrink-0 items-center [&>svg]:size-3.5", className), children }));
27863
+ TreeIcon.displayName = "Tree.Icon";
27864
+
27865
+ const TreeLabel = React__namespace.forwardRef(({ className, children }, ref) => /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("truncate text-neutral5", className), children }));
27866
+ TreeLabel.displayName = "Tree.Label";
27867
+
27868
+ const TreeInput = React__namespace.forwardRef(
27869
+ ({ type, onSubmit, onCancel, defaultValue = "", placeholder, autoFocus = true, className }, ref) => {
27870
+ const depth = useTreeDepth();
27871
+ const inputRef = React__namespace.useRef(null);
27872
+ const submittedRef = React__namespace.useRef(false);
27873
+ const handleSubmit = React__namespace.useCallback(
27874
+ (value) => {
27875
+ if (submittedRef.current) return;
27876
+ const trimmed = value.trim();
27877
+ if (trimmed) {
27878
+ submittedRef.current = true;
27879
+ onSubmit(trimmed);
27880
+ } else {
27881
+ onCancel?.();
27882
+ }
27883
+ },
27884
+ [onSubmit, onCancel]
27885
+ );
27886
+ const handleKeyDown = React__namespace.useCallback(
27887
+ (e) => {
27888
+ if (e.key === "Enter") {
27889
+ e.preventDefault();
27890
+ handleSubmit(e.currentTarget.value);
27891
+ } else if (e.key === "Escape") {
27892
+ e.preventDefault();
27893
+ onCancel?.();
27894
+ }
27895
+ },
27896
+ [handleSubmit, onCancel]
27897
+ );
27898
+ const handleBlur = React__namespace.useCallback(
27899
+ (e) => {
27900
+ handleSubmit(e.currentTarget.value);
27901
+ },
27902
+ [handleSubmit]
27903
+ );
27904
+ const handleFocus = React__namespace.useCallback((e) => {
27905
+ e.currentTarget.select();
27906
+ }, []);
27907
+ const Icon = type === "folder" ? lucideReact.Folder : lucideReact.File;
27908
+ return /* @__PURE__ */ jsxRuntime.jsxs(
27909
+ "li",
27910
+ {
27911
+ ref,
27912
+ role: "treeitem",
27913
+ className: cn(
27914
+ "group flex h-7 min-w-0 items-center gap-1.5 rounded-sm px-1",
27915
+ transitions.colors,
27916
+ "focus-within:outline-none focus-within:ring-1 focus-within:ring-accent1 focus-within:shadow-focus-ring",
27917
+ className
27918
+ ),
27919
+ style: { paddingLeft: depth * 12 + 18 },
27920
+ children: [
27921
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex shrink-0 items-center [&>svg]:size-3.5", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "text-neutral3" }) }),
27922
+ /* @__PURE__ */ jsxRuntime.jsx(
27923
+ "input",
27924
+ {
27925
+ ref: inputRef,
27926
+ type: "text",
27927
+ defaultValue,
27928
+ placeholder,
27929
+ autoFocus,
27930
+ onKeyDown: handleKeyDown,
27931
+ onBlur: handleBlur,
27932
+ onFocus: handleFocus,
27933
+ className: "min-w-0 flex-1 border-none bg-transparent text-xs text-neutral5 outline-none placeholder:text-neutral3"
27934
+ }
27935
+ )
27936
+ ]
27937
+ }
27938
+ );
27939
+ }
27940
+ );
27941
+ TreeInput.displayName = "Tree.Input";
27942
+
27943
+ const Tree = Object.assign(TreeRoot, {
27944
+ Folder: TreeFolder,
27945
+ FolderTrigger: TreeFolderTrigger,
27946
+ FolderContent: TreeFolderContent,
27947
+ File: TreeFile,
27948
+ Icon: TreeIcon,
27949
+ Label: TreeLabel,
27950
+ Input: TreeInput
27951
+ });
27952
+
27953
+ const STRUCTURAL_IDS = /* @__PURE__ */ new Set(["root", "skill-md", "license-md", "references", "scripts", "assets"]);
27954
+ function slugify(name) {
27955
+ return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
27956
+ }
27957
+ function createInitialStructure(name) {
27958
+ const slug = slugify(name) || "untitled";
27959
+ return [
27960
+ {
27961
+ id: "root",
27962
+ name: slug,
27963
+ type: "folder",
27964
+ children: [
27965
+ { id: "skill-md", name: "SKILL.md", type: "file", content: "" },
27966
+ { id: "license-md", name: "LICENSE.md", type: "file", content: "" },
27967
+ { id: "references", name: "references", type: "folder", children: [] },
27968
+ { id: "scripts", name: "scripts", type: "folder", children: [] },
27969
+ { id: "assets", name: "assets", type: "folder", children: [] }
27970
+ ]
27971
+ }
27972
+ ];
27973
+ }
27974
+ function updateRootFolderName(files, name) {
27975
+ const slug = slugify(name) || "untitled";
27976
+ return files.map((node) => node.id === "root" ? { ...node, name: slug } : node);
27977
+ }
27978
+ function extractSkillInstructions(files) {
27979
+ const root = files.find((n) => n.id === "root");
27980
+ if (!root?.children) return "";
27981
+ const skillMd = root.children.find((n) => n.id === "skill-md");
27982
+ return skillMd?.content ?? "";
27983
+ }
27984
+ function extractSkillLicense(files) {
27985
+ const root = files.find((n) => n.id === "root");
27986
+ if (!root?.children) return void 0;
27987
+ const licenseMd = root.children.find((n) => n.id === "license-md");
27988
+ const content = licenseMd?.content?.trim();
27989
+ return content || void 0;
27990
+ }
27991
+ function isImageContent(content) {
27992
+ return !!content && content.startsWith("data:image/");
27993
+ }
27994
+ function getFileIcon$1(name) {
27995
+ const ext = name.split(".").pop()?.toLowerCase();
27996
+ switch (ext) {
27997
+ case "ts":
27998
+ case "tsx":
27999
+ case "js":
28000
+ case "jsx":
28001
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCode, { className: "text-blue-400" });
28002
+ case "json":
28003
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileJson, { className: "text-yellow-400" });
28004
+ case "md":
28005
+ case "mdx":
28006
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "text-neutral4" });
28007
+ case "png":
28008
+ case "jpg":
28009
+ case "jpeg":
28010
+ case "gif":
28011
+ case "svg":
28012
+ case "webp":
28013
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Image, { className: "text-purple-400" });
28014
+ default:
28015
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.File, { className: "text-neutral4" });
28016
+ }
28017
+ }
28018
+ function getFolderIcon(isOpen) {
28019
+ return isOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderOpen, { className: "text-amber-400" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Folder, { className: "text-amber-400" });
28020
+ }
28021
+ function insertNode(nodes, parentId, newNode) {
28022
+ return nodes.map((node) => {
28023
+ if (node.id === parentId && node.type === "folder") {
28024
+ return { ...node, children: [...node.children ?? [], newNode] };
28025
+ }
28026
+ if (node.children) {
28027
+ return { ...node, children: insertNode(node.children, parentId, newNode) };
28028
+ }
28029
+ return node;
28030
+ });
28031
+ }
28032
+ function removeNode(nodes, nodeId) {
28033
+ return nodes.filter((node) => node.id !== nodeId).map((node) => {
28034
+ if (node.children) {
28035
+ return { ...node, children: removeNode(node.children, nodeId) };
28036
+ }
28037
+ return node;
28038
+ });
28039
+ }
28040
+ function updateNodeContent(nodes, nodeId, content) {
28041
+ return nodes.map((node) => {
28042
+ if (node.id === nodeId) {
28043
+ return { ...node, content };
28044
+ }
28045
+ if (node.children) {
28046
+ return { ...node, children: updateNodeContent(node.children, nodeId, content) };
28047
+ }
28048
+ return node;
28049
+ });
28050
+ }
28051
+ function FolderAddAction({ tooltip, onClick }) {
28052
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-0 group-hover:opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx(IconButton, { size: "sm", variant: "ghost", tooltip, onClick, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}) }) });
28053
+ }
28054
+ function FileDeleteAction({ nodeId, onRemove }) {
28055
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto shrink-0 opacity-0 group-hover:opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx(
28056
+ IconButton,
28057
+ {
28058
+ size: "sm",
28059
+ variant: "ghost",
28060
+ tooltip: "Delete file",
28061
+ onClick: (e) => {
28062
+ e.stopPropagation();
28063
+ onRemove(nodeId);
28064
+ },
28065
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, {})
28066
+ }
28067
+ ) });
28068
+ }
28069
+ function UserFileList({
28070
+ nodes,
28071
+ readOnly,
28072
+ onRemove
28073
+ }) {
28074
+ return nodes.filter((n) => !STRUCTURAL_IDS.has(n.id)).map((node) => /* @__PURE__ */ jsxRuntime.jsxs(Tree.File, { id: node.id, children: [
28075
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFileIcon$1(node.name) }),
28076
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: node.name }),
28077
+ !readOnly && !STRUCTURAL_IDS.has(node.id) && /* @__PURE__ */ jsxRuntime.jsx(FileDeleteAction, { nodeId: node.id, onRemove })
28078
+ ] }, node.id));
28079
+ }
28080
+ function SkillFileTree({ files, onChange, selectedFileId, onSelectFile, readOnly }) {
28081
+ const [pendingInput, setPendingInput] = React.useState(null);
28082
+ const [openFolders, setOpenFolders] = React.useState({
28083
+ references: true,
28084
+ scripts: true,
28085
+ assets: true
28086
+ });
28087
+ const imageInputRef = React.useRef(null);
28088
+ const setFolderOpen = React.useCallback((folderId, open) => {
28089
+ setOpenFolders((prev) => ({ ...prev, [folderId]: open }));
28090
+ }, []);
28091
+ const handleAddFile = React.useCallback(
28092
+ (parentId) => {
28093
+ setFolderOpen(parentId, true);
28094
+ setPendingInput({ parentId, type: "file" });
28095
+ },
28096
+ [setFolderOpen]
28097
+ );
28098
+ const handleAddImage = React.useCallback(() => {
28099
+ setFolderOpen("assets", true);
28100
+ imageInputRef.current?.click();
28101
+ }, [setFolderOpen]);
28102
+ const handleImagePicked = React.useCallback(
28103
+ (e) => {
28104
+ const file = e.target.files?.[0];
28105
+ if (!file) return;
28106
+ const reader = new FileReader();
28107
+ reader.onload = () => {
28108
+ const base64 = reader.result;
28109
+ const newNode = {
28110
+ id: uuid.v4(),
28111
+ name: file.name,
28112
+ type: "file",
28113
+ content: base64
28114
+ };
28115
+ onChange(insertNode(files, "assets", newNode));
28116
+ onSelectFile(newNode.id);
28117
+ };
28118
+ reader.readAsDataURL(file);
28119
+ e.target.value = "";
28120
+ },
28121
+ [files, onChange, onSelectFile]
28122
+ );
28123
+ const handleInputSubmit = React.useCallback(
28124
+ (name) => {
28125
+ if (!pendingInput) return;
28126
+ const newNode = {
28127
+ id: uuid.v4(),
28128
+ name,
28129
+ type: "file",
28130
+ content: ""
28131
+ };
28132
+ onChange(insertNode(files, pendingInput.parentId, newNode));
28133
+ setPendingInput(null);
28134
+ },
28135
+ [pendingInput, files, onChange]
28136
+ );
28137
+ const handleInputCancel = React.useCallback(() => {
28138
+ setPendingInput(null);
28139
+ }, []);
28140
+ const handleRemove = React.useCallback(
28141
+ (nodeId) => {
28142
+ if (STRUCTURAL_IDS.has(nodeId)) return;
28143
+ if (selectedFileId === nodeId) {
28144
+ onSelectFile(null);
28145
+ }
28146
+ onChange(removeNode(files, nodeId));
28147
+ },
28148
+ [files, onChange, selectedFileId, onSelectFile]
28149
+ );
28150
+ const root = files.find((n) => n.id === "root");
28151
+ if (!root?.children) return null;
28152
+ const referencesFolder = root.children.find((n) => n.id === "references");
28153
+ const scriptsFolder = root.children.find((n) => n.id === "scripts");
28154
+ const assetsFolder = root.children.find((n) => n.id === "assets");
28155
+ return /* @__PURE__ */ jsxRuntime.jsxs(TooltipProvider, { children: [
28156
+ /* @__PURE__ */ jsxRuntime.jsx("input", { ref: imageInputRef, type: "file", accept: "image/*", className: "hidden", onChange: handleImagePicked }),
28157
+ /* @__PURE__ */ jsxRuntime.jsx(Tree, { selectedId: selectedFileId ?? void 0, onSelect: onSelectFile, children: /* @__PURE__ */ jsxRuntime.jsxs(Tree.Folder, { defaultOpen: true, children: [
28158
+ /* @__PURE__ */ jsxRuntime.jsxs(Tree.FolderTrigger, { children: [
28159
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFolderIcon(true) }),
28160
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: root.name })
28161
+ ] }),
28162
+ /* @__PURE__ */ jsxRuntime.jsxs(Tree.FolderContent, { children: [
28163
+ /* @__PURE__ */ jsxRuntime.jsxs(Tree.File, { id: "skill-md", children: [
28164
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFileIcon$1("SKILL.md") }),
28165
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: "SKILL.md" })
28166
+ ] }),
28167
+ /* @__PURE__ */ jsxRuntime.jsxs(Tree.File, { id: "license-md", children: [
28168
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFileIcon$1("LICENSE.md") }),
28169
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: "LICENSE.md" })
28170
+ ] }),
28171
+ referencesFolder && /* @__PURE__ */ jsxRuntime.jsxs(Tree.Folder, { open: openFolders.references, onOpenChange: (open) => setFolderOpen("references", open), children: [
28172
+ /* @__PURE__ */ jsxRuntime.jsxs(
28173
+ Tree.FolderTrigger,
28174
+ {
28175
+ actions: !readOnly && /* @__PURE__ */ jsxRuntime.jsx(FolderAddAction, { tooltip: "New file", onClick: () => handleAddFile("references") }),
28176
+ children: [
28177
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFolderIcon(openFolders.references) }),
28178
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: "references" })
28179
+ ]
28180
+ }
28181
+ ),
28182
+ /* @__PURE__ */ jsxRuntime.jsxs(Tree.FolderContent, { children: [
28183
+ /* @__PURE__ */ jsxRuntime.jsx(UserFileList, { nodes: referencesFolder.children ?? [], readOnly, onRemove: handleRemove }),
28184
+ pendingInput?.parentId === "references" && /* @__PURE__ */ jsxRuntime.jsx(Tree.Input, { type: "file", onSubmit: handleInputSubmit, onCancel: handleInputCancel })
28185
+ ] })
28186
+ ] }),
28187
+ scriptsFolder && /* @__PURE__ */ jsxRuntime.jsxs(Tree.Folder, { open: openFolders.scripts, onOpenChange: (open) => setFolderOpen("scripts", open), children: [
28188
+ /* @__PURE__ */ jsxRuntime.jsxs(
28189
+ Tree.FolderTrigger,
28190
+ {
28191
+ actions: !readOnly && /* @__PURE__ */ jsxRuntime.jsx(FolderAddAction, { tooltip: "New file", onClick: () => handleAddFile("scripts") }),
28192
+ children: [
28193
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFolderIcon(openFolders.scripts) }),
28194
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: "scripts" })
28195
+ ]
28196
+ }
28197
+ ),
28198
+ /* @__PURE__ */ jsxRuntime.jsxs(Tree.FolderContent, { children: [
28199
+ /* @__PURE__ */ jsxRuntime.jsx(UserFileList, { nodes: scriptsFolder.children ?? [], readOnly, onRemove: handleRemove }),
28200
+ pendingInput?.parentId === "scripts" && /* @__PURE__ */ jsxRuntime.jsx(Tree.Input, { type: "file", onSubmit: handleInputSubmit, onCancel: handleInputCancel })
28201
+ ] })
28202
+ ] }),
28203
+ assetsFolder && /* @__PURE__ */ jsxRuntime.jsxs(Tree.Folder, { open: openFolders.assets, onOpenChange: (open) => setFolderOpen("assets", open), children: [
28204
+ /* @__PURE__ */ jsxRuntime.jsxs(
28205
+ Tree.FolderTrigger,
28206
+ {
28207
+ actions: !readOnly && /* @__PURE__ */ jsxRuntime.jsx(FolderAddAction, { tooltip: "Add image", onClick: handleAddImage }),
28208
+ children: [
28209
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Icon, { children: getFolderIcon(openFolders.assets) }),
28210
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.Label, { children: "assets" })
28211
+ ]
28212
+ }
28213
+ ),
28214
+ /* @__PURE__ */ jsxRuntime.jsx(Tree.FolderContent, { children: /* @__PURE__ */ jsxRuntime.jsx(UserFileList, { nodes: assetsFolder.children ?? [], readOnly, onRemove: handleRemove }) })
28215
+ ] })
28216
+ ] })
28217
+ ] }) })
28218
+ ] });
28219
+ }
28220
+
28221
+ function flattenFiles(nodes, basePath) {
28222
+ const results = [];
28223
+ for (const node of nodes) {
28224
+ const nodePath = basePath ? `${basePath}/${node.name}` : node.name;
28225
+ if (node.type === "file" && node.content !== void 0) {
28226
+ results.push({ path: nodePath, content: node.content });
28227
+ } else if (node.type === "folder" && node.children) {
28228
+ results.push(...flattenFiles(node.children, nodePath));
28229
+ }
28230
+ }
28231
+ return results;
28232
+ }
28233
+ function useCreateSkill() {
28234
+ const client = react$1.useMastraClient();
28235
+ const queryClient = reactQuery.useQueryClient();
28236
+ const writeFile = useWriteWorkspaceFile();
28237
+ return reactQuery.useMutation({
28238
+ mutationFn: async (params) => {
28239
+ const { name, description, workspaceId, files } = params;
28240
+ const filesToWrite = flattenFiles(files, "");
28241
+ await Promise.all(
28242
+ filesToWrite.map(
28243
+ (file) => writeFile.mutateAsync({
28244
+ workspaceId,
28245
+ path: `skills/${file.path}`,
28246
+ content: file.content,
28247
+ recursive: true
28248
+ })
28249
+ )
28250
+ );
28251
+ return client.createStoredSkill({
28252
+ name,
28253
+ description,
28254
+ instructions: extractSkillInstructions(files),
28255
+ license: extractSkillLicense(files),
28256
+ files
28257
+ });
28258
+ },
28259
+ onSuccess: (_, variables) => {
28260
+ queryClient.invalidateQueries({ queryKey: ["stored-skills"] });
28261
+ queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
28262
+ toast.success("Skill created");
28263
+ },
28264
+ onError: (error) => {
28265
+ toast.error(`Failed to create skill: ${error instanceof Error ? error.message : "Unknown error"}`);
28266
+ }
28267
+ });
28268
+ }
28269
+
28270
+ function findFileContent(nodes, fileId) {
28271
+ for (const node of nodes) {
28272
+ if (node.id === fileId && node.type === "file") return node.content ?? "";
28273
+ if (node.children) {
28274
+ const found = findFileContent(node.children, fileId);
28275
+ if (found !== void 0) return found;
28276
+ }
28277
+ }
28278
+ return void 0;
28279
+ }
28280
+ function findFileName(nodes, fileId) {
28281
+ for (const node of nodes) {
28282
+ if (node.id === fileId) return node.name;
28283
+ if (node.children) {
28284
+ const found = findFileName(node.children, fileId);
28285
+ if (found !== void 0) return found;
28286
+ }
28287
+ }
28288
+ return void 0;
28289
+ }
28290
+ function SkillFolder({
28291
+ files,
28292
+ onChange,
28293
+ readOnly,
28294
+ workspaceId,
28295
+ setWorkspaceId,
28296
+ workspaceOptions
28297
+ }) {
28298
+ const [selectedFileId, setSelectedFileId] = React.useState(null);
28299
+ const handleFileContentChange = React.useCallback(
28300
+ (content) => {
28301
+ if (!selectedFileId) return;
28302
+ onChange(updateNodeContent(files, selectedFileId, content));
28303
+ },
28304
+ [selectedFileId, files, onChange]
28305
+ );
28306
+ const selectedFileContent = React.useMemo(() => {
28307
+ if (!selectedFileId) return void 0;
28308
+ return findFileContent(files, selectedFileId);
28309
+ }, [files, selectedFileId]);
28310
+ const selectedFileName = React.useMemo(() => {
28311
+ if (!selectedFileId) return void 0;
28312
+ return findFileName(files, selectedFileId);
28313
+ }, [files, selectedFileId]);
28314
+ const editorLanguage = React.useMemo(() => {
28315
+ if (!selectedFileName) return void 0;
28316
+ if (selectedFileName.endsWith(".md")) return "markdown";
28317
+ if (selectedFileName.endsWith(".json")) return "json";
28318
+ return void 0;
28319
+ }, [selectedFileName]);
28320
+ const isFileSelected = selectedFileId !== null && selectedFileContent !== void 0;
28321
+ const isImage = isImageContent(selectedFileContent);
28322
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[300px_1fr] h-full", children: [
28323
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto h-full border-r border-border1 p-4", children: [
28324
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5 pb-4", children: [
28325
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "label", variant: "ui-sm", className: "text-neutral3", children: "Workspace" }),
28326
+ /* @__PURE__ */ jsxRuntime.jsx(
28327
+ Combobox,
28328
+ {
28329
+ options: workspaceOptions,
28330
+ value: workspaceId,
28331
+ onValueChange: setWorkspaceId,
28332
+ placeholder: "Select a workspace...",
28333
+ disabled: readOnly,
28334
+ variant: "default"
28335
+ }
28336
+ )
28337
+ ] }),
28338
+ /* @__PURE__ */ jsxRuntime.jsx(
28339
+ SkillFileTree,
28340
+ {
28341
+ files,
28342
+ onChange,
28343
+ selectedFileId,
28344
+ onSelectFile: setSelectedFileId,
28345
+ readOnly
28346
+ }
28347
+ )
28348
+ ] }),
28349
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full p-4", children: isFileSelected ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isImage ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-1 p-4 bg-surface2", children: /* @__PURE__ */ jsxRuntime.jsx(
28350
+ "img",
28351
+ {
28352
+ src: selectedFileContent,
28353
+ alt: selectedFileName,
28354
+ className: "max-w-full max-h-[300px] rounded-md object-contain"
28355
+ }
28356
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
28357
+ CodeEditor,
28358
+ {
28359
+ language: editorLanguage,
28360
+ value: selectedFileContent,
28361
+ onChange: readOnly ? void 0 : (val) => handleFileContentChange(val ?? ""),
28362
+ showCopyButton: false,
28363
+ autoFocus: true,
28364
+ className: "h-full"
28365
+ },
28366
+ selectedFileId
28367
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-xs text-neutral3", children: "Select a file to edit its content" }) })
28368
+ ] });
28369
+ }
28370
+
28371
+ function SkillEditDialog({ isOpen, onClose, onSkillCreated, readOnly }) {
28372
+ const [name, setName] = React.useState("");
28373
+ const [description, setDescription] = React.useState("");
28374
+ const [workspaceId, setWorkspaceId] = React.useState("");
28375
+ const [files, setFiles] = React.useState([]);
28376
+ const prevNameRef = React.useRef("");
28377
+ const createSkill = useCreateSkill();
28378
+ const { data: workspacesData } = useWorkspaces();
28379
+ const workspaceOptions = React.useMemo(
28380
+ () => (workspacesData?.workspaces ?? []).map((ws) => ({ value: ws.id, label: ws.name })),
28381
+ [workspacesData]
28382
+ );
28383
+ React.useEffect(() => {
28384
+ if (isOpen) {
28385
+ setName("");
28386
+ setDescription("");
28387
+ setWorkspaceId(workspaceOptions.length === 1 ? workspaceOptions[0].value : "");
28388
+ setFiles([]);
28389
+ prevNameRef.current = "";
28390
+ }
28391
+ }, [isOpen, workspaceOptions]);
28392
+ const handleNameChange = React.useCallback(
28393
+ (newName) => {
28394
+ setName(newName);
28395
+ const hasStructure = files.some((n) => n.id === "root");
28396
+ if (!hasStructure && newName.trim()) {
28397
+ setFiles(createInitialStructure(newName));
28398
+ } else if (hasStructure) {
28399
+ setFiles((prev) => updateRootFolderName(prev, newName));
28400
+ }
28401
+ prevNameRef.current = newName;
28402
+ },
28403
+ [files]
28404
+ );
28405
+ const handleSave = React.useCallback(async () => {
28406
+ const result = await createSkill.mutateAsync({
28407
+ name,
28408
+ description,
28409
+ workspaceId,
28410
+ files
28411
+ });
28412
+ onSkillCreated(result, workspaceId);
28413
+ onClose();
28414
+ }, [name, description, workspaceId, files, createSkill, onSkillCreated, onClose]);
28415
+ return /* @__PURE__ */ jsxRuntime.jsxs(
28416
+ SideDialog,
28417
+ {
28418
+ dialogTitle: "Add Skill",
28419
+ dialogDescription: "Configure skill details and workspace files",
28420
+ isOpen,
28421
+ onClose,
28422
+ className: "h-full",
28423
+ children: [
28424
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Top, { children: [
28425
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "New Skill" }),
28426
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
28427
+ Button,
28428
+ {
28429
+ variant: "primary",
28430
+ size: "sm",
28431
+ onClick: handleSave,
28432
+ disabled: !name.trim() || !workspaceId || createSkill.isPending,
28433
+ className: "mr-6",
28434
+ children: createSkill.isPending ? "Creating..." : "Save"
28435
+ }
28436
+ )
28437
+ ] }),
28438
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Content, { className: "overflow-y-auto h-full grid-rows-[auto_1fr]", children: [
28439
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
28440
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
28441
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "label", variant: "ui-sm", className: "text-neutral3", children: "Name" }),
28442
+ /* @__PURE__ */ jsxRuntime.jsx(
28443
+ Input,
28444
+ {
28445
+ value: name,
28446
+ onChange: (e) => handleNameChange(e.target.value),
28447
+ placeholder: "Skill name",
28448
+ disabled: readOnly
28449
+ }
28450
+ )
28451
+ ] }),
28452
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
28453
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "label", variant: "ui-sm", className: "text-neutral3", children: "Description" }),
28454
+ /* @__PURE__ */ jsxRuntime.jsx(
28455
+ Input,
28456
+ {
28457
+ value: description,
28458
+ onChange: (e) => setDescription(e.target.value),
28459
+ placeholder: "Brief description of the skill",
28460
+ disabled: readOnly
28461
+ }
28462
+ )
28463
+ ] })
28464
+ ] }),
28465
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full border border-border1 rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
28466
+ SkillFolder,
28467
+ {
28468
+ files,
28469
+ onChange: setFiles,
28470
+ readOnly,
28471
+ workspaceOptions,
28472
+ workspaceId,
28473
+ setWorkspaceId
28474
+ }
28475
+ ) })
28476
+ ] })
28477
+ ]
28478
+ }
28479
+ );
28480
+ }
28481
+
28482
+ function SkillsPage() {
28483
+ const { form, readOnly } = useAgentEditFormContext();
28484
+ const { control } = form;
28485
+ const { data: storedSkillsResponse, isLoading } = useStoredSkills();
28486
+ const [dialogOpen, setDialogOpen] = React.useState(false);
28487
+ const [search, setSearch] = React.useState("");
28488
+ const selectedSkills = reactHookForm.useWatch({ control, name: "skills" }) ?? {};
28489
+ const selectedSkillIds = Object.keys(selectedSkills);
28490
+ const storedSkills = storedSkillsResponse?.skills ?? [];
28491
+ const getSkillDescription = (skillId) => {
28492
+ const skill = storedSkills.find((s) => s.id === skillId);
28493
+ return skill?.description || "";
28494
+ };
28495
+ const handleToggleSkill = (skillId) => {
28496
+ const currentSkills = form.getValues("skills") ?? {};
28497
+ const isSelected = currentSkills[skillId] !== void 0;
28498
+ if (isSelected) {
28499
+ const next = { ...currentSkills };
28500
+ delete next[skillId];
28501
+ form.setValue("skills", next);
28502
+ } else {
28503
+ form.setValue("skills", {
28504
+ ...currentSkills,
28505
+ [skillId]: { description: getSkillDescription(skillId) }
28506
+ });
28507
+ }
28508
+ };
28509
+ const handleSkillCreated = (skill, workspaceId) => {
28510
+ const currentSkills = form.getValues("skills") ?? {};
28511
+ form.setValue("skills", {
28512
+ ...currentSkills,
28513
+ [skill.id]: { description: skill.description || "" }
28514
+ });
28515
+ form.setValue("workspace", { type: "id", workspaceId });
28516
+ setDialogOpen(false);
28517
+ };
28518
+ const filteredSkills = storedSkills.filter((skill) => skill.name.toLowerCase().includes(search.toLowerCase()));
28519
+ const totalCount = selectedSkillIds.length;
28520
+ return /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: "h-full", children: [
28521
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
28522
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
28523
+ /* @__PURE__ */ jsxRuntime.jsx(
28524
+ SectionHeader$1,
28525
+ {
28526
+ title: "Skills",
28527
+ subtitle: `Give your agent specialized knowledge by using skills.${totalCount > 0 ? ` (${totalCount} selected)` : ""}`
28528
+ }
28529
+ ),
28530
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: () => setDialogOpen(true), children: [
28531
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "size-3" }),
28532
+ "Add a skill"
28533
+ ] })
28534
+ ] }),
28535
+ /* @__PURE__ */ jsxRuntime.jsx(Searchbar, { onSearch: setSearch, label: "Search skills", placeholder: "Search skills" }),
28536
+ filteredSkills.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-2", children: filteredSkills.map((skill) => /* @__PURE__ */ jsxRuntime.jsxs(Entity, { className: "bg-surface2", children: [
28537
+ /* @__PURE__ */ jsxRuntime.jsxs(EntityContent, { children: [
28538
+ /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: skill.name }),
28539
+ /* @__PURE__ */ jsxRuntime.jsx(EntityDescription, { children: skill.description || "No description" })
28540
+ ] }),
28541
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
28542
+ Switch,
28543
+ {
28544
+ checked: selectedSkillIds.includes(skill.id),
28545
+ onCheckedChange: () => handleToggleSkill(skill.id)
28546
+ }
28547
+ )
28548
+ ] }, skill.id)) }),
28549
+ !isLoading && storedSkills.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-12", children: /* @__PURE__ */ jsxRuntime.jsx(
28550
+ EmptyState$1,
28551
+ {
28552
+ iconSlot: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Drill, { height: 40, width: 40 }),
28553
+ titleSlot: "No skills available",
28554
+ descriptionSlot: "Create a skill to give your agent specialized knowledge.",
28555
+ actionSlot: !readOnly ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "outline", size: "sm", onClick: () => setDialogOpen(true), children: [
28556
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "size-3" }),
28557
+ "Add a skill"
28558
+ ] }) : void 0
28559
+ }
28560
+ ) })
28561
+ ] }),
28562
+ /* @__PURE__ */ jsxRuntime.jsx(
28563
+ SkillEditDialog,
28564
+ {
28565
+ isOpen: dialogOpen,
28566
+ onClose: () => setDialogOpen(false),
28567
+ onSkillCreated: handleSkillCreated,
28568
+ readOnly
28569
+ }
28570
+ )
28571
+ ] });
28572
+ }
28573
+
28574
+ const arrayToRecord = (arr) => {
28575
+ const record = {};
28576
+ for (const id of arr) {
28577
+ record[id] = { description: void 0 };
28578
+ }
28579
+ return record;
28580
+ };
28581
+ const normalizeToolsToRecord = (tools) => {
28582
+ if (!tools) return {};
28583
+ if (!Array.isArray(tools)) return { ...tools };
28584
+ const result = {};
28585
+ for (const item of tools) {
28586
+ if (typeof item === "string") {
28587
+ result[item] = { description: void 0 };
28588
+ } else {
28589
+ Object.assign(result, item.value);
28590
+ }
28591
+ }
28592
+ return result;
28593
+ };
28594
+ const splitModelId = (id) => {
28595
+ if (!id) return void 0;
28596
+ const [p, ...rest] = id.split("/");
28597
+ const n = rest.join("/");
28598
+ return p && n ? { provider: p, name: n } : void 0;
28599
+ };
28600
+ const joinModelId = (m) => m?.provider && m?.name ? `${m.provider}/${m.name}` : void 0;
28601
+ const transformIntegrationToolsForApi = (integrationTools) => {
28602
+ if (!integrationTools || Object.keys(integrationTools).length === 0) return void 0;
28603
+ const result = {};
28604
+ for (const [compositeKey, config] of Object.entries(integrationTools)) {
28605
+ const separatorIndex = compositeKey.indexOf(":");
28606
+ if (separatorIndex === -1) continue;
28607
+ const providerId = compositeKey.slice(0, separatorIndex);
28608
+ const toolSlug = compositeKey.slice(separatorIndex + 1);
28609
+ if (!result[providerId]) {
28610
+ result[providerId] = { tools: {} };
28611
+ }
28612
+ result[providerId].tools[toolSlug] = { description: config.description, rules: config.rules };
28613
+ }
28614
+ return result;
28615
+ };
28616
+ const normalizeIntegrationToolsToRecord = (integrationTools) => {
28617
+ if (!integrationTools) return {};
28618
+ const result = {};
28619
+ for (const [providerId, providerConfig] of Object.entries(integrationTools)) {
28620
+ if (providerConfig.tools) {
28621
+ for (const [toolSlug, toolConfig] of Object.entries(providerConfig.tools)) {
28622
+ result[`${providerId}:${toolSlug}`] = { description: toolConfig.description, rules: toolConfig.rules };
28623
+ }
28624
+ }
28625
+ }
28626
+ return result;
28627
+ };
28628
+ const normalizeSkillsFromApi = (skills) => {
28629
+ if (!skills) return {};
28630
+ if (Array.isArray(skills)) {
28631
+ const result2 = {};
28632
+ for (const variant of skills) {
28633
+ for (const [key, value] of Object.entries(variant.value)) {
28634
+ result2[key] = {
28635
+ description: value.description,
28636
+ instructions: value.instructions,
28637
+ pin: value.pin,
28638
+ strategy: value.strategy
28639
+ };
28640
+ }
28641
+ }
28642
+ return result2;
28643
+ }
28644
+ const result = {};
28645
+ for (const [key, value] of Object.entries(skills)) {
28646
+ result[key] = {
28647
+ description: value.description,
28648
+ instructions: value.instructions,
28649
+ pin: value.pin,
28650
+ strategy: value.strategy
28651
+ };
28652
+ }
28653
+ return result;
28654
+ };
28655
+ const normalizeWorkspaceFromApi = (workspace) => {
28656
+ if (!workspace) return void 0;
28657
+ if (Array.isArray(workspace)) {
28658
+ return workspace[0]?.value;
28659
+ }
28660
+ return workspace;
28661
+ };
28662
+ const mapInstructionBlocksToApi = (blocks) => (blocks ?? []).map((block) => ({
28663
+ type: block.type,
28664
+ content: block.content,
28665
+ rules: block.rules
28666
+ }));
28667
+ const mapInstructionBlocksFromApi = (instructionsRaw) => {
28668
+ const instructionsString = Array.isArray(instructionsRaw) ? instructionsRaw.map((b) => b.type === "prompt_block" ? b.content : "").filter(Boolean).join("\n\n") : instructionsRaw || "";
28669
+ const instructionBlocks = Array.isArray(instructionsRaw) ? instructionsRaw.filter(
28670
+ (b) => b.type === "prompt_block"
28671
+ ).map((b) => createInstructionBlock(b.content, b.rules)) : [createInstructionBlock(instructionsRaw || "")];
28672
+ return { instructionsString, instructionBlocks };
28673
+ };
28674
+ const mapScorersToApi = (scorers) => {
28675
+ const entries = scorers ? Object.entries(scorers) : void 0;
28676
+ if (!entries) return void 0;
28677
+ return Object.fromEntries(
28678
+ entries.map(([key, value]) => [
28679
+ key,
28680
+ {
28681
+ description: value.description,
28682
+ sampling: value.sampling ? {
28683
+ type: value.sampling.type,
28684
+ rate: value.sampling.rate || 0
28685
+ } : void 0,
28686
+ rules: value.rules
28687
+ }
28688
+ ])
28689
+ );
28690
+ };
28691
+ const normalizeScorersFromApi = (scorers) => {
28692
+ if (!scorers) return {};
28693
+ let record;
28694
+ if (Array.isArray(scorers)) {
28695
+ record = {};
28696
+ for (const variant of scorers) {
28697
+ Object.assign(record, variant.value);
28698
+ }
28699
+ } else {
28700
+ record = scorers;
28701
+ }
28702
+ const result = {};
28703
+ for (const [key, value] of Object.entries(record)) {
28704
+ result[key] = {
28705
+ description: value.description,
28706
+ sampling: value.sampling?.type === "ratio" ? { type: "ratio", rate: value.sampling.rate } : void 0,
28707
+ rules: value.rules
28708
+ };
28709
+ }
28710
+ return result;
28711
+ };
28712
+ const buildObservationalMemoryForApi = (om) => {
28713
+ if (!om?.enabled) return void 0;
28714
+ const modelId = joinModelId(om.model);
28715
+ const obsModelId = joinModelId(om.observation?.model);
28716
+ const observation = obsModelId || om.observation?.messageTokens || om.observation?.maxTokensPerBatch || om.observation?.bufferTokens !== void 0 || om.observation?.bufferActivation !== void 0 || om.observation?.blockAfter !== void 0 ? {
28717
+ model: obsModelId,
28718
+ messageTokens: om.observation?.messageTokens,
28719
+ maxTokensPerBatch: om.observation?.maxTokensPerBatch,
26957
28720
  bufferTokens: om.observation?.bufferTokens,
26958
28721
  bufferActivation: om.observation?.bufferActivation,
26959
28722
  blockAfter: om.observation?.blockAfter
@@ -27039,6 +28802,8 @@ function computeAgentInitialValues(dataSource) {
27039
28802
  observationalMemory: parseObservationalMemoryFromApi(memoryData.observationalMemory)
27040
28803
  } : void 0,
27041
28804
  instructionBlocks,
28805
+ skills: normalizeSkillsFromApi(dataSource.skills),
28806
+ workspace: normalizeWorkspaceFromApi(dataSource.workspace),
27042
28807
  variables: dataSource.requestContextSchema
27043
28808
  };
27044
28809
  }
@@ -27064,15 +28829,22 @@ function useAgentCmsForm(options) {
27064
28829
  const ids = Object.keys(mcpClientRecord ?? {});
27065
28830
  if (ids.length === 0) return;
27066
28831
  Promise.all(ids.map((id) => client.getStoredMCPClient(id).details())).then((results) => {
27067
- form.setValue(
27068
- "mcpClients",
27069
- results.map((r) => ({
27070
- id: r.id,
27071
- name: r.name,
27072
- description: r.description,
27073
- servers: r.servers
27074
- }))
27075
- );
28832
+ const mcpClientValues = results.map((r) => ({
28833
+ id: r.id,
28834
+ name: r.name,
28835
+ description: r.description,
28836
+ servers: r.servers,
28837
+ selectedTools: mcpClientRecord?.[r.id]?.tools ?? {}
28838
+ }));
28839
+ form.setValue("mcpClients", mcpClientValues, { shouldDirty: true });
28840
+ const currentTools = form.getValues("tools") ?? {};
28841
+ const next = { ...currentTools };
28842
+ for (const mcpClient of mcpClientValues) {
28843
+ for (const [name, config] of Object.entries(mcpClient.selectedTools ?? {})) {
28844
+ next[name] = { description: config.description };
28845
+ }
28846
+ }
28847
+ form.setValue("tools", next, { shouldDirty: true });
27076
28848
  }).catch(() => {
27077
28849
  });
27078
28850
  });
@@ -27086,19 +28858,38 @@ function useAgentCmsForm(options) {
27086
28858
  const mcpClientsToDelete = values.mcpClientsToDelete ?? [];
27087
28859
  await Promise.all(mcpClientsToDelete.map((id) => client.getStoredMCPClient(id).delete()));
27088
28860
  }
28861
+ const mcpToolNames = /* @__PURE__ */ new Set();
28862
+ for (const c of values.mcpClients ?? []) {
28863
+ for (const name of Object.keys(c.selectedTools ?? {})) {
28864
+ mcpToolNames.add(name);
28865
+ }
28866
+ }
28867
+ const registryTools = {};
28868
+ for (const [name, config] of Object.entries(values.tools ?? {})) {
28869
+ if (!mcpToolNames.has(name)) {
28870
+ registryTools[name] = config;
28871
+ }
28872
+ }
27089
28873
  const mcpClientIds = await collectMCPClientIds(values.mcpClients ?? [], client);
27090
- const mcpClientsParam = Object.fromEntries(mcpClientIds.map((id) => [id, {}]));
28874
+ const mcpClientsParam = Object.fromEntries(
28875
+ mcpClientIds.map((id, index) => {
28876
+ const selectedTools = values.mcpClients?.[index]?.selectedTools ?? {};
28877
+ return [id, { tools: selectedTools }];
28878
+ })
28879
+ );
27091
28880
  return {
27092
28881
  name: values.name,
27093
28882
  description: values.description || void 0,
27094
28883
  instructions: mapInstructionBlocksToApi(values.instructionBlocks),
27095
28884
  model: values.model,
27096
- tools: values.tools && Object.keys(values.tools).length > 0 ? values.tools : void 0,
28885
+ tools: Object.keys(registryTools).length > 0 ? registryTools : void 0,
27097
28886
  integrationTools: transformIntegrationToolsForApi(values.integrationTools),
27098
28887
  workflows: values.workflows && Object.keys(values.workflows).length > 0 ? values.workflows : void 0,
27099
28888
  agents: values.agents && Object.keys(values.agents).length > 0 ? values.agents : void 0,
27100
28889
  mcpClients: mcpClientsParam,
27101
28890
  scorers: mapScorersToApi(values.scorers),
28891
+ skills: values.skills,
28892
+ workspace: values.workspace,
27102
28893
  requestContextSchema: values.variables ? Object.fromEntries(Object.entries(values.variables)) : void 0
27103
28894
  };
27104
28895
  },
@@ -27136,6 +28927,7 @@ function useAgentCmsForm(options) {
27136
28927
  ...sharedParams,
27137
28928
  memory: editMemory
27138
28929
  });
28930
+ form.reset(values);
27139
28931
  queryClient.invalidateQueries({ queryKey: ["agent-versions", agentId] });
27140
28932
  toast.success("Draft saved");
27141
28933
  } catch (error) {
@@ -27154,17 +28946,16 @@ function useAgentCmsForm(options) {
27154
28946
  setIsSubmitting(true);
27155
28947
  try {
27156
28948
  if (isEdit) {
27157
- const sharedParams = await buildSharedParams(values);
27158
- const editMemory = buildMemoryParams(values);
27159
- await updateStoredAgent.mutateAsync({
27160
- ...sharedParams,
27161
- memory: editMemory
27162
- });
27163
- const versionsResponse = await client.getStoredAgent(options.agentId).listVersions({ sortDirection: "DESC", perPage: 1 });
28949
+ const [agentDetails, versionsResponse] = await Promise.all([
28950
+ client.getStoredAgent(options.agentId).details(),
28951
+ client.getStoredAgent(options.agentId).listVersions({ sortDirection: "DESC", perPage: 1 })
28952
+ ]);
27164
28953
  const latestVersion = versionsResponse.versions[0];
27165
- if (latestVersion) {
27166
- await client.getStoredAgent(options.agentId).activateVersion(latestVersion.id);
28954
+ if (!latestVersion || latestVersion.id === agentDetails.activeVersionId) {
28955
+ toast.error("No draft changes to publish. Save a draft first.");
28956
+ return;
27167
28957
  }
28958
+ await client.getStoredAgent(options.agentId).activateVersion(latestVersion.id);
27168
28959
  await Promise.all([
27169
28960
  queryClient.invalidateQueries({ queryKey: ["agent-versions", agentId] }),
27170
28961
  queryClient.invalidateQueries({ queryKey: ["stored-agent", agentId] }),
@@ -27197,25 +28988,15 @@ function useAgentCmsForm(options) {
27197
28988
  } finally {
27198
28989
  setIsSubmitting(false);
27199
28990
  }
27200
- }, [
27201
- form,
27202
- isEdit,
27203
- client,
27204
- createStoredAgent,
27205
- updateStoredAgent,
27206
- options,
27207
- agentId,
27208
- buildSharedParams,
27209
- buildMemoryParams,
27210
- queryClient
27211
- ]);
28991
+ }, [form, isEdit, client, createStoredAgent, options, agentId, buildSharedParams, queryClient]);
27212
28992
  const watched = reactHookForm.useWatch({ control: form.control });
27213
28993
  const canPublish = React.useMemo(() => {
27214
28994
  const identityDone = !!watched.name && !!watched.model?.provider && !!watched.model?.name;
27215
28995
  const instructionsDone = (watched.instructionBlocks ?? []).some((b) => b.content?.trim());
27216
28996
  return identityDone && instructionsDone;
27217
28997
  }, [watched.name, watched.model?.provider, watched.model?.name, watched.instructionBlocks]);
27218
- return { form, handlePublish, handleSaveDraft, isSubmitting, isSavingDraft, canPublish };
28998
+ const isDirty = form.formState.isDirty;
28999
+ return { form, handlePublish, handleSaveDraft, isSubmitting, isSavingDraft, canPublish, isDirty };
27219
29000
  }
27220
29001
 
27221
29002
  function AgentCmsFormShell({
@@ -27231,7 +29012,8 @@ function AgentCmsFormShell({
27231
29012
  currentPath,
27232
29013
  banner,
27233
29014
  children,
27234
- versionId
29015
+ versionId,
29016
+ rightPanel
27235
29017
  }) {
27236
29018
  return /* @__PURE__ */ jsxRuntime.jsx(
27237
29019
  AgentEditFormProvider,
@@ -27244,7 +29026,7 @@ function AgentCmsFormShell({
27244
29026
  handlePublish,
27245
29027
  handleSaveDraft,
27246
29028
  readOnly,
27247
- children: /* @__PURE__ */ jsxRuntime.jsxs(AgentsCmsLayout, { basePath, currentPath, versionId, children: [
29029
+ children: /* @__PURE__ */ jsxRuntime.jsxs(AgentsCmsLayout, { basePath, currentPath, versionId, rightPanel, children: [
27248
29030
  banner,
27249
29031
  children
27250
29032
  ] })
@@ -27252,6 +29034,61 @@ function AgentCmsFormShell({
27252
29034
  );
27253
29035
  }
27254
29036
 
29037
+ function formatTimestamp(isoString) {
29038
+ const date = new Date(isoString);
29039
+ return date.toLocaleDateString(void 0, {
29040
+ month: "short",
29041
+ day: "numeric",
29042
+ year: "numeric",
29043
+ hour: "2-digit",
29044
+ minute: "2-digit"
29045
+ });
29046
+ }
29047
+ function AgentVersionPanel({
29048
+ agentId,
29049
+ selectedVersionId,
29050
+ onVersionSelect,
29051
+ activeVersionId
29052
+ }) {
29053
+ const { data, isLoading } = useAgentVersions({
29054
+ agentId,
29055
+ params: { sortDirection: "DESC" }
29056
+ });
29057
+ const versions = data?.versions ?? [];
29058
+ const activeVersion = activeVersionId ? versions.find((v) => v.id === activeVersionId) : void 0;
29059
+ const activeVersionNumber = activeVersion?.versionNumber;
29060
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full flex flex-col", children: [
29061
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-3 border-b border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "font-medium text-neutral5", children: "Version history" }) }),
29062
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "flex-1 min-h-0", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-xs", className: "text-neutral2", children: "Loading versions..." }) }) : /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col", children: versions.map((version) => {
29063
+ const isSelected = selectedVersionId === version.id || !selectedVersionId && version.id === versions[0]?.id;
29064
+ const isPublished = version.id === activeVersionId;
29065
+ const isDraft = activeVersionNumber !== void 0 && version.versionNumber > activeVersionNumber;
29066
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
29067
+ "button",
29068
+ {
29069
+ type: "button",
29070
+ onClick: () => onVersionSelect(version.id),
29071
+ className: cn(
29072
+ "w-full text-left px-3 py-2.5 text-sm transition-colors border-l-2",
29073
+ isSelected ? "bg-surface2 text-neutral5 border-accent1" : "border-transparent text-neutral3 hover:bg-surface3 hover:text-neutral5"
29074
+ ),
29075
+ children: [
29076
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
29077
+ /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-sm", className: "text-inherit", children: [
29078
+ "v",
29079
+ version.versionNumber
29080
+ ] }),
29081
+ isPublished && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "success", children: "Published" }),
29082
+ isDraft && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "info", children: "Draft" })
29083
+ ] }),
29084
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-xs", className: "text-neutral2 mt-0.5", children: formatTimestamp(version.createdAt) })
29085
+ ]
29086
+ }
29087
+ ) }, version.id);
29088
+ }) }) })
29089
+ ] });
29090
+ }
29091
+
27255
29092
  const NameCell$3 = ({ row }) => {
27256
29093
  const { Link, paths } = useLinkComponent();
27257
29094
  const processor = row.original;
@@ -30773,7 +32610,7 @@ const useDatasetItemVersions = (datasetId, itemId) => {
30773
32610
  enabled: Boolean(datasetId) && Boolean(itemId)
30774
32611
  });
30775
32612
  };
30776
- const useDatasetItemVersion = (datasetId, itemId, datasetVersion) => {
32613
+ const useDatasetItemVersion = (datasetId, itemId, datasetVersion, latestVersion) => {
30777
32614
  const client = react$1.useMastraClient();
30778
32615
  return reactQuery.useQuery({
30779
32616
  queryKey: ["dataset-item-version", datasetId, itemId, datasetVersion],
@@ -30786,11 +32623,11 @@ const useDatasetItemVersion = (datasetId, itemId, datasetVersion) => {
30786
32623
  input: v.input,
30787
32624
  groundTruth: v.groundTruth,
30788
32625
  metadata: v.metadata,
30789
- validTo: v.validTo,
30790
- isDeleted: v.isDeleted,
32626
+ validTo: v.validTo ?? null,
32627
+ isDeleted: v.isDeleted ?? false,
30791
32628
  createdAt: v.createdAt,
30792
32629
  updatedAt: v.updatedAt,
30793
- isLatest: false
32630
+ isLatest: latestVersion != null ? datasetVersion === latestVersion : false
30794
32631
  };
30795
32632
  },
30796
32633
  enabled: Boolean(datasetId) && Boolean(itemId) && datasetVersion > 0
@@ -32437,6 +34274,52 @@ function DeleteDatasetDialog({
32437
34274
  ] }) });
32438
34275
  }
32439
34276
 
34277
+ function DatasetCombobox({
34278
+ value,
34279
+ onValueChange,
34280
+ placeholder = "Select a dataset...",
34281
+ searchPlaceholder = "Search datasets...",
34282
+ emptyText = "No datasets found.",
34283
+ className,
34284
+ disabled = false,
34285
+ variant = "default"
34286
+ }) {
34287
+ const { data, isLoading, isError, error } = useDatasets();
34288
+ const { navigate, paths } = useLinkComponent();
34289
+ React.useEffect(() => {
34290
+ if (isError) {
34291
+ const errorMessage = error instanceof Error ? error.message : "Failed to load datasets";
34292
+ toast.error(`Error loading datasets: ${errorMessage}`);
34293
+ }
34294
+ }, [isError, error]);
34295
+ const datasets = data?.datasets ?? [];
34296
+ const datasetOptions = datasets.map((d) => ({
34297
+ label: d.name,
34298
+ value: d.id
34299
+ }));
34300
+ const handleValueChange = (newDatasetId) => {
34301
+ if (onValueChange) {
34302
+ onValueChange(newDatasetId);
34303
+ } else if (newDatasetId && newDatasetId !== value) {
34304
+ navigate(paths.datasetLink(newDatasetId));
34305
+ }
34306
+ };
34307
+ return /* @__PURE__ */ jsxRuntime.jsx(
34308
+ Combobox,
34309
+ {
34310
+ options: datasetOptions,
34311
+ value,
34312
+ onValueChange: handleValueChange,
34313
+ placeholder: isLoading ? "Loading datasets..." : placeholder,
34314
+ searchPlaceholder,
34315
+ emptyText,
34316
+ className,
34317
+ disabled: disabled || isLoading || isError,
34318
+ variant
34319
+ }
34320
+ );
34321
+ }
34322
+
32440
34323
  function ItemListRoot({ children, className }) {
32441
34324
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-rows-[auto_1fr] overflow-y-auto", className), children });
32442
34325
  }
@@ -33221,24 +35104,18 @@ function ItemDetailToolbar({
33221
35104
  !isEditing && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
33222
35105
  /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "standard", size: "default", href: `/datasets/${datasetId}/items/${itemId}`, as: Link, children: [
33223
35106
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.History, {}),
33224
- "History"
35107
+ "Versions"
33225
35108
  ] }),
33226
- /* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { spacing: "close", children: [
33227
- /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "standard", size: "default", onClick: onEdit, children: [
33228
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, {}),
33229
- "Edit"
33230
- ] }),
33231
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
33232
- /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "standard", size: "default", "aria-label": "Actions menu", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, {}) }) }),
33233
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu.Content, { align: "end", className: "w-48", children: [
33234
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu.Item, { onSelect: onDelete, className: "text-red-500 focus:text-red-400", children: [
33235
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, {}),
33236
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Delete Item" })
33237
- ] }),
33238
- /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu.Item, { disabled: true, children: [
33239
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, {}),
33240
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Duplicate Item (Coming Soon)" })
33241
- ] })
35109
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { children: [
35110
+ /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "standard", size: "default", "aria-label": "Actions menu", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EllipsisVerticalIcon, {}) }) }),
35111
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu.Content, { align: "end", className: "w-48", children: [
35112
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu.Item, { onSelect: onEdit, children: [
35113
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, {}),
35114
+ "Edit"
35115
+ ] }),
35116
+ /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu.Item, { onSelect: onDelete, className: "text-red-500 focus:text-red-400", children: [
35117
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, {}),
35118
+ "Delete Item"
33242
35119
  ] })
33243
35120
  ] })
33244
35121
  ] })
@@ -36170,9 +38047,9 @@ function ExperimentResultPanel({
36170
38047
  onClose,
36171
38048
  onShowTrace
36172
38049
  }) {
36173
- const hasError = Boolean(result.error);
36174
- const inputStr = formatValue$1(result.input);
36175
- const outputStr = formatValue$1(result.output);
38050
+ const hasError = Boolean(result?.error);
38051
+ const inputStr = formatValue$1(result?.input);
38052
+ const outputStr = formatValue$1(result?.output);
36176
38053
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
36177
38054
  /* @__PURE__ */ jsxRuntime.jsxs(ListAndDetails.ColumnToolbar, { children: [
36178
38055
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -36205,6 +38082,15 @@ function ExperimentResultPanel({
36205
38082
  result.itemId
36206
38083
  ] }) })
36207
38084
  ] }) }),
38085
+ hasError && /* @__PURE__ */ jsxRuntime.jsxs(Notice, { variant: "destructive", children: [
38086
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.OctagonAlertIcon, {}),
38087
+ /* @__PURE__ */ jsxRuntime.jsxs(Notice.Message, { children: [
38088
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Error: " }),
38089
+ formatValue$1(
38090
+ result?.error && typeof result.error === "object" ? result.error.message : result?.error
38091
+ )
38092
+ ] })
38093
+ ] }),
36208
38094
  /* @__PURE__ */ jsxRuntime.jsx(SideDialog.CodeSection, { title: "Input", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileCodeIcon, {}), codeStr: inputStr }),
36209
38095
  /* @__PURE__ */ jsxRuntime.jsx(SideDialog.CodeSection, { title: "Output", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileOutputIcon, {}), codeStr: outputStr }),
36210
38096
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-2", children: [
@@ -36213,16 +38099,6 @@ function ExperimentResultPanel({
36213
38099
  " Created"
36214
38100
  ] }),
36215
38101
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-neutral4", children: format.format(new Date(result.createdAt), "MMM d, yyyy 'at' h:mm a") })
36216
- ] }),
36217
- hasError && /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
36218
- /* @__PURE__ */ jsxRuntime.jsxs(Section.Header, { children: [
36219
- /* @__PURE__ */ jsxRuntime.jsxs(Section.Heading, { children: [
36220
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, {}),
36221
- " Error"
36222
- ] }),
36223
- /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: result.error || "" })
36224
- ] }),
36225
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-black/20 p-4 overflow-hidden rounded-xl border border-white/10 text-neutral4 text-ui-md", children: /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-wrap font-mono text-sm whitespace-pre-wrap break-all", children: result.error }) })
36226
38102
  ] })
36227
38103
  ] })
36228
38104
  ] });
@@ -37322,8 +39198,9 @@ function DatasetItemVersionsPanel({
37322
39198
  }
37323
39199
  };
37324
39200
  const columnsToRender = isSelectionActive ? versionsListColumnsWithCheckbox : versionsListColumns;
37325
- return /* @__PURE__ */ jsxRuntime.jsxs(Column, { className: "min-w-[20rem]", children: [
39201
+ return /* @__PURE__ */ jsxRuntime.jsxs(Column, { className: "min-w-[17rem]", children: [
37326
39202
  isSelectionActive ? /* @__PURE__ */ jsxRuntime.jsx(Column.Toolbar, { className: "grid justify-stretch gap-3 w-full", children: /* @__PURE__ */ jsxRuntime.jsxs(ButtonsGroup, { children: [
39203
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "standard", size: "default", onClick: handleCancelSelection, children: "Cancel" }),
37327
39204
  /* @__PURE__ */ jsxRuntime.jsx(
37328
39205
  ButtonWithTooltip,
37329
39206
  {
@@ -37331,14 +39208,14 @@ function DatasetItemVersionsPanel({
37331
39208
  size: "default",
37332
39209
  disabled: selectedIds.size !== 2,
37333
39210
  onClick: handleExecuteCompare,
37334
- tooltipContent: selectedIds.size !== 2 ? "Select exactly 2 versions to compare" : void 0,
37335
- children: "Compare Versions"
39211
+ tooltipContent: selectedIds.size !== 2 ? "Check 2 versions to compare" : void 0,
39212
+ className: "grow",
39213
+ children: "Compare Selected"
37336
39214
  }
37337
- ),
37338
- /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "standard", size: "default", onClick: handleCancelSelection, children: "Cancel" })
37339
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(Column.Toolbar, { children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "standard", size: "default", onClick: handleCompareClick, children: [
37340
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ScaleIcon, {}),
37341
- " Compare"
39215
+ )
39216
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(Column.Toolbar, { children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "standard", size: "default", onClick: handleCompareClick, className: "w-full", children: [
39217
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitCompareIcon, {}),
39218
+ " Compare Versions"
37342
39219
  ] }) }),
37343
39220
  isLoading ? /* @__PURE__ */ jsxRuntime.jsx(DatasetItemVersionsListSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsxs(ItemList, { children: [
37344
39221
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-rows-[1fr_auto] gap-4", children: /* @__PURE__ */ jsxRuntime.jsx(ItemList.Header, { columns: columnsToRender, children: columnsToRender.map(
@@ -37346,7 +39223,7 @@ function DatasetItemVersionsPanel({
37346
39223
  ) }) }),
37347
39224
  /* @__PURE__ */ jsxRuntime.jsx(ItemList.Scroller, { children: /* @__PURE__ */ jsxRuntime.jsx(ItemList.Items, { children: versions?.map((item, index) => {
37348
39225
  const versionKey = String(item.datasetVersion);
37349
- const createdAtDate = typeof item.createdAt === "string" ? new Date(item.createdAt) : item.createdAt;
39226
+ const versionDate = typeof item.updatedAt === "string" ? new Date(item.updatedAt) : item.updatedAt;
37350
39227
  return /* @__PURE__ */ jsxRuntime.jsxs(
37351
39228
  ItemList.Row,
37352
39229
  {
@@ -37356,11 +39233,14 @@ function DatasetItemVersionsPanel({
37356
39233
  Checkbox,
37357
39234
  {
37358
39235
  checked: selectedIds.has(versionKey),
39236
+ disabled: item.isDeleted,
37359
39237
  onCheckedChange: () => {
37360
39238
  },
37361
39239
  onClick: (e) => {
37362
39240
  e.stopPropagation();
37363
- handleToggleSelection(versionKey);
39241
+ if (!item.isDeleted) {
39242
+ handleToggleSelection(versionKey);
39243
+ }
37364
39244
  },
37365
39245
  "aria-label": `Select version ${item.datasetVersion}`
37366
39246
  }
@@ -37373,13 +39253,18 @@ function DatasetItemVersionsPanel({
37373
39253
  isSelected: isSelectionActive ? selectedIds.has(versionKey) : isVersionSelected(item),
37374
39254
  onClick: () => handleVersionClick(item),
37375
39255
  className: "py-3",
37376
- children: /* @__PURE__ */ jsxRuntime.jsxs(ItemList.FlexCell, { className: "w-full text-neutral flex gap-4 items-baseline text-neutral3", children: [
37377
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "min-w-8", children: [
37378
- "v",
37379
- item.datasetVersion
39256
+ children: /* @__PURE__ */ jsxRuntime.jsxs(ItemList.FlexCell, { className: "w-full text-neutral grid text-neutral3", children: [
39257
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex", children: [
39258
+ /* @__PURE__ */ jsxRuntime.jsxs("strong", { className: "min-w-11", children: [
39259
+ "v",
39260
+ item.datasetVersion
39261
+ ] }),
39262
+ /* @__PURE__ */ jsxRuntime.jsx("em", { children: versionDate ? dateFns.format(versionDate, "MMM d, yyyy HH:mm") : null })
37380
39263
  ] }),
37381
- /* @__PURE__ */ jsxRuntime.jsx("em", { children: createdAtDate ? dateFns.format(createdAtDate, "MMM d, yyyy HH:mm") : null }),
37382
- item.isLatest && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto inline-block text-neutral4 text-xs p-1 px-2 leading-none rounded-sm bg-cyan-800", children: "Latest" })
39264
+ (item.isLatest || item.isDeleted) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 pl-11 ", children: [
39265
+ item.isLatest && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block text-neutral4 text-xs p-1 px-2 leading-none rounded-sm bg-cyan-900", children: "Latest" }),
39266
+ item.isDeleted && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block text-neutral4 text-xs p-1 px-2 leading-none rounded-sm bg-red-900", children: "Deleted" })
39267
+ ] })
37383
39268
  ] })
37384
39269
  }
37385
39270
  )
@@ -37961,6 +39846,83 @@ function PageHeader({ title, description, icon, className }) {
37961
39846
  ] });
37962
39847
  }
37963
39848
 
39849
+ const diffOverrides = view.EditorView.theme({
39850
+ "&.cm-editor .cm-changedLine": {
39851
+ backgroundColor: "transparent",
39852
+ backgroundImage: "none",
39853
+ borderLeft: "none"
39854
+ },
39855
+ "&.cm-editor .cm-changedText": {
39856
+ backgroundImage: "none",
39857
+ backgroundColor: "#880000",
39858
+ padding: "1px 5px",
39859
+ display: "inline-block",
39860
+ borderRadius: "4px"
39861
+ },
39862
+ "&.cm-editor .cm-changedText, &.cm-editor .cm-changedText *": {
39863
+ color: "white"
39864
+ },
39865
+ "&.cm-editor .cm-line": {
39866
+ lineHeight: "1.5",
39867
+ opacity: "0.5"
39868
+ },
39869
+ "&.cm-editor .cm-line.cm-changedLine": {
39870
+ opacity: "1"
39871
+ },
39872
+ "&.cm-editor .cm-gutters": {
39873
+ display: "none"
39874
+ }
39875
+ });
39876
+ const theme = codemirrorThemeDracula.draculaInit({
39877
+ settings: {
39878
+ fontFamily: "var(--geist-mono)",
39879
+ fontSize: "0.8125rem",
39880
+ lineHighlight: "transparent",
39881
+ gutterBackground: "transparent",
39882
+ gutterForeground: "#939393",
39883
+ background: "transparent"
39884
+ },
39885
+ styles: [{ tag: [highlight$1.tags.className, highlight$1.tags.propertyName] }]
39886
+ });
39887
+ function CodeDiff({ codeA, codeB }) {
39888
+ const containerRef = React.useRef(null);
39889
+ const viewRef = React.useRef(null);
39890
+ React.useEffect(() => {
39891
+ if (!containerRef.current) return;
39892
+ if (viewRef.current) {
39893
+ viewRef.current.destroy();
39894
+ }
39895
+ const extensions = [langJson.json(), theme, diffOverrides, view.EditorView.lineWrapping, state.EditorState.readOnly.of(true)];
39896
+ const mergeView = new merge.MergeView({
39897
+ parent: containerRef.current,
39898
+ a: {
39899
+ doc: codeA,
39900
+ extensions
39901
+ },
39902
+ b: {
39903
+ doc: codeB,
39904
+ extensions
39905
+ },
39906
+ collapseUnchanged: { margin: 3, minSize: 4 }
39907
+ });
39908
+ viewRef.current = mergeView;
39909
+ return () => {
39910
+ mergeView.destroy();
39911
+ viewRef.current = null;
39912
+ };
39913
+ }, [codeA, codeB]);
39914
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-auto rounded-xl border border-white/10 bg-black/20", children: [
39915
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 top-0 h-full w-px bg-white/10 z-10" }),
39916
+ /* @__PURE__ */ jsxRuntime.jsx(
39917
+ "div",
39918
+ {
39919
+ ref: containerRef,
39920
+ className: "[&_.cm-mergeViewEditor]:flex-1 [&_.cm-editor]:bg-transparent [&_.cm-editor]:p-6 [&_.cm-gutters]:bg-transparent"
39921
+ }
39922
+ )
39923
+ ] });
39924
+ }
39925
+
37964
39926
  const PlaygroundQueryClient = ({ children, options }) => {
37965
39927
  const queryClient = new reactQuery.QueryClient(options);
37966
39928
  return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children });
@@ -39473,180 +41435,6 @@ function ReferenceViewerDialog({
39473
41435
  ] });
39474
41436
  }
39475
41437
 
39476
- const useSearchSkillsSh = (workspaceId) => {
39477
- const client = react$1.useMastraClient();
39478
- return reactQuery.useMutation({
39479
- mutationFn: async (query) => {
39480
- if (!workspaceId) {
39481
- throw new Error("Workspace ID is required");
39482
- }
39483
- const baseUrl = client.options.baseUrl || "";
39484
- const url = `${baseUrl}/api/workspaces/${workspaceId}/skills-sh/search?q=${encodeURIComponent(query)}&limit=10`;
39485
- const response = await fetch(url);
39486
- if (!response.ok) {
39487
- throw new Error(`Failed to search skills: ${response.statusText}`);
39488
- }
39489
- return response.json().catch(() => {
39490
- throw new Error("Invalid response from server");
39491
- });
39492
- }
39493
- });
39494
- };
39495
- const usePopularSkillsSh = (workspaceId) => {
39496
- const client = react$1.useMastraClient();
39497
- return reactQuery.useQuery({
39498
- queryKey: ["skills-sh", "popular", workspaceId],
39499
- queryFn: async () => {
39500
- if (!workspaceId) {
39501
- throw new Error("Workspace ID is required");
39502
- }
39503
- const baseUrl = client.options.baseUrl || "";
39504
- const url = `${baseUrl}/api/workspaces/${workspaceId}/skills-sh/popular?limit=10&offset=0`;
39505
- const response = await fetch(url);
39506
- if (!response.ok) {
39507
- throw new Error(`Failed to fetch popular skills: ${response.statusText}`);
39508
- }
39509
- return response.json().catch(() => {
39510
- throw new Error("Invalid response from server");
39511
- });
39512
- },
39513
- staleTime: 5 * 60 * 1e3,
39514
- // 5 minutes
39515
- enabled: !!workspaceId
39516
- });
39517
- };
39518
- const useSkillPreview = (workspaceId, owner, repo, skillPath, options) => {
39519
- const client = react$1.useMastraClient();
39520
- return reactQuery.useQuery({
39521
- queryKey: ["skills-sh", "preview", workspaceId, owner, repo, skillPath],
39522
- queryFn: async () => {
39523
- if (!workspaceId || !owner || !repo || !skillPath) {
39524
- throw new Error("workspaceId, owner, repo, and skillPath are required");
39525
- }
39526
- const baseUrl = client.options.baseUrl || "";
39527
- const params = new URLSearchParams({ owner, repo, path: skillPath });
39528
- const url = `${baseUrl}/api/workspaces/${workspaceId}/skills-sh/preview?${params}`;
39529
- const response = await fetch(url);
39530
- if (!response.ok) {
39531
- throw new Error(`Failed to fetch preview: ${response.statusText}`);
39532
- }
39533
- const data = await response.json().catch(() => {
39534
- throw new Error("Invalid response from server");
39535
- });
39536
- return data.content;
39537
- },
39538
- enabled: options?.enabled !== false && !!workspaceId && !!owner && !!repo && !!skillPath,
39539
- retry: false
39540
- });
39541
- };
39542
- const useInstallSkill = () => {
39543
- const client = react$1.useMastraClient();
39544
- const queryClient = reactQuery.useQueryClient();
39545
- return reactQuery.useMutation({
39546
- mutationFn: async (params) => {
39547
- const [owner, repo] = params.repository.split("/");
39548
- if (!owner || !repo) {
39549
- throw new Error("Invalid repository format. Expected owner/repo");
39550
- }
39551
- const baseUrl = client.options.baseUrl || "";
39552
- const url = `${baseUrl}/api/workspaces/${params.workspaceId}/skills-sh/install`;
39553
- const body = { owner, repo, skillName: params.skillName };
39554
- if (params.mount) {
39555
- body.mount = params.mount;
39556
- }
39557
- const response = await fetch(url, {
39558
- method: "POST",
39559
- headers: { "Content-Type": "application/json" },
39560
- body: JSON.stringify(body)
39561
- });
39562
- if (!response.ok) {
39563
- const error = await response.json().catch(() => ({}));
39564
- throw new Error(error.error || error.message || `Failed to install skill: ${response.statusText}`);
39565
- }
39566
- return response.json().catch(() => {
39567
- throw new Error("Invalid response from server");
39568
- });
39569
- },
39570
- onSuccess: (_, variables) => {
39571
- queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
39572
- }
39573
- });
39574
- };
39575
- const useUpdateSkills = () => {
39576
- const client = react$1.useMastraClient();
39577
- const queryClient = reactQuery.useQueryClient();
39578
- return reactQuery.useMutation({
39579
- mutationFn: async (params) => {
39580
- const baseUrl = client.options.baseUrl || "";
39581
- const url = `${baseUrl}/api/workspaces/${params.workspaceId}/skills-sh/update`;
39582
- const response = await fetch(url, {
39583
- method: "POST",
39584
- headers: { "Content-Type": "application/json" },
39585
- body: JSON.stringify({ skillName: params.skillName })
39586
- });
39587
- if (!response.ok) {
39588
- const error = await response.json().catch(() => ({}));
39589
- throw new Error(error.error || error.message || `Failed to update skill: ${response.statusText}`);
39590
- }
39591
- return response.json().catch(() => {
39592
- throw new Error("Invalid response from server");
39593
- });
39594
- },
39595
- onSuccess: (_, variables) => {
39596
- queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
39597
- }
39598
- });
39599
- };
39600
- const useRemoveSkill = () => {
39601
- const client = react$1.useMastraClient();
39602
- const queryClient = reactQuery.useQueryClient();
39603
- return reactQuery.useMutation({
39604
- mutationFn: async (params) => {
39605
- const baseUrl = client.options.baseUrl || "";
39606
- const url = `${baseUrl}/api/workspaces/${params.workspaceId}/skills-sh/remove`;
39607
- const response = await fetch(url, {
39608
- method: "POST",
39609
- headers: { "Content-Type": "application/json" },
39610
- body: JSON.stringify({ skillName: params.skillName })
39611
- });
39612
- if (!response.ok) {
39613
- const error = await response.json().catch(() => ({}));
39614
- throw new Error(error.error || error.message || `Failed to remove skill: ${response.statusText}`);
39615
- }
39616
- return response.json().catch(() => {
39617
- throw new Error("Invalid response from server");
39618
- });
39619
- },
39620
- onSuccess: (_, variables) => {
39621
- queryClient.invalidateQueries({ queryKey: ["workspace", "skills", variables.workspaceId] });
39622
- }
39623
- });
39624
- };
39625
- function parseSkillSource(topSource, skillName) {
39626
- let cleanSource = topSource.replace(/^https?:\/\//, "");
39627
- cleanSource = cleanSource.replace(/^github\.com\//, "");
39628
- cleanSource = cleanSource.replace(/\/$/, "");
39629
- const parts = cleanSource.split("/").filter(Boolean);
39630
- if (parts.length < 2) {
39631
- return null;
39632
- }
39633
- const owner = parts[0];
39634
- const repo = parts[1];
39635
- let skillPath;
39636
- if (parts.length > 2) {
39637
- skillPath = parts.slice(2).join("/");
39638
- } else if (skillName) {
39639
- skillPath = skillName;
39640
- } else {
39641
- return null;
39642
- }
39643
- return {
39644
- owner,
39645
- repo,
39646
- skillPath
39647
- };
39648
- }
39649
-
39650
41438
  function getSkillUniqueId(skill) {
39651
41439
  return `${skill.topSource}/${skill.name}`;
39652
41440
  }
@@ -39909,314 +41697,6 @@ function AddSkillDialog({
39909
41697
  ] }) });
39910
41698
  }
39911
41699
 
39912
- const useWorkspaceInfo = (workspaceId) => {
39913
- const client = react$1.useMastraClient();
39914
- return reactQuery.useQuery({
39915
- queryKey: ["workspace", "info", workspaceId],
39916
- queryFn: async () => {
39917
- if (!compatibility.isWorkspaceV1Supported(client)) {
39918
- throw new Error("Workspace v1 not supported by core or client");
39919
- }
39920
- if (!workspaceId) {
39921
- throw new Error("workspaceId is required");
39922
- }
39923
- const workspace = client.getWorkspace(workspaceId);
39924
- return workspace.info();
39925
- },
39926
- enabled: !!workspaceId && compatibility.isWorkspaceV1Supported(client),
39927
- retry: compatibility.shouldRetryWorkspaceQuery
39928
- });
39929
- };
39930
- const useWorkspaces = () => {
39931
- const client = react$1.useMastraClient();
39932
- return reactQuery.useQuery({
39933
- queryKey: ["workspaces"],
39934
- queryFn: async () => {
39935
- if (!compatibility.isWorkspaceV1Supported(client)) {
39936
- throw new Error("Workspace v1 not supported by core or client");
39937
- }
39938
- return client.listWorkspaces();
39939
- },
39940
- retry: compatibility.shouldRetryWorkspaceQuery
39941
- });
39942
- };
39943
- const useWorkspaceFiles = (path, options) => {
39944
- const client = react$1.useMastraClient();
39945
- return reactQuery.useQuery({
39946
- queryKey: ["workspace", "files", path, options?.recursive, options?.workspaceId],
39947
- queryFn: async () => {
39948
- if (!compatibility.isWorkspaceV1Supported(client)) {
39949
- throw new Error("Workspace v1 not supported by core or client");
39950
- }
39951
- if (!options?.workspaceId) {
39952
- throw new Error("workspaceId is required");
39953
- }
39954
- const workspace = client.getWorkspace(options.workspaceId);
39955
- return workspace.listFiles(path, options?.recursive);
39956
- },
39957
- enabled: options?.enabled !== false && !!path && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
39958
- retry: compatibility.shouldRetryWorkspaceQuery
39959
- });
39960
- };
39961
- const useWorkspaceFile = (path, options) => {
39962
- const client = react$1.useMastraClient();
39963
- return reactQuery.useQuery({
39964
- queryKey: ["workspace", "file", path, options?.workspaceId],
39965
- queryFn: async () => {
39966
- if (!compatibility.isWorkspaceV1Supported(client)) {
39967
- throw new Error("Workspace v1 not supported by core or client");
39968
- }
39969
- if (!options?.workspaceId) {
39970
- throw new Error("workspaceId is required");
39971
- }
39972
- const workspace = client.getWorkspace(options.workspaceId);
39973
- return workspace.readFile(path, options?.encoding);
39974
- },
39975
- enabled: options?.enabled !== false && !!path && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
39976
- retry: compatibility.shouldRetryWorkspaceQuery
39977
- });
39978
- };
39979
- const useWorkspaceFileStat = (path, options) => {
39980
- const client = react$1.useMastraClient();
39981
- return reactQuery.useQuery({
39982
- queryKey: ["workspace", "stat", path, options?.workspaceId],
39983
- queryFn: async () => {
39984
- if (!compatibility.isWorkspaceV1Supported(client)) {
39985
- throw new Error("Workspace v1 not supported by core or client");
39986
- }
39987
- if (!options?.workspaceId) {
39988
- throw new Error("workspaceId is required");
39989
- }
39990
- const workspace = client.getWorkspace(options.workspaceId);
39991
- return workspace.stat(path);
39992
- },
39993
- enabled: options?.enabled !== false && !!path && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
39994
- retry: compatibility.shouldRetryWorkspaceQuery
39995
- });
39996
- };
39997
- const useWriteWorkspaceFile = () => {
39998
- const client = react$1.useMastraClient();
39999
- const queryClient = reactQuery.useQueryClient();
40000
- return reactQuery.useMutation({
40001
- mutationFn: async (params) => {
40002
- if (!compatibility.isWorkspaceV1Supported(client)) {
40003
- throw new Error("Workspace v1 not supported by core or client");
40004
- }
40005
- const workspace = client.getWorkspace(params.workspaceId);
40006
- return workspace.writeFile(params.path, params.content, {
40007
- encoding: params.encoding,
40008
- recursive: params.recursive ?? true
40009
- });
40010
- },
40011
- onSuccess: (_, variables) => {
40012
- const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
40013
- queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
40014
- queryClient.invalidateQueries({ queryKey: ["workspace", "file", variables.path] });
40015
- }
40016
- });
40017
- };
40018
- const useWriteWorkspaceFileFromFile = () => {
40019
- const client = react$1.useMastraClient();
40020
- const queryClient = reactQuery.useQueryClient();
40021
- return reactQuery.useMutation({
40022
- mutationFn: async (params) => {
40023
- if (!compatibility.isWorkspaceV1Supported(client)) {
40024
- throw new Error("Workspace v1 not supported by core or client");
40025
- }
40026
- const arrayBuffer = await params.file.arrayBuffer();
40027
- const base64 = btoa(new Uint8Array(arrayBuffer).reduce((data, byte) => data + String.fromCharCode(byte), ""));
40028
- const workspace = client.getWorkspace(params.workspaceId);
40029
- return workspace.writeFile(params.path, base64, {
40030
- encoding: "base64",
40031
- recursive: params.recursive ?? true
40032
- });
40033
- },
40034
- onSuccess: (_, variables) => {
40035
- const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
40036
- queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
40037
- queryClient.invalidateQueries({ queryKey: ["workspace", "file", variables.path] });
40038
- }
40039
- });
40040
- };
40041
- const useDeleteWorkspaceFile = () => {
40042
- const client = react$1.useMastraClient();
40043
- const queryClient = reactQuery.useQueryClient();
40044
- return reactQuery.useMutation({
40045
- mutationFn: async (params) => {
40046
- if (!compatibility.isWorkspaceV1Supported(client)) {
40047
- throw new Error("Workspace v1 not supported by core or client");
40048
- }
40049
- const workspace = client.getWorkspace(params.workspaceId);
40050
- return workspace.delete(params.path, {
40051
- recursive: params.recursive,
40052
- force: params.force
40053
- });
40054
- },
40055
- onSuccess: (_, variables) => {
40056
- const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
40057
- queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
40058
- queryClient.invalidateQueries({ queryKey: ["workspace", "file", variables.path] });
40059
- }
40060
- });
40061
- };
40062
- const useCreateWorkspaceDirectory = () => {
40063
- const client = react$1.useMastraClient();
40064
- const queryClient = reactQuery.useQueryClient();
40065
- return reactQuery.useMutation({
40066
- mutationFn: async (params) => {
40067
- if (!compatibility.isWorkspaceV1Supported(client)) {
40068
- throw new Error("Workspace v1 not supported by core or client");
40069
- }
40070
- const workspace = client.getWorkspace(params.workspaceId);
40071
- return workspace.mkdir(params.path, params.recursive);
40072
- },
40073
- onSuccess: (_, variables) => {
40074
- const parentPath = variables.path.split("/").slice(0, -1).join("/") || "/";
40075
- queryClient.invalidateQueries({ queryKey: ["workspace", "files", parentPath] });
40076
- }
40077
- });
40078
- };
40079
- const useSearchWorkspace = () => {
40080
- const client = react$1.useMastraClient();
40081
- return reactQuery.useMutation({
40082
- mutationFn: async (params) => {
40083
- if (!compatibility.isWorkspaceV1Supported(client)) {
40084
- throw new Error("Workspace v1 not supported by core or client");
40085
- }
40086
- const workspace = client.getWorkspace(params.workspaceId);
40087
- return workspace.search({
40088
- query: params.query,
40089
- topK: params.topK,
40090
- mode: params.mode,
40091
- minScore: params.minScore
40092
- });
40093
- }
40094
- });
40095
- };
40096
- const useIndexWorkspaceContent = () => {
40097
- const client = react$1.useMastraClient();
40098
- return reactQuery.useMutation({
40099
- mutationFn: async (params) => {
40100
- if (!compatibility.isWorkspaceV1Supported(client)) {
40101
- throw new Error("Workspace v1 not supported by core or client");
40102
- }
40103
- const workspace = client.getWorkspace(params.workspaceId);
40104
- return workspace.index({
40105
- path: params.path,
40106
- content: params.content,
40107
- metadata: params.metadata
40108
- });
40109
- }
40110
- });
40111
- };
40112
-
40113
- const useWorkspaceSkills = (options) => {
40114
- const client = react$1.useMastraClient();
40115
- return reactQuery.useQuery({
40116
- queryKey: ["workspace", "skills", options?.workspaceId],
40117
- queryFn: async () => {
40118
- if (!compatibility.isWorkspaceV1Supported(client)) {
40119
- throw new Error("Workspace v1 not supported by core or client");
40120
- }
40121
- if (!options?.workspaceId) {
40122
- throw new Error("workspaceId is required");
40123
- }
40124
- const workspace = client.getWorkspace(options.workspaceId);
40125
- return workspace.listSkills();
40126
- },
40127
- enabled: !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
40128
- retry: compatibility.shouldRetryWorkspaceQuery
40129
- });
40130
- };
40131
- const useWorkspaceSkill = (skillName, options) => {
40132
- const client = react$1.useMastraClient();
40133
- return reactQuery.useQuery({
40134
- queryKey: ["workspace", "skills", skillName, options?.workspaceId],
40135
- queryFn: async () => {
40136
- if (!compatibility.isWorkspaceV1Supported(client)) {
40137
- throw new Error("Workspace v1 not supported by core or client");
40138
- }
40139
- if (!options?.workspaceId) {
40140
- throw new Error("workspaceId is required");
40141
- }
40142
- const workspace = client.getWorkspace(options.workspaceId);
40143
- const skill = workspace.getSkill(skillName);
40144
- return skill.details();
40145
- },
40146
- enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
40147
- retry: compatibility.shouldRetryWorkspaceQuery
40148
- });
40149
- };
40150
- const useWorkspaceSkillReferences = (skillName, options) => {
40151
- const client = react$1.useMastraClient();
40152
- return reactQuery.useQuery({
40153
- queryKey: ["workspace", "skills", skillName, "references", options?.workspaceId],
40154
- queryFn: async () => {
40155
- if (!compatibility.isWorkspaceV1Supported(client)) {
40156
- throw new Error("Workspace v1 not supported by core or client");
40157
- }
40158
- if (!options?.workspaceId) {
40159
- throw new Error("workspaceId is required");
40160
- }
40161
- const workspace = client.getWorkspace(options.workspaceId);
40162
- const skill = workspace.getSkill(skillName);
40163
- return skill.listReferences();
40164
- },
40165
- enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
40166
- retry: compatibility.shouldRetryWorkspaceQuery
40167
- });
40168
- };
40169
- const useWorkspaceSkillReference = (skillName, referencePath, options) => {
40170
- const client = react$1.useMastraClient();
40171
- return reactQuery.useQuery({
40172
- queryKey: ["workspace", "skills", skillName, "references", referencePath, options?.workspaceId],
40173
- queryFn: async () => {
40174
- if (!compatibility.isWorkspaceV1Supported(client)) {
40175
- throw new Error("Workspace v1 not supported by core or client");
40176
- }
40177
- if (!options?.workspaceId) {
40178
- throw new Error("workspaceId is required");
40179
- }
40180
- const workspace = client.getWorkspace(options.workspaceId);
40181
- const skill = workspace.getSkill(skillName);
40182
- return skill.getReference(referencePath);
40183
- },
40184
- enabled: options?.enabled !== false && !!skillName && !!referencePath && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
40185
- retry: compatibility.shouldRetryWorkspaceQuery
40186
- });
40187
- };
40188
- const useSearchWorkspaceSkills = () => {
40189
- const client = react$1.useMastraClient();
40190
- return reactQuery.useMutation({
40191
- mutationFn: async (params) => {
40192
- if (!compatibility.isWorkspaceV1Supported(client)) {
40193
- throw new Error("Workspace v1 not supported by core or client");
40194
- }
40195
- const workspace = client.getWorkspace(params.workspaceId);
40196
- return workspace.searchSkills(params);
40197
- }
40198
- });
40199
- };
40200
- const useAgentSkill = (agentId, skillName, options) => {
40201
- const client = react$1.useMastraClient();
40202
- return reactQuery.useQuery({
40203
- queryKey: ["agents", agentId, "skills", skillName, options?.workspaceId],
40204
- queryFn: async () => {
40205
- if (!compatibility.isWorkspaceV1Supported(client)) {
40206
- throw new Error("Workspace v1 not supported by core or client");
40207
- }
40208
- if (!options?.workspaceId) {
40209
- throw new Error("workspaceId is required");
40210
- }
40211
- const workspace = client.getWorkspace(options.workspaceId);
40212
- const skill = workspace.getSkill(skillName);
40213
- return skill.details();
40214
- },
40215
- enabled: options?.enabled !== false && !!agentId && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
40216
- retry: compatibility.shouldRetryWorkspaceQuery
40217
- });
40218
- };
40219
-
40220
41700
  const useMastraPlatform = () => {
40221
41701
  const mastraPlatformEndpoint = window.MASTRA_CLOUD_API_ENDPOINT;
40222
41702
  const isMastraPlatform = Boolean(mastraPlatformEndpoint);
@@ -40499,6 +41979,7 @@ exports.AgentSettingsProvider = AgentSettingsProvider;
40499
41979
  exports.AgentSourceIcon = AgentSourceIcon;
40500
41980
  exports.AgentToolPanel = AgentToolPanel;
40501
41981
  exports.AgentVersionCombobox = AgentVersionCombobox;
41982
+ exports.AgentVersionPanel = AgentVersionPanel;
40502
41983
  exports.AgentsCmsLayout = AgentsCmsLayout;
40503
41984
  exports.AgentsPage = AgentsPage;
40504
41985
  exports.AgentsSection = AgentsSection;
@@ -40523,6 +42004,7 @@ exports.ChatThreads = ChatThreads;
40523
42004
  exports.CheckIcon = CheckIcon;
40524
42005
  exports.Checkbox = Checkbox;
40525
42006
  exports.ChevronIcon = ChevronIcon;
42007
+ exports.CodeDiff = CodeDiff;
40526
42008
  exports.CodeEditor = CodeEditor;
40527
42009
  exports.Collapsible = Collapsible;
40528
42010
  exports.CollapsibleContent = CollapsibleContent;
@@ -40550,6 +42032,7 @@ exports.CreateDatasetDialog = CreateDatasetDialog;
40550
42032
  exports.CreateDatasetFromItemsDialog = CreateDatasetFromItemsDialog;
40551
42033
  exports.CrossIcon = CrossIcon;
40552
42034
  exports.Crumb = Crumb;
42035
+ exports.DatasetCombobox = DatasetCombobox;
40553
42036
  exports.DatasetCompareVersionToolbar = DatasetCompareVersionToolbar;
40554
42037
  exports.DatasetCompareVersionsList = DatasetCompareVersionsList;
40555
42038
  exports.DatasetExperiments = DatasetExperiments;
@@ -40754,6 +42237,7 @@ exports.SkillIcon = SkillIcon;
40754
42237
  exports.SkillRemoveButton = SkillRemoveButton;
40755
42238
  exports.SkillUpdateButton = SkillUpdateButton;
40756
42239
  exports.SkillsNotConfigured = SkillsNotConfigured;
42240
+ exports.SkillsPage = SkillsPage;
40757
42241
  exports.SkillsTable = SkillsTable;
40758
42242
  exports.SlashIcon = SlashIcon;
40759
42243
  exports.Slider = Slider;
@@ -40817,6 +42301,7 @@ exports.TracesList = TracesList;
40817
42301
  exports.TracesTools = TracesTools;
40818
42302
  exports.TracingSettingsContext = TracingSettingsContext;
40819
42303
  exports.TracingSettingsProvider = TracingSettingsProvider;
42304
+ exports.Tree = Tree;
40820
42305
  exports.Truncate = Truncate;
40821
42306
  exports.TsIcon = TsIcon;
40822
42307
  exports.Txt = Txt;
@@ -40893,7 +42378,9 @@ exports.mapInstructionBlocksToApi = mapInstructionBlocksToApi;
40893
42378
  exports.mapScorersToApi = mapScorersToApi;
40894
42379
  exports.normalizeIntegrationToolsToRecord = normalizeIntegrationToolsToRecord;
40895
42380
  exports.normalizeScorersFromApi = normalizeScorersFromApi;
42381
+ exports.normalizeSkillsFromApi = normalizeSkillsFromApi;
40896
42382
  exports.normalizeToolsToRecord = normalizeToolsToRecord;
42383
+ exports.normalizeWorkspaceFromApi = normalizeWorkspaceFromApi;
40897
42384
  exports.parseError = parseError;
40898
42385
  exports.parseFieldPath = parseFieldPath;
40899
42386
  exports.parseJSONCell = parseJSONCell;
@@ -40936,6 +42423,7 @@ exports.useCompareExperiments = useCompareExperiments;
40936
42423
  exports.useCompareScorerVersions = useCompareScorerVersions;
40937
42424
  exports.useCreateAgentVersion = useCreateAgentVersion;
40938
42425
  exports.useCreateScorerVersion = useCreateScorerVersion;
42426
+ exports.useCreateSkill = useCreateSkill;
40939
42427
  exports.useCreateWorkspaceDirectory = useCreateWorkspaceDirectory;
40940
42428
  exports.useCurrentRun = useCurrentRun;
40941
42429
  exports.useDataset = useDataset;
@@ -41018,6 +42506,7 @@ exports.useStoredAgentMutations = useStoredAgentMutations;
41018
42506
  exports.useStoredAgents = useStoredAgents;
41019
42507
  exports.useStoredScorer = useStoredScorer;
41020
42508
  exports.useStoredScorerMutations = useStoredScorerMutations;
42509
+ exports.useStoredSkills = useStoredSkills;
41021
42510
  exports.useStudioConfig = useStudioConfig;
41022
42511
  exports.useTableKeyboardNavigation = useTableKeyboardNavigation;
41023
42512
  exports.useThreadInput = useThreadInput;