@mastra/playground-ui 6.2.2-alpha.2 → 6.2.2

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.
package/dist/index.cjs.js CHANGED
@@ -63,6 +63,7 @@ const HoverCard = require('@radix-ui/react-hover-card');
63
63
  const AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
64
64
  const runtimeContext = require('@mastra/core/runtime-context');
65
65
  const format = require('date-fns/format');
66
+ const DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
66
67
 
67
68
  function _interopNamespaceDefault(e) {
68
69
  const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
@@ -97,6 +98,7 @@ const TabsPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(TabsPrimi
97
98
  const VisuallyHidden__namespace = /*#__PURE__*/_interopNamespaceDefault(VisuallyHidden);
98
99
  const HoverCard__namespace = /*#__PURE__*/_interopNamespaceDefault(HoverCard);
99
100
  const AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(AlertDialogPrimitive);
101
+ const DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DropdownMenuPrimitive);
100
102
 
101
103
  const createMastraClient = (baseUrl, mastraClientHeaders = {}) => {
102
104
  return new clientJs.MastraClient({
@@ -4552,16 +4554,16 @@ const usePlaygroundStore = zustand.create()(
4552
4554
  )
4553
4555
  );
4554
4556
 
4555
- const useWorkflow = (workflowId, enabled = true) => {
4557
+ const useWorkflow = (workflowId) => {
4556
4558
  const client = useMastraClient();
4557
4559
  const { runtimeContext } = usePlaygroundStore();
4558
4560
  return reactQuery.useQuery({
4559
4561
  queryKey: ["workflow", workflowId],
4560
- queryFn: () => client.getWorkflow(workflowId).details(runtimeContext),
4562
+ queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
4563
+ enabled: Boolean(workflowId),
4561
4564
  retry: false,
4562
4565
  refetchOnWindowFocus: false,
4563
- throwOnError: false,
4564
- enabled
4566
+ throwOnError: false
4565
4567
  });
4566
4568
  };
4567
4569
  const useLegacyWorkflow = (workflowId) => {
@@ -8292,7 +8294,7 @@ const Row = React.forwardRef(
8292
8294
  "tr",
8293
8295
  {
8294
8296
  className: clsx(
8295
- "border-b-sm border-border1 hover:bg-surface3 focus:bg-surface3 -outline-offset-2",
8297
+ "border-b-sm border-border1 hover:bg-surface3 focus:bg-surface3 -outline-offset-2 last:border-b-0",
8296
8298
  selected && "bg-surface4",
8297
8299
  onClick && "cursor-pointer",
8298
8300
  className
@@ -12947,13 +12949,13 @@ function KeyValueList({ data, LinkComponent, className, labelsAreHidden, isLoadi
12947
12949
  style: { width: `${Math.floor(Math.random() * (90 - 30 + 1)) + 50}%` },
12948
12950
  children: " "
12949
12951
  }
12950
- ) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isValueItemArray ? value?.map((item) => {
12952
+ ) : isValueItemArray ? value?.map((item) => {
12951
12953
  return item.path ? /* @__PURE__ */ jsxRuntime.jsx(RelationWrapper, { description: item.description, children: /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: item.path, children: [
12952
12954
  item?.name,
12953
12955
  " ",
12954
12956
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, {})
12955
12957
  ] }) }, item.id) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: item?.name }, item.id);
12956
- }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value ? value : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-icon3 text-[0.75rem]", children: "n/a" }) }) })
12958
+ }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value ? value : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-icon3 text-[0.75rem]", children: "n/a" }) })
12957
12959
  }
12958
12960
  )
12959
12961
  ] }, label + index);
@@ -13649,7 +13651,7 @@ const DateTimePicker = ({
13649
13651
  /* @__PURE__ */ jsxRuntime.jsx(
13650
13652
  PopoverContent,
13651
13653
  {
13652
- className: "backdrop-blur-4xl w-auto p-0 bg-surface4 max-w-[16.5rem]",
13654
+ className: "backdrop-blur-4xl w-auto !p-0 bg-surface4 max-w-[16.5rem]",
13653
13655
  align: "start",
13654
13656
  "data-testid": "datepicker-calendar",
13655
13657
  children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -13775,7 +13777,7 @@ const DateTimePickerContent = ({
13775
13777
  "div",
13776
13778
  {
13777
13779
  "aria-label": "Choose date",
13778
- className: cn("relative mt-2 flex flex-col ", className),
13780
+ className: cn("relative flex flex-col", className),
13779
13781
  onKeyDown: (e) => {
13780
13782
  e.stopPropagation();
13781
13783
  if (e.key === "Escape") {
@@ -13872,7 +13874,16 @@ function getShortId(id) {
13872
13874
  return id.slice(0, 8);
13873
13875
  }
13874
13876
 
13875
- function ScoreDialog({ scorer, score, isOpen, onClose, onNext, onPrevious }) {
13877
+ function ScoreDialog({
13878
+ scorer,
13879
+ score,
13880
+ isOpen,
13881
+ onClose,
13882
+ onNext,
13883
+ onPrevious,
13884
+ computeTraceLink
13885
+ }) {
13886
+ const { Link } = useLinkComponent();
13876
13887
  return /* @__PURE__ */ jsxRuntime.jsxs(
13877
13888
  SideDialog,
13878
13889
  {
@@ -13895,10 +13906,30 @@ function ScoreDialog({ scorer, score, isOpen, onClose, onNext, onPrevious }) {
13895
13906
  ] })
13896
13907
  ] }) }),
13897
13908
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-[1.5rem] px-[2.5rem] overflow-y-auto grid gap-[1.5rem] content-start", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-[1.5rem] mb-[2rem]", children: [
13909
+ score?.traceId && /* @__PURE__ */ jsxRuntime.jsx(
13910
+ KeyValueList,
13911
+ {
13912
+ data: [
13913
+ {
13914
+ label: "Trace ID",
13915
+ value: /* @__PURE__ */ jsxRuntime.jsx(Link, { href: computeTraceLink(score?.traceId), children: score?.traceId }),
13916
+ key: "traceId"
13917
+ },
13918
+ ...score?.spanId ? [
13919
+ {
13920
+ label: "Span ID",
13921
+ value: /* @__PURE__ */ jsxRuntime.jsx(Link, { href: computeTraceLink(score?.traceId, score?.spanId), children: score?.spanId }),
13922
+ key: "spanId"
13923
+ }
13924
+ ] : []
13925
+ ],
13926
+ LinkComponent: Link
13927
+ }
13928
+ ),
13898
13929
  /* @__PURE__ */ jsxRuntime.jsx(
13899
13930
  SideDialogCodeSection,
13900
13931
  {
13901
- title: `Score: ${score?.score ? score?.score : "n/a"}`,
13932
+ title: `Score: ${Number.isNaN(score?.score) ? "n/a" : score?.score}`,
13902
13933
  codeStr: score?.reason,
13903
13934
  simplified: true
13904
13935
  }
@@ -13990,29 +14021,11 @@ const useScoresByEntityId = (entityId, entityType, page = 0) => {
13990
14021
  };
13991
14022
  const useScoresByScorerId = ({ scorerId, page = 0, entityId, entityType }) => {
13992
14023
  const client = useMastraClient();
13993
- const [scores, setScores] = React.useState(null);
13994
- const [isLoading, setIsLoading] = React.useState(true);
13995
- React.useEffect(() => {
13996
- const fetchScores = async () => {
13997
- setIsLoading(true);
13998
- try {
13999
- const res = await client.getScoresByScorerId({
14000
- scorerId,
14001
- page: page || 0,
14002
- entityId: entityId || void 0,
14003
- entityType: entityType || void 0,
14004
- perPage: 10
14005
- });
14006
- setScores(res);
14007
- setIsLoading(false);
14008
- } catch (error) {
14009
- setScores(null);
14010
- setIsLoading(false);
14011
- }
14012
- };
14013
- fetchScores();
14014
- }, [scorerId, page, entityId, entityType]);
14015
- return { scores, isLoading };
14024
+ return reactQuery.useQuery({
14025
+ queryKey: ["scores", scorerId, page, entityId, entityType],
14026
+ queryFn: () => client.getScoresByScorerId({ scorerId, page, entityId, entityType, perPage: 10 }),
14027
+ refetchInterval: 5e3
14028
+ });
14016
14029
  };
14017
14030
  const useScorer = (scorerId) => {
14018
14031
  const client = useMastraClient();
@@ -14038,25 +14051,12 @@ const useScorer = (scorerId) => {
14038
14051
  };
14039
14052
  const useScorers = () => {
14040
14053
  const client = useMastraClient();
14041
- const [scorers, setScorers] = React.useState({});
14042
- const [isLoading, setIsLoading] = React.useState(true);
14043
- React.useEffect(() => {
14044
- const fetchScorers = async () => {
14045
- setIsLoading(true);
14046
- try {
14047
- const res = await client.getScorers();
14048
- setScorers(res);
14049
- } catch (error) {
14050
- setScorers({});
14051
- console.error("Error fetching agents", error);
14052
- sonner.toast.error("Error fetching agents");
14053
- } finally {
14054
- setIsLoading(false);
14055
- }
14056
- };
14057
- fetchScorers();
14058
- }, []);
14059
- return { scorers, isLoading };
14054
+ return reactQuery.useQuery({
14055
+ queryKey: ["scorers"],
14056
+ queryFn: () => client.getScorers(),
14057
+ staleTime: 0,
14058
+ gcTime: 0
14059
+ });
14060
14060
  };
14061
14061
 
14062
14062
  const NameCell = ({ row }) => {
@@ -14303,7 +14303,9 @@ const AgentMetadataModelSwitcher = ({
14303
14303
  defaultModel,
14304
14304
  updateModel,
14305
14305
  closeEditor,
14306
- modelProviders
14306
+ modelProviders,
14307
+ autoSave = false,
14308
+ selectProviderPlaceholder = "Select provider"
14307
14309
  }) => {
14308
14310
  const [selectedModel, setSelectedModel] = React.useState(defaultModel);
14309
14311
  const [showSuggestions, setShowSuggestions] = React.useState(false);
@@ -14315,10 +14317,19 @@ const AgentMetadataModelSwitcher = ({
14315
14317
  return "";
14316
14318
  });
14317
14319
  const [loading, setLoading] = React.useState(false);
14320
+ const [infoMsg, setInfoMsg] = React.useState("");
14318
14321
  const modelsList = Object.entries(Models).filter(([provider]) => modelProviders.includes(provider));
14319
14322
  const allModels = modelsList.flatMap(([_, { models }]) => models);
14320
14323
  const providersList = modelsList.map(([provider, { icon }]) => ({ provider, icon }));
14321
14324
  const model = allModels.find((model2) => model2.model === selectedModel);
14325
+ React.useEffect(() => {
14326
+ const isValidModel = allModels.some((model2) => model2.model === selectedModel);
14327
+ if (selectedModel && !isValidModel) {
14328
+ setInfoMsg("Model not in suggestions—make sure the name is correct.");
14329
+ } else {
14330
+ setInfoMsg("");
14331
+ }
14332
+ }, [selectedModel, allModels]);
14322
14333
  const handleSave = async () => {
14323
14334
  setLoading(true);
14324
14335
  const providerToUse = model?.provider ?? selectedProvider;
@@ -14326,67 +14337,156 @@ const AgentMetadataModelSwitcher = ({
14326
14337
  setLoading(false);
14327
14338
  closeEditor();
14328
14339
  };
14329
- const filteredModels = allModels.filter((model2) => model2.model.includes(selectedModel));
14330
- return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
14340
+ const filteredModels = allModels.filter((model2) => {
14341
+ if (selectedProvider) {
14342
+ return model2.model.includes(selectedModel) && model2.provider === selectedProvider;
14343
+ }
14344
+ return model2.model.includes(selectedModel);
14345
+ });
14346
+ const handleProviderChange = (provider) => {
14347
+ setSelectedProvider(provider);
14348
+ setSelectedModel("");
14349
+ if (autoSave) {
14350
+ updateModel({
14351
+ provider,
14352
+ modelId: ""
14353
+ });
14354
+ }
14355
+ };
14356
+ const handleModelInputBlur = (e) => {
14357
+ setShowSuggestions(false);
14358
+ const isValidModel = allModels.some((model2) => model2.model === e.target.value);
14359
+ if (!isValidModel) {
14360
+ if (autoSave) {
14361
+ updateModel({
14362
+ provider: selectedProvider,
14363
+ modelId: e.target.value
14364
+ });
14365
+ }
14366
+ }
14367
+ };
14368
+ const handleModelClick = (model2) => {
14369
+ setSelectedModel(model2.model);
14370
+ const isValidModel = allModels.some((m) => m.model === model2.model);
14371
+ if (isValidModel) {
14372
+ setSelectedProvider(model2.provider);
14373
+ }
14374
+ if (autoSave) {
14375
+ updateModel({
14376
+ provider: model2.provider,
14377
+ modelId: model2.model
14378
+ });
14379
+ }
14380
+ setShowSuggestions(false);
14381
+ };
14382
+ const handleModelInputChange = (e) => {
14383
+ setSelectedModel(e.target.value);
14384
+ const isValidModel = allModels.some((m) => m.model === e.target.value);
14385
+ if (isValidModel) {
14386
+ const model2 = allModels.find((m) => m.model === e.target.value);
14387
+ if (model2) {
14388
+ setSelectedProvider(model2.provider);
14389
+ }
14390
+ }
14391
+ };
14392
+ const handleModelReset = () => {
14393
+ setSelectedModel("");
14394
+ setInfoMsg("");
14395
+ if (autoSave) {
14396
+ updateModel({
14397
+ provider: selectedProvider,
14398
+ modelId: ""
14399
+ });
14400
+ }
14401
+ };
14402
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
14331
14403
  /* @__PURE__ */ jsxRuntime.jsxs(
14332
- Select$1,
14404
+ "div",
14333
14405
  {
14334
- value: model?.provider ?? selectedProvider,
14335
- onValueChange: setSelectedProvider,
14336
- disabled: !!model?.provider,
14406
+ className: cn("grid items-center gap-2", {
14407
+ "xl:grid-cols-[auto_1fr_auto]": !autoSave,
14408
+ "xl:grid-cols-[auto_1fr]": autoSave
14409
+ }),
14337
14410
  children: [
14338
- /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "max-w-[150px]", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select provider" }) }),
14339
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: providersList.map((provider) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: provider.provider, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
14340
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: providerMapToIcon[provider.icon] }),
14341
- provider.provider
14342
- ] }) }, provider.provider)) })
14411
+ /* @__PURE__ */ jsxRuntime.jsxs(Select$1, { value: selectedProvider, onValueChange: handleProviderChange, disabled: !!model?.provider, children: [
14412
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: selectProviderPlaceholder }) }),
14413
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: providersList.map((provider) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: provider.provider, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
14414
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: providerMapToIcon[provider.icon] }),
14415
+ provider.provider
14416
+ ] }) }, provider.provider)) })
14417
+ ] }),
14418
+ /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: showSuggestions, children: [
14419
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
14420
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
14421
+ Input,
14422
+ {
14423
+ id: "model-input",
14424
+ list: "model-suggestions",
14425
+ className: "flex-1 w-full h-[2.25rem] rounded-md min-w-[12rem]",
14426
+ type: "text",
14427
+ value: selectedModel,
14428
+ onChange: handleModelInputChange,
14429
+ onFocus: () => setShowSuggestions(true),
14430
+ onBlur: handleModelInputBlur,
14431
+ placeholder: "Enter model name or select from suggestions...",
14432
+ autoComplete: "off"
14433
+ }
14434
+ ) }),
14435
+ selectedModel && /* @__PURE__ */ jsxRuntime.jsx(
14436
+ "button",
14437
+ {
14438
+ className: "flex items-center justify-center absolute top-0 right-0 text-icon3 hover:text-white hover:text-icon4 w-[2.25rem] h-[2.25rem] p-[.5rem] rounded-md",
14439
+ onClick: handleModelReset,
14440
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {})
14441
+ }
14442
+ )
14443
+ ] }),
14444
+ filteredModels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
14445
+ PopoverContent,
14446
+ {
14447
+ onOpenAutoFocus: (e) => e.preventDefault(),
14448
+ className: "flex flex-col w-[var(--radix-popover-trigger-width)] max-h-[calc(var(--radix-popover-content-available-height)-50px)] overflow-y-auto",
14449
+ children: filteredModels.map((model2) => /* @__PURE__ */ jsxRuntime.jsx(
14450
+ "button",
14451
+ {
14452
+ className: "flex items-center justify-start gap-2 cursor-pointer hover:bg-surface5 p-2 text-[0.875rem]",
14453
+ onClick: () => handleModelClick(model2),
14454
+ children: model2.model
14455
+ },
14456
+ model2.provider + model2.model
14457
+ ))
14458
+ }
14459
+ )
14460
+ ] }),
14461
+ !autoSave && /* @__PURE__ */ jsxRuntime.jsx(
14462
+ Button$2,
14463
+ {
14464
+ onClick: handleSave,
14465
+ variant: "secondary",
14466
+ size: "sm",
14467
+ disabled: loading || !selectedModel,
14468
+ className: "w-full",
14469
+ children: loading ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) : "Save"
14470
+ }
14471
+ )
14343
14472
  ]
14344
14473
  }
14345
14474
  ),
14346
- /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: showSuggestions, children: [
14347
- /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
14348
- Input,
14349
- {
14350
- id: "model-input",
14351
- list: "model-suggestions",
14352
- className: "flex-1",
14353
- type: "text",
14354
- value: selectedModel,
14355
- onChange: (e) => {
14356
- setSelectedModel(e.target.value);
14357
- setShowSuggestions(true);
14358
- },
14359
- placeholder: "Enter model name or select from suggestions..."
14360
- }
14361
- ) }),
14362
- filteredModels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
14363
- PopoverContent,
14364
- {
14365
- onOpenAutoFocus: (e) => e.preventDefault(),
14366
- className: "flex flex-col gap-2 w-[var(--radix-popover-trigger-width)] max-h-[calc(var(--radix-popover-content-available-height)-50px)] overflow-y-auto",
14367
- children: filteredModels.map((model2) => /* @__PURE__ */ jsxRuntime.jsxs(
14368
- "div",
14369
- {
14370
- className: "flex items-center gap-2 cursor-pointer hover:bg-surface5 p-2",
14371
- onClick: () => {
14372
- setSelectedModel(model2.model);
14373
- setShowSuggestions(false);
14374
- },
14375
- children: [
14376
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: providerMapToIcon[model2.icon] }),
14377
- model2.model
14378
- ]
14379
- },
14380
- model2.provider + model2.model
14381
- ))
14382
- }
14383
- )
14384
- ] }),
14385
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
14386
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: handleSave, className: "text-icon3 hover:text-icon6", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: loading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheck, {}) }) }) }),
14387
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: loading ? "Saving..." : "Save new model" })
14388
- ] })
14389
- ] }) });
14475
+ infoMsg && /* @__PURE__ */ jsxRuntime.jsxs(
14476
+ "div",
14477
+ {
14478
+ className: cn(
14479
+ "text-[0.75rem] text-icon3 flex gap-[.5rem] mt-[0.5rem] ml-[.5rem]",
14480
+ "[&>svg]:w-[1.1em] [&>svg]:h-[1.1em] [&>svg]:opacity-7 [&>svg]:flex-shrink-0 [&>svg]:mt-[0.1rem]"
14481
+ ),
14482
+ children: [
14483
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.InfoIcon, {}),
14484
+ " ",
14485
+ infoMsg
14486
+ ]
14487
+ }
14488
+ )
14489
+ ] });
14390
14490
  };
14391
14491
 
14392
14492
  const AgentMetadataNetworkList = ({ agents }) => {
@@ -14499,11 +14599,11 @@ const AgentMetadataWorkflowList = ({ workflows }) => {
14499
14599
  };
14500
14600
  const AgentMetadataScorerList = ({ entityId, entityType }) => {
14501
14601
  const { Link, paths } = useLinkComponent();
14502
- const { scorers, isLoading } = useScorers();
14602
+ const { data: scorers = {}, isLoading } = useScorers();
14503
14603
  const scorerList = Object.keys(scorers).filter((scorerKey) => {
14504
14604
  const scorer = scorers[scorerKey];
14505
14605
  if (entityType === "AGENT") {
14506
- return scorer.agentIds.includes(entityId);
14606
+ return scorer.agentNames.includes(entityId);
14507
14607
  }
14508
14608
  return scorer.workflowIds.includes(entityId);
14509
14609
  }).map((scorerKey) => ({ ...scorers[scorerKey], id: scorerKey }));
@@ -15916,10 +16016,11 @@ const ToolListInner = ({ toolsWithAgents }) => {
15916
16016
  const ToolEntity = ({ tool }) => {
15917
16017
  const linkRef = React.useRef(null);
15918
16018
  const { Link, paths } = useLinkComponent();
16019
+ const toolLink = tool.agents.length > 0 ? paths.agentToolLink(tool.agents[0].id, tool.id) : paths.toolLink(tool.id);
15919
16020
  return /* @__PURE__ */ jsxRuntime.jsxs(Entity, { onClick: () => linkRef.current?.click(), children: [
15920
16021
  /* @__PURE__ */ jsxRuntime.jsx(EntityIcon, { children: /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, { className: "group-hover/entity:text-[#ECB047]" }) }),
15921
16022
  /* @__PURE__ */ jsxRuntime.jsxs(EntityContent, { children: [
15922
- /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: /* @__PURE__ */ jsxRuntime.jsx(Link, { ref: linkRef, href: paths.toolLink(tool.id), children: tool.id }) }),
16023
+ /* @__PURE__ */ jsxRuntime.jsx(EntityName, { children: /* @__PURE__ */ jsxRuntime.jsx(Link, { ref: linkRef, href: toolLink, children: tool.id }) }),
15923
16024
  /* @__PURE__ */ jsxRuntime.jsx(EntityDescription, { children: tool.description }),
15924
16025
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex flex-wrap gap-2 pt-4", children: tool.agents.map((agent) => {
15925
16026
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -16292,7 +16393,7 @@ function TemplateForm({
16292
16393
  "h2",
16293
16394
  {
16294
16395
  className: cn(
16295
- "text-icon5 text-[1.125rem] font-semibold flex items-center gap-[0.5rem]",
16396
+ "text-icon4 text-[1.125rem] font-semibold flex items-center gap-[0.5rem]",
16296
16397
  "[&>svg]:w-[1.2em] [&_svg]:h-[1.2em] [&_svg]:opacity-70 "
16297
16398
  ),
16298
16399
  children: [
@@ -16305,29 +16406,13 @@ function TemplateForm({
16305
16406
  SelectField,
16306
16407
  {
16307
16408
  options: providerOptions,
16308
- label: "Provider",
16409
+ label: "Template AI Model Provider",
16309
16410
  onValueChange: onProviderChange,
16310
16411
  value: selectedProvider,
16311
- placeholder: "Select a provider"
16412
+ placeholder: "Select"
16312
16413
  }
16313
16414
  ),
16314
16415
  selectedProvider && Object.entries(variables || {}).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16315
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-[0.5rem]", children: [
16316
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon3 text-[0.875rem] font-medium", children: "Select AI Model for Template Installation *" }),
16317
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-icon4 text-[0.75rem]", children: "This model will be used by the workflow to process and install the template" }),
16318
- /* @__PURE__ */ jsxRuntime.jsx(
16319
- AgentMetadataModelSwitcher,
16320
- {
16321
- defaultProvider: defaultModelProvider || "",
16322
- defaultModel: defaultModelId || "",
16323
- updateModel: onModelUpdate || (() => Promise.resolve({ message: "Updated" })),
16324
- closeEditor: () => {
16325
- },
16326
- modelProviders: ["openai", "anthropic", "google", "xai", "groq"]
16327
- }
16328
- ),
16329
- (!defaultModelProvider || !defaultModelId) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-red-500 text-[0.75rem]", children: "Please select an AI model to continue" })
16330
- ] }),
16331
16416
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon3 text-[0.875rem]", children: "Set required Environmental Variables" }),
16332
16417
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-[1fr_1fr] gap-[1rem] items-start", children: isLoadingEnvVars ? /* @__PURE__ */ jsxRuntime.jsxs(
16333
16418
  "div",
@@ -16367,13 +16452,31 @@ function TemplateForm({
16367
16452
  className: "w-full"
16368
16453
  }
16369
16454
  )
16370
- ] }, key)) })
16455
+ ] }, key)) }),
16456
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border1 pt-[3rem] mt-[0.875rem] relative", children: [
16457
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute w-[2rem] h-[2rem] rounded-full bg-surface2 top-0 left-[50%] translate-x-[-50%] translate-y-[-1rem] text-[0.75rem] text-icon3 flex items-center justify-center", children: "And" }),
16458
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon4 text-[1rem]", children: "Set AI Model for Template Installation" }),
16459
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-icon3 text-[0.875rem] mt-[.5rem] mb-[2rem]", children: "This model will be used by the workflow to process and install the template" }),
16460
+ /* @__PURE__ */ jsxRuntime.jsx(
16461
+ AgentMetadataModelSwitcher,
16462
+ {
16463
+ defaultProvider: defaultModelProvider || "",
16464
+ defaultModel: defaultModelId || "",
16465
+ updateModel: onModelUpdate || (() => Promise.resolve({ message: "Updated" })),
16466
+ closeEditor: () => {
16467
+ },
16468
+ modelProviders: ["openai", "anthropic", "google", "xai", "groq"],
16469
+ autoSave: true,
16470
+ selectProviderPlaceholder: "Provider"
16471
+ }
16472
+ )
16473
+ ] })
16371
16474
  ] }),
16372
16475
  selectedProvider && !isLoadingEnvVars && /* @__PURE__ */ jsxRuntime.jsxs(
16373
- "button",
16476
+ Button,
16374
16477
  {
16375
16478
  className: cn(
16376
- "flex items-center gap-[0.5rem] justify-center text-[0.875rem] w-full bg-surface5 min-h-[2.5rem] rounded-lg text-icon5 hover:bg-surface6 transition-colors",
16479
+ "flex items-center gap-[0.5rem] mt-[1rem] justify-center text-[0.875rem] w-full bg-surface5 min-h-[2.5rem] rounded-lg text-icon5 hover:bg-surface6 transition-colors",
16377
16480
  "[&>svg]:w-[1.1em] [&_svg]:h-[1.1em] [&_svg]:text-icon5"
16378
16481
  ),
16379
16482
  onClick: handleInstallTemplate,
@@ -16612,7 +16715,7 @@ function TemplateFailure({ errorMsg, validationErrors }) {
16612
16715
  };
16613
16716
  };
16614
16717
  const { icon, title } = getIconAndTitle();
16615
- return /* @__PURE__ */ jsxRuntime.jsxs(Container, { className: "space-y-4 text-icon3 mb-[2rem] content-center max-w-2xl mx-auto", children: [
16718
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { className: "space-y-4 text-icon3 mb-[2rem] content-center", children: [
16616
16719
  /* @__PURE__ */ jsxRuntime.jsxs(
16617
16720
  "div",
16618
16721
  {
@@ -17710,10 +17813,14 @@ function TraceTimeline({
17710
17813
  ) : /* @__PURE__ */ jsxRuntime.jsx(
17711
17814
  "div",
17712
17815
  {
17713
- className: cn("grid items-start content-start gap-y-[2px]", "xl:gap-x-[1rem] xl:py-[1rem]", {
17714
- "xl:grid-cols-[3fr_auto]": !overallEndTime,
17715
- "xl:grid-cols-[3fr_2fr]": overallEndTime
17716
- }),
17816
+ className: cn(
17817
+ "grid items-start content-start gap-y-[2px] bg-surface2 rounded-lg overflow-hidden pl-[1.5rem] py-[1.5rem]",
17818
+ "xl:gap-x-[1rem] xl:py-[1rem]",
17819
+ {
17820
+ "xl:grid-cols-[3fr_auto]": !overallEndTime,
17821
+ "xl:grid-cols-[3fr_2fr]": overallEndTime
17822
+ }
17823
+ ),
17717
17824
  children: hierarchicalSpans?.map((span) => /* @__PURE__ */ jsxRuntime.jsx(
17718
17825
  TraceTimelineSpan,
17719
17826
  {
@@ -17987,7 +18094,24 @@ function getSpanInfo({ span, withTraceId = true, withSpanId = true }) {
17987
18094
  return baseInfo;
17988
18095
  }
17989
18096
 
17990
- function SpanDetails({ span }) {
18097
+ const ScoreTable = ({ scores, onItemClick }) => {
18098
+ return /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
18099
+ /* @__PURE__ */ jsxRuntime.jsxs(Thead, { children: [
18100
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { children: "Type" }),
18101
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { children: "Scorer" }),
18102
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { children: "Score" }),
18103
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { children: "Created At" })
18104
+ ] }),
18105
+ /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: scores.map((score) => /* @__PURE__ */ jsxRuntime.jsxs(Row, { onClick: () => onItemClick(score.scorerName), children: [
18106
+ /* @__PURE__ */ jsxRuntime.jsx(TxtCell, { children: /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { children: score.type }) }),
18107
+ /* @__PURE__ */ jsxRuntime.jsx(TxtCell, { children: score.scorerName }),
18108
+ /* @__PURE__ */ jsxRuntime.jsx(TxtCell, { children: score.score }),
18109
+ /* @__PURE__ */ jsxRuntime.jsx(DateTimeCell, { dateTime: new Date(score.createdAt) })
18110
+ ] }, score.scoreId)) })
18111
+ ] });
18112
+ };
18113
+
18114
+ function SpanDetails({ span, onScorerTriggered }) {
17991
18115
  if (!span) {
17992
18116
  return null;
17993
18117
  }
@@ -17995,18 +18119,226 @@ function SpanDetails({ span }) {
17995
18119
  /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Input", codeStr: JSON.stringify(span.input || null, null, 2) }),
17996
18120
  /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Output", codeStr: JSON.stringify(span.output || null, null, 2) }),
17997
18121
  /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Metadata", codeStr: JSON.stringify(span.metadata || null, null, 2) }),
17998
- /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Attributes", codeStr: JSON.stringify(span.attributes || null, null, 2) })
18122
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Attributes", codeStr: JSON.stringify(span.attributes || null, null, 2) }),
18123
+ span?.links?.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-[2.5rem] pr-[2.5rem]", children: [
18124
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { as: "h2", className: "pb-[1rem]", children: [
18125
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GaugeIcon, {}),
18126
+ " Scores"
18127
+ ] }),
18128
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface2 rounded-lg overflow-hidden border-sm border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(
18129
+ ScoreTable,
18130
+ {
18131
+ scores: span?.links,
18132
+ onItemClick: (scorerName) => onScorerTriggered(scorerName, span.traceId, span.spanId)
18133
+ }
18134
+ ) })
18135
+ ] })
17999
18136
  ] });
18000
18137
  }
18001
18138
 
18139
+ const DropdownMenu = DropdownMenuPrimitive__namespace.Root;
18140
+ const DropdownMenuGroup = DropdownMenuPrimitive__namespace.Group;
18141
+ const DropdownMenuPortal = DropdownMenuPrimitive__namespace.Portal;
18142
+ const DropdownMenuSub = DropdownMenuPrimitive__namespace.Sub;
18143
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive__namespace.RadioGroup;
18144
+ const DropdownMenuTrigger = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Trigger, { ref, className: cn("cursor-pointer focus-visible:rounded", className), ...props, children }));
18145
+ DropdownMenuTrigger.displayName = DropdownMenuPrimitive__namespace.Trigger.displayName;
18146
+ const DropdownMenuSubTrigger = React__namespace.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
18147
+ DropdownMenuPrimitive__namespace.SubTrigger,
18148
+ {
18149
+ ref,
18150
+ className: cn(
18151
+ "focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm",
18152
+ inset && "pl-8",
18153
+ className
18154
+ ),
18155
+ ...props,
18156
+ children: [
18157
+ children,
18158
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "ml-auto -rotate-90" })
18159
+ ]
18160
+ }
18161
+ ));
18162
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive__namespace.SubTrigger.displayName;
18163
+ const DropdownMenuSubContent = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
18164
+ DropdownMenuPrimitive__namespace.SubContent,
18165
+ {
18166
+ ref,
18167
+ className: cn(
18168
+ "popover-background data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 z-50 min-w-[8rem] overflow-auto overflow-x-hidden rounded-none p-1",
18169
+ className
18170
+ ),
18171
+ ...props
18172
+ }
18173
+ ));
18174
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive__namespace.SubContent.displayName;
18175
+ const DropdownMenuContent = React__namespace.forwardRef(({ className, container, sideOffset = 4, ...props }, ref) => {
18176
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.Portal, { container, children: /* @__PURE__ */ jsxRuntime.jsx(
18177
+ DropdownMenuPrimitive__namespace.Content,
18178
+ {
18179
+ ref,
18180
+ sideOffset,
18181
+ className: clsx(
18182
+ "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 bg-surface2 text-icon3 border-sm border-border1 z-50 min-w-[8rem] overflow-auto rounded-md p-1 shadow-md",
18183
+ className
18184
+ ),
18185
+ ...props
18186
+ }
18187
+ ) });
18188
+ });
18189
+ DropdownMenuContent.displayName = DropdownMenuPrimitive__namespace.Content.displayName;
18190
+ const DropdownMenuItem = React__namespace.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
18191
+ DropdownMenuPrimitive__namespace.Item,
18192
+ {
18193
+ ref,
18194
+ className: cn(
18195
+ "focus:text-accent-foreground relative flex cursor-default cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 font-sans text-[0.8125rem] transition-colors focus:bg-[#66686A]/20 data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>span]:truncate",
18196
+ inset && "pl-8",
18197
+ className
18198
+ ),
18199
+ ...props
18200
+ }
18201
+ ));
18202
+ DropdownMenuItem.displayName = DropdownMenuPrimitive__namespace.Item.displayName;
18203
+ const DropdownMenuCheckboxItem = React__namespace.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
18204
+ DropdownMenuPrimitive__namespace.CheckboxItem,
18205
+ {
18206
+ ref,
18207
+ className: cn(
18208
+ "focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default cursor-pointer select-none items-center gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
18209
+ className
18210
+ ),
18211
+ checked,
18212
+ ...props,
18213
+ children: [
18214
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-sm border-border1 flex h-4 w-4 items-center justify-center rounded-sm", children: checked && /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {}) }) }),
18215
+ children
18216
+ ]
18217
+ }
18218
+ ));
18219
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive__namespace.CheckboxItem.displayName;
18220
+ const DropdownMenuRadioItem = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
18221
+ DropdownMenuPrimitive__namespace.RadioItem,
18222
+ {
18223
+ ref,
18224
+ className: cn(
18225
+ "focus:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm transition-colors focus:bg-[#66686A]/20 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
18226
+ className
18227
+ ),
18228
+ ...props,
18229
+ children: [
18230
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenuPrimitive__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Circle, { className: "h-2 w-2 fill-current" }) }) }),
18231
+ children
18232
+ ]
18233
+ }
18234
+ ));
18235
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive__namespace.RadioItem.displayName;
18236
+ const DropdownMenuLabel = React__namespace.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
18237
+ DropdownMenuPrimitive__namespace.Label,
18238
+ {
18239
+ ref,
18240
+ className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
18241
+ ...props
18242
+ }
18243
+ ));
18244
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive__namespace.Label.displayName;
18245
+ const DropdownMenuSeparator = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
18246
+ DropdownMenuPrimitive__namespace.Separator,
18247
+ {
18248
+ ref,
18249
+ className: cn("popover-dividers-bg -mx-1 my-1 h-px", className),
18250
+ ...props
18251
+ }
18252
+ ));
18253
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive__namespace.Separator.displayName;
18254
+ const DropdownMenuShortcut = ({ className, ...props }) => {
18255
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("ml-auto text-xs tracking-widest opacity-60", className), ...props });
18256
+ };
18257
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
18258
+ function Dropdown({
18259
+ open,
18260
+ onOpenChange,
18261
+ children,
18262
+ modal
18263
+ }) {
18264
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu, { modal, open, onOpenChange, children });
18265
+ }
18266
+ Dropdown.Trigger = DropdownMenuTrigger;
18267
+ Dropdown.Content = DropdownMenuContent;
18268
+ Dropdown.Group = DropdownMenuGroup;
18269
+ Dropdown.Portal = DropdownMenuPortal;
18270
+ Dropdown.Item = DropdownMenuItem;
18271
+ Dropdown.CheckboxItem = DropdownMenuCheckboxItem;
18272
+ Dropdown.RadioItem = DropdownMenuRadioItem;
18273
+ Dropdown.Label = DropdownMenuLabel;
18274
+ Dropdown.Separator = DropdownMenuSeparator;
18275
+ Dropdown.Shortcut = DropdownMenuShortcut;
18276
+ Dropdown.Sub = DropdownMenuSub;
18277
+ Dropdown.SubContent = DropdownMenuSubContent;
18278
+ Dropdown.SubTrigger = DropdownMenuSubTrigger;
18279
+ Dropdown.RadioGroup = DropdownMenuRadioGroup;
18280
+
18281
+ const useTriggerScorer = (onScorerTriggered) => {
18282
+ const client = useMastraClient();
18283
+ return reactQuery.useMutation({
18284
+ mutationFn: async ({ scorerName, traceId, spanId }) => {
18285
+ const response = await client.score({
18286
+ scorerName,
18287
+ targets: [{ traceId, spanId }]
18288
+ });
18289
+ return response;
18290
+ },
18291
+ onSuccess: (_, variables) => {
18292
+ sonner.toast.success("Scorer triggered successfully");
18293
+ onScorerTriggered(variables.scorerName, variables.traceId, variables.spanId);
18294
+ },
18295
+ onError: () => {
18296
+ sonner.toast.error("Error triggering scorer");
18297
+ }
18298
+ });
18299
+ };
18300
+
18301
+ const ScorersDropdown = ({ trace, spanId, onScorerTriggered, entityType }) => {
18302
+ const { data: scorers = {}, isLoading } = useScorers();
18303
+ const { mutate: triggerScorer, isPending } = useTriggerScorer(onScorerTriggered);
18304
+ let scorerList = Object.entries(scorers).map(([key, scorer]) => ({
18305
+ id: key,
18306
+ name: scorer.scorer.config.name,
18307
+ description: scorer.scorer.config.description,
18308
+ isRegistered: scorer.isRegistered,
18309
+ type: scorer.scorer.config.type
18310
+ })).filter((scorer) => scorer.isRegistered);
18311
+ if (entityType !== "Agent" || spanId) {
18312
+ scorerList = scorerList.filter((scorer) => scorer.type !== "agent");
18313
+ }
18314
+ const isWaiting = isPending || isLoading;
18315
+ return /* @__PURE__ */ jsxRuntime.jsxs(Dropdown, { children: [
18316
+ /* @__PURE__ */ jsxRuntime.jsx(Dropdown.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button$1, { variant: "light", disabled: isWaiting, children: [
18317
+ isWaiting ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) : /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GaugeIcon, {}) }),
18318
+ "Run scorer",
18319
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) })
18320
+ ] }) }),
18321
+ /* @__PURE__ */ jsxRuntime.jsx(Dropdown.Content, { children: scorerList.map((scorer) => /* @__PURE__ */ jsxRuntime.jsx(
18322
+ Dropdown.Item,
18323
+ {
18324
+ onClick: () => triggerScorer({ scorerName: scorer.name, traceId: trace.traceId, spanId }),
18325
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: scorer.name })
18326
+ },
18327
+ scorer.id
18328
+ )) })
18329
+ ] });
18330
+ };
18331
+
18002
18332
  function SpanDialog({
18333
+ trace,
18003
18334
  span,
18004
18335
  isOpen,
18005
18336
  onClose,
18006
18337
  onNext,
18007
18338
  onPrevious,
18008
18339
  onViewToggle,
18009
- spanInfo = []
18340
+ spanInfo = [],
18341
+ onScorerTriggered
18010
18342
  }) {
18011
18343
  const { Link } = useLinkComponent();
18012
18344
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -18035,21 +18367,24 @@ function SpanDialog({
18035
18367
  /* @__PURE__ */ jsxRuntime.jsx("button", { className: "flex items-center gap-1", onClick: onViewToggle, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelTopIcon, {}) })
18036
18368
  ] }),
18037
18369
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-[1.5rem] px-[2.5rem] overflow-y-auto grid gap-[1.5rem] content-start", children: [
18038
- /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
18039
- /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { children: [
18040
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
18041
- " ",
18042
- span?.name
18370
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
18371
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
18372
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { children: [
18373
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
18374
+ " ",
18375
+ span?.name
18376
+ ] }),
18377
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
18378
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HashIcon, {}),
18379
+ " ",
18380
+ span?.spanId
18381
+ ] })
18043
18382
  ] }),
18044
- /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
18045
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HashIcon, {}),
18046
- " ",
18047
- span?.spanId
18048
- ] })
18383
+ span?.traceId && span?.spanId && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ScorersDropdown, { trace, spanId: span?.spanId, onScorerTriggered }) })
18049
18384
  ] }),
18050
18385
  span?.attributes?.usage && /* @__PURE__ */ jsxRuntime.jsx(TraceSpanUsage, { spanUsage: span.attributes.usage, className: "mt-[1.5rem]" }),
18051
18386
  /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: spanInfo, LinkComponent: Link, className: "mt-[1.5rem]" }),
18052
- /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span })
18387
+ /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span, onScorerTriggered })
18053
18388
  ] })
18054
18389
  ]
18055
18390
  }
@@ -18064,11 +18399,15 @@ function TraceDialog({
18064
18399
  onClose,
18065
18400
  onNext,
18066
18401
  onPrevious,
18067
- isLoadingSpans
18402
+ isLoadingSpans,
18403
+ computeAgentsLink,
18404
+ computeWorkflowsLink,
18405
+ onScorerTriggered,
18406
+ initialSpanId
18068
18407
  }) {
18069
18408
  const { Link } = useLinkComponent();
18070
- const [dialogIsOpen, setDialogIsOpen] = React.useState(false);
18071
- const [selectedSpanId, setSelectedSpanId] = React.useState(void 0);
18409
+ const [dialogIsOpen, setDialogIsOpen] = React.useState(Boolean(initialSpanId));
18410
+ const [selectedSpanId, setSelectedSpanId] = React.useState(initialSpanId);
18072
18411
  const [combinedView, setCombinedView] = React.useState(false);
18073
18412
  const selectedSpan = traceSpans.find((span) => span.spanId === selectedSpanId);
18074
18413
  const traceInfo = useTraceInfo(traceDetails);
@@ -18116,6 +18455,12 @@ function TraceDialog({
18116
18455
  return currentIndex > 0;
18117
18456
  };
18118
18457
  const selectedSpanInfo = getSpanInfo({ span: selectedSpan, withTraceId: !combinedView, withSpanId: combinedView });
18458
+ let entityType;
18459
+ if (traceDetails?.attributes?.agentId) {
18460
+ entityType = "Agent";
18461
+ } else if (traceDetails?.attributes?.workflowId) {
18462
+ entityType = "Workflow";
18463
+ }
18119
18464
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18120
18465
  /* @__PURE__ */ jsxRuntime.jsxs(
18121
18466
  SideDialog,
@@ -18139,7 +18484,7 @@ function TraceDialog({
18139
18484
  "grid-rows-[auto_1fr_1fr]": selectedSpan && combinedView
18140
18485
  }),
18141
18486
  children: [
18142
- /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
18487
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeader, { className: "pr-[2.5rem]", children: [
18143
18488
  /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { children: [
18144
18489
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
18145
18490
  " ",
@@ -18152,6 +18497,15 @@ function TraceDialog({
18152
18497
  ] })
18153
18498
  ] }),
18154
18499
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("overflow-y-auto pb-[2.5rem]"), children: [
18500
+ traceDetails && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
18501
+ ScorersDropdown,
18502
+ {
18503
+ trace: traceDetails,
18504
+ spanId: selectedSpanId,
18505
+ onScorerTriggered,
18506
+ entityType
18507
+ }
18508
+ ) }),
18155
18509
  traceDetails?.metadata?.usage && /* @__PURE__ */ jsxRuntime.jsx(
18156
18510
  TraceSpanUsage,
18157
18511
  {
@@ -18171,7 +18525,20 @@ function TraceDialog({
18171
18525
  isLoading: isLoadingSpans,
18172
18526
  className: "pr-[2.5rem] pt-[2.5rem]"
18173
18527
  }
18174
- )
18528
+ ),
18529
+ traceDetails?.links?.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-[2.5rem] pr-[2.5rem]", children: [
18530
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { as: "h2", className: "pb-[1rem]", children: [
18531
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GaugeIcon, {}),
18532
+ " Scores"
18533
+ ] }),
18534
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface2 rounded-lg overflow-hidden border-sm border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(
18535
+ ScoreTable,
18536
+ {
18537
+ scores: traceDetails?.links,
18538
+ onItemClick: (scorerName) => onScorerTriggered(scorerName, traceDetails.traceId, selectedSpanId)
18539
+ }
18540
+ ) })
18541
+ ] })
18175
18542
  ] }),
18176
18543
  selectedSpan && combinedView && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto grid grid-rows-[auto_1fr] relative", children: [
18177
18544
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 right-[2.5rem] h-[.5rem] bg-surface1 rounded-full top-0" }),
@@ -18202,11 +18569,11 @@ function TraceDialog({
18202
18569
  ] }),
18203
18570
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[20rem_1fr] gap-[1rem] overflow-y-auto", children: [
18204
18571
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto grid content-start p-[1.5rem] pl-0 gap-[2rem]", children: [
18205
- /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { as: "h2", children: [
18572
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { as: "h2", children: [
18206
18573
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
18207
18574
  " ",
18208
18575
  selectedSpan?.name
18209
- ] }),
18576
+ ] }) }),
18210
18577
  selectedSpan?.attributes?.usage && /* @__PURE__ */ jsxRuntime.jsx(
18211
18578
  TraceSpanUsage,
18212
18579
  {
@@ -18216,7 +18583,7 @@ function TraceDialog({
18216
18583
  ),
18217
18584
  /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: selectedSpanInfo, LinkComponent: Link })
18218
18585
  ] }),
18219
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto pr-[2.5rem] pt-[2rem]", children: /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span: selectedSpan }) })
18586
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto pr-[2.5rem] pt-[2rem]", children: /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span: selectedSpan, onScorerTriggered }) })
18220
18587
  ] })
18221
18588
  ] })
18222
18589
  ]
@@ -18225,16 +18592,21 @@ function TraceDialog({
18225
18592
  ]
18226
18593
  }
18227
18594
  ),
18228
- /* @__PURE__ */ jsxRuntime.jsx(
18595
+ traceDetails && /* @__PURE__ */ jsxRuntime.jsx(
18229
18596
  SpanDialog,
18230
18597
  {
18598
+ trace: traceDetails,
18231
18599
  span: selectedSpan,
18232
18600
  isOpen: Boolean(dialogIsOpen && selectedSpanId && !combinedView),
18233
- onClose: () => setDialogIsOpen(false),
18601
+ onClose: () => {
18602
+ setDialogIsOpen(false);
18603
+ setSelectedSpanId(void 0);
18604
+ },
18234
18605
  onNext: thereIsNextSpan() ? toNextSpan : void 0,
18235
18606
  onPrevious: thereIsPreviousSpan() ? toPreviousSpan : void 0,
18236
18607
  onViewToggle: () => setCombinedView(!combinedView),
18237
- spanInfo: selectedSpanInfo
18608
+ spanInfo: selectedSpanInfo,
18609
+ onScorerTriggered
18238
18610
  }
18239
18611
  )
18240
18612
  ] });