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

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.es.js CHANGED
@@ -22,7 +22,7 @@ import * as DialogPrimitive from '@radix-ui/react-dialog';
22
22
  import { useDebouncedCallback } from 'use-debounce';
23
23
  import { create } from 'zustand';
24
24
  import { persist } from 'zustand/middleware';
25
- import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query';
25
+ import { useQuery, useMutation, QueryClient, QueryClientProvider } from '@tanstack/react-query';
26
26
  import './index.css';export * from '@tanstack/react-query';
27
27
  import { MarkerType, Handle, Position, useNodesState, useEdgesState, ReactFlow, Controls, Background, BackgroundVariant, ReactFlowProvider, useViewport, useReactFlow, Panel } from '@xyflow/react';
28
28
  import '@xyflow/react/dist/style.css';
@@ -63,6 +63,7 @@ import * as HoverCard from '@radix-ui/react-hover-card';
63
63
  import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
64
64
  import { RuntimeContext as RuntimeContext$2 } from '@mastra/core/runtime-context';
65
65
  import { format as format$1 } from 'date-fns/format';
66
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
66
67
 
67
68
  const createMastraClient = (baseUrl, mastraClientHeaders = {}) => {
68
69
  return new MastraClient({
@@ -4518,16 +4519,16 @@ const usePlaygroundStore = create()(
4518
4519
  )
4519
4520
  );
4520
4521
 
4521
- const useWorkflow = (workflowId, enabled = true) => {
4522
+ const useWorkflow = (workflowId) => {
4522
4523
  const client = useMastraClient();
4523
4524
  const { runtimeContext } = usePlaygroundStore();
4524
4525
  return useQuery({
4525
4526
  queryKey: ["workflow", workflowId],
4526
- queryFn: () => client.getWorkflow(workflowId).details(runtimeContext),
4527
+ queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
4528
+ enabled: Boolean(workflowId),
4527
4529
  retry: false,
4528
4530
  refetchOnWindowFocus: false,
4529
- throwOnError: false,
4530
- enabled
4531
+ throwOnError: false
4531
4532
  });
4532
4533
  };
4533
4534
  const useLegacyWorkflow = (workflowId) => {
@@ -8258,7 +8259,7 @@ const Row = forwardRef(
8258
8259
  "tr",
8259
8260
  {
8260
8261
  className: clsx(
8261
- "border-b-sm border-border1 hover:bg-surface3 focus:bg-surface3 -outline-offset-2",
8262
+ "border-b-sm border-border1 hover:bg-surface3 focus:bg-surface3 -outline-offset-2 last:border-b-0",
8262
8263
  selected && "bg-surface4",
8263
8264
  onClick && "cursor-pointer",
8264
8265
  className
@@ -12913,13 +12914,13 @@ function KeyValueList({ data, LinkComponent, className, labelsAreHidden, isLoadi
12913
12914
  style: { width: `${Math.floor(Math.random() * (90 - 30 + 1)) + 50}%` },
12914
12915
  children: " "
12915
12916
  }
12916
- ) : /* @__PURE__ */ jsx(Fragment, { children: isValueItemArray ? value?.map((item) => {
12917
+ ) : isValueItemArray ? value?.map((item) => {
12917
12918
  return item.path ? /* @__PURE__ */ jsx(RelationWrapper, { description: item.description, children: /* @__PURE__ */ jsxs(Link, { href: item.path, children: [
12918
12919
  item?.name,
12919
12920
  " ",
12920
12921
  /* @__PURE__ */ jsx(ChevronRightIcon, {})
12921
12922
  ] }) }, item.id) : /* @__PURE__ */ jsx("span", { children: item?.name }, item.id);
12922
- }) : /* @__PURE__ */ jsx(Fragment, { children: value ? value : /* @__PURE__ */ jsx("span", { className: "text-icon3 text-[0.75rem]", children: "n/a" }) }) })
12923
+ }) : /* @__PURE__ */ jsx(Fragment, { children: value ? value : /* @__PURE__ */ jsx("span", { className: "text-icon3 text-[0.75rem]", children: "n/a" }) })
12923
12924
  }
12924
12925
  )
12925
12926
  ] }, label + index);
@@ -13615,7 +13616,7 @@ const DateTimePicker = ({
13615
13616
  /* @__PURE__ */ jsx(
13616
13617
  PopoverContent,
13617
13618
  {
13618
- className: "backdrop-blur-4xl w-auto p-0 bg-surface4 max-w-[16.5rem]",
13619
+ className: "backdrop-blur-4xl w-auto !p-0 bg-surface4 max-w-[16.5rem]",
13619
13620
  align: "start",
13620
13621
  "data-testid": "datepicker-calendar",
13621
13622
  children: /* @__PURE__ */ jsx(
@@ -13741,7 +13742,7 @@ const DateTimePickerContent = ({
13741
13742
  "div",
13742
13743
  {
13743
13744
  "aria-label": "Choose date",
13744
- className: cn("relative mt-2 flex flex-col ", className),
13745
+ className: cn("relative flex flex-col", className),
13745
13746
  onKeyDown: (e) => {
13746
13747
  e.stopPropagation();
13747
13748
  if (e.key === "Escape") {
@@ -13838,7 +13839,16 @@ function getShortId(id) {
13838
13839
  return id.slice(0, 8);
13839
13840
  }
13840
13841
 
13841
- function ScoreDialog({ scorer, score, isOpen, onClose, onNext, onPrevious }) {
13842
+ function ScoreDialog({
13843
+ scorer,
13844
+ score,
13845
+ isOpen,
13846
+ onClose,
13847
+ onNext,
13848
+ onPrevious,
13849
+ computeTraceLink
13850
+ }) {
13851
+ const { Link } = useLinkComponent();
13842
13852
  return /* @__PURE__ */ jsxs(
13843
13853
  SideDialog,
13844
13854
  {
@@ -13861,10 +13871,30 @@ function ScoreDialog({ scorer, score, isOpen, onClose, onNext, onPrevious }) {
13861
13871
  ] })
13862
13872
  ] }) }),
13863
13873
  /* @__PURE__ */ jsx("div", { className: "p-[1.5rem] px-[2.5rem] overflow-y-auto grid gap-[1.5rem] content-start", children: /* @__PURE__ */ jsxs("div", { className: "grid gap-[1.5rem] mb-[2rem]", children: [
13874
+ score?.traceId && /* @__PURE__ */ jsx(
13875
+ KeyValueList,
13876
+ {
13877
+ data: [
13878
+ {
13879
+ label: "Trace ID",
13880
+ value: /* @__PURE__ */ jsx(Link, { href: computeTraceLink(score?.traceId), children: score?.traceId }),
13881
+ key: "traceId"
13882
+ },
13883
+ ...score?.spanId ? [
13884
+ {
13885
+ label: "Span ID",
13886
+ value: /* @__PURE__ */ jsx(Link, { href: computeTraceLink(score?.traceId, score?.spanId), children: score?.spanId }),
13887
+ key: "spanId"
13888
+ }
13889
+ ] : []
13890
+ ],
13891
+ LinkComponent: Link
13892
+ }
13893
+ ),
13864
13894
  /* @__PURE__ */ jsx(
13865
13895
  SideDialogCodeSection,
13866
13896
  {
13867
- title: `Score: ${score?.score ? score?.score : "n/a"}`,
13897
+ title: `Score: ${Number.isNaN(score?.score) ? "n/a" : score?.score}`,
13868
13898
  codeStr: score?.reason,
13869
13899
  simplified: true
13870
13900
  }
@@ -13956,29 +13986,11 @@ const useScoresByEntityId = (entityId, entityType, page = 0) => {
13956
13986
  };
13957
13987
  const useScoresByScorerId = ({ scorerId, page = 0, entityId, entityType }) => {
13958
13988
  const client = useMastraClient();
13959
- const [scores, setScores] = useState(null);
13960
- const [isLoading, setIsLoading] = useState(true);
13961
- useEffect(() => {
13962
- const fetchScores = async () => {
13963
- setIsLoading(true);
13964
- try {
13965
- const res = await client.getScoresByScorerId({
13966
- scorerId,
13967
- page: page || 0,
13968
- entityId: entityId || void 0,
13969
- entityType: entityType || void 0,
13970
- perPage: 10
13971
- });
13972
- setScores(res);
13973
- setIsLoading(false);
13974
- } catch (error) {
13975
- setScores(null);
13976
- setIsLoading(false);
13977
- }
13978
- };
13979
- fetchScores();
13980
- }, [scorerId, page, entityId, entityType]);
13981
- return { scores, isLoading };
13989
+ return useQuery({
13990
+ queryKey: ["scores", scorerId, page, entityId, entityType],
13991
+ queryFn: () => client.getScoresByScorerId({ scorerId, page, entityId, entityType, perPage: 10 }),
13992
+ refetchInterval: 5e3
13993
+ });
13982
13994
  };
13983
13995
  const useScorer = (scorerId) => {
13984
13996
  const client = useMastraClient();
@@ -14004,25 +14016,12 @@ const useScorer = (scorerId) => {
14004
14016
  };
14005
14017
  const useScorers = () => {
14006
14018
  const client = useMastraClient();
14007
- const [scorers, setScorers] = useState({});
14008
- const [isLoading, setIsLoading] = useState(true);
14009
- useEffect(() => {
14010
- const fetchScorers = async () => {
14011
- setIsLoading(true);
14012
- try {
14013
- const res = await client.getScorers();
14014
- setScorers(res);
14015
- } catch (error) {
14016
- setScorers({});
14017
- console.error("Error fetching agents", error);
14018
- toast.error("Error fetching agents");
14019
- } finally {
14020
- setIsLoading(false);
14021
- }
14022
- };
14023
- fetchScorers();
14024
- }, []);
14025
- return { scorers, isLoading };
14019
+ return useQuery({
14020
+ queryKey: ["scorers"],
14021
+ queryFn: () => client.getScorers(),
14022
+ staleTime: 0,
14023
+ gcTime: 0
14024
+ });
14026
14025
  };
14027
14026
 
14028
14027
  const NameCell = ({ row }) => {
@@ -14269,7 +14268,9 @@ const AgentMetadataModelSwitcher = ({
14269
14268
  defaultModel,
14270
14269
  updateModel,
14271
14270
  closeEditor,
14272
- modelProviders
14271
+ modelProviders,
14272
+ autoSave = false,
14273
+ selectProviderPlaceholder = "Select provider"
14273
14274
  }) => {
14274
14275
  const [selectedModel, setSelectedModel] = useState(defaultModel);
14275
14276
  const [showSuggestions, setShowSuggestions] = useState(false);
@@ -14281,10 +14282,19 @@ const AgentMetadataModelSwitcher = ({
14281
14282
  return "";
14282
14283
  });
14283
14284
  const [loading, setLoading] = useState(false);
14285
+ const [infoMsg, setInfoMsg] = useState("");
14284
14286
  const modelsList = Object.entries(Models).filter(([provider]) => modelProviders.includes(provider));
14285
14287
  const allModels = modelsList.flatMap(([_, { models }]) => models);
14286
14288
  const providersList = modelsList.map(([provider, { icon }]) => ({ provider, icon }));
14287
14289
  const model = allModels.find((model2) => model2.model === selectedModel);
14290
+ useEffect(() => {
14291
+ const isValidModel = allModels.some((model2) => model2.model === selectedModel);
14292
+ if (selectedModel && !isValidModel) {
14293
+ setInfoMsg("Model not in suggestions—make sure the name is correct.");
14294
+ } else {
14295
+ setInfoMsg("");
14296
+ }
14297
+ }, [selectedModel, allModels]);
14288
14298
  const handleSave = async () => {
14289
14299
  setLoading(true);
14290
14300
  const providerToUse = model?.provider ?? selectedProvider;
@@ -14292,67 +14302,156 @@ const AgentMetadataModelSwitcher = ({
14292
14302
  setLoading(false);
14293
14303
  closeEditor();
14294
14304
  };
14295
- const filteredModels = allModels.filter((model2) => model2.model.includes(selectedModel));
14296
- return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
14305
+ const filteredModels = allModels.filter((model2) => {
14306
+ if (selectedProvider) {
14307
+ return model2.model.includes(selectedModel) && model2.provider === selectedProvider;
14308
+ }
14309
+ return model2.model.includes(selectedModel);
14310
+ });
14311
+ const handleProviderChange = (provider) => {
14312
+ setSelectedProvider(provider);
14313
+ setSelectedModel("");
14314
+ if (autoSave) {
14315
+ updateModel({
14316
+ provider,
14317
+ modelId: ""
14318
+ });
14319
+ }
14320
+ };
14321
+ const handleModelInputBlur = (e) => {
14322
+ setShowSuggestions(false);
14323
+ const isValidModel = allModels.some((model2) => model2.model === e.target.value);
14324
+ if (!isValidModel) {
14325
+ if (autoSave) {
14326
+ updateModel({
14327
+ provider: selectedProvider,
14328
+ modelId: e.target.value
14329
+ });
14330
+ }
14331
+ }
14332
+ };
14333
+ const handleModelClick = (model2) => {
14334
+ setSelectedModel(model2.model);
14335
+ const isValidModel = allModels.some((m) => m.model === model2.model);
14336
+ if (isValidModel) {
14337
+ setSelectedProvider(model2.provider);
14338
+ }
14339
+ if (autoSave) {
14340
+ updateModel({
14341
+ provider: model2.provider,
14342
+ modelId: model2.model
14343
+ });
14344
+ }
14345
+ setShowSuggestions(false);
14346
+ };
14347
+ const handleModelInputChange = (e) => {
14348
+ setSelectedModel(e.target.value);
14349
+ const isValidModel = allModels.some((m) => m.model === e.target.value);
14350
+ if (isValidModel) {
14351
+ const model2 = allModels.find((m) => m.model === e.target.value);
14352
+ if (model2) {
14353
+ setSelectedProvider(model2.provider);
14354
+ }
14355
+ }
14356
+ };
14357
+ const handleModelReset = () => {
14358
+ setSelectedModel("");
14359
+ setInfoMsg("");
14360
+ if (autoSave) {
14361
+ updateModel({
14362
+ provider: selectedProvider,
14363
+ modelId: ""
14364
+ });
14365
+ }
14366
+ };
14367
+ return /* @__PURE__ */ jsxs("div", { children: [
14297
14368
  /* @__PURE__ */ jsxs(
14298
- Select$1,
14369
+ "div",
14299
14370
  {
14300
- value: model?.provider ?? selectedProvider,
14301
- onValueChange: setSelectedProvider,
14302
- disabled: !!model?.provider,
14371
+ className: cn("grid items-center gap-2", {
14372
+ "xl:grid-cols-[auto_1fr_auto]": !autoSave,
14373
+ "xl:grid-cols-[auto_1fr]": autoSave
14374
+ }),
14303
14375
  children: [
14304
- /* @__PURE__ */ jsx(SelectTrigger, { className: "max-w-[150px]", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select provider" }) }),
14305
- /* @__PURE__ */ jsx(SelectContent, { children: providersList.map((provider) => /* @__PURE__ */ jsx(SelectItem, { value: provider.provider, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
14306
- /* @__PURE__ */ jsx(Icon, { children: providerMapToIcon[provider.icon] }),
14307
- provider.provider
14308
- ] }) }, provider.provider)) })
14376
+ /* @__PURE__ */ jsxs(Select$1, { value: selectedProvider, onValueChange: handleProviderChange, disabled: !!model?.provider, children: [
14377
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: selectProviderPlaceholder }) }),
14378
+ /* @__PURE__ */ jsx(SelectContent, { children: providersList.map((provider) => /* @__PURE__ */ jsx(SelectItem, { value: provider.provider, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
14379
+ /* @__PURE__ */ jsx(Icon, { children: providerMapToIcon[provider.icon] }),
14380
+ provider.provider
14381
+ ] }) }, provider.provider)) })
14382
+ ] }),
14383
+ /* @__PURE__ */ jsxs(Popover, { open: showSuggestions, children: [
14384
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
14385
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
14386
+ Input,
14387
+ {
14388
+ id: "model-input",
14389
+ list: "model-suggestions",
14390
+ className: "flex-1 w-full h-[2.25rem] rounded-md min-w-[12rem]",
14391
+ type: "text",
14392
+ value: selectedModel,
14393
+ onChange: handleModelInputChange,
14394
+ onFocus: () => setShowSuggestions(true),
14395
+ onBlur: handleModelInputBlur,
14396
+ placeholder: "Enter model name or select from suggestions...",
14397
+ autoComplete: "off"
14398
+ }
14399
+ ) }),
14400
+ selectedModel && /* @__PURE__ */ jsx(
14401
+ "button",
14402
+ {
14403
+ 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",
14404
+ onClick: handleModelReset,
14405
+ children: /* @__PURE__ */ jsx(XIcon, {})
14406
+ }
14407
+ )
14408
+ ] }),
14409
+ filteredModels.length > 0 && /* @__PURE__ */ jsx(
14410
+ PopoverContent,
14411
+ {
14412
+ onOpenAutoFocus: (e) => e.preventDefault(),
14413
+ className: "flex flex-col w-[var(--radix-popover-trigger-width)] max-h-[calc(var(--radix-popover-content-available-height)-50px)] overflow-y-auto",
14414
+ children: filteredModels.map((model2) => /* @__PURE__ */ jsx(
14415
+ "button",
14416
+ {
14417
+ className: "flex items-center justify-start gap-2 cursor-pointer hover:bg-surface5 p-2 text-[0.875rem]",
14418
+ onClick: () => handleModelClick(model2),
14419
+ children: model2.model
14420
+ },
14421
+ model2.provider + model2.model
14422
+ ))
14423
+ }
14424
+ )
14425
+ ] }),
14426
+ !autoSave && /* @__PURE__ */ jsx(
14427
+ Button$2,
14428
+ {
14429
+ onClick: handleSave,
14430
+ variant: "secondary",
14431
+ size: "sm",
14432
+ disabled: loading || !selectedModel,
14433
+ className: "w-full",
14434
+ children: loading ? /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Spinner, {}) }) : "Save"
14435
+ }
14436
+ )
14309
14437
  ]
14310
14438
  }
14311
14439
  ),
14312
- /* @__PURE__ */ jsxs(Popover, { open: showSuggestions, children: [
14313
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
14314
- Input,
14315
- {
14316
- id: "model-input",
14317
- list: "model-suggestions",
14318
- className: "flex-1",
14319
- type: "text",
14320
- value: selectedModel,
14321
- onChange: (e) => {
14322
- setSelectedModel(e.target.value);
14323
- setShowSuggestions(true);
14324
- },
14325
- placeholder: "Enter model name or select from suggestions..."
14326
- }
14327
- ) }),
14328
- filteredModels.length > 0 && /* @__PURE__ */ jsx(
14329
- PopoverContent,
14330
- {
14331
- onOpenAutoFocus: (e) => e.preventDefault(),
14332
- 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",
14333
- children: filteredModels.map((model2) => /* @__PURE__ */ jsxs(
14334
- "div",
14335
- {
14336
- className: "flex items-center gap-2 cursor-pointer hover:bg-surface5 p-2",
14337
- onClick: () => {
14338
- setSelectedModel(model2.model);
14339
- setShowSuggestions(false);
14340
- },
14341
- children: [
14342
- /* @__PURE__ */ jsx(Icon, { children: providerMapToIcon[model2.icon] }),
14343
- model2.model
14344
- ]
14345
- },
14346
- model2.provider + model2.model
14347
- ))
14348
- }
14349
- )
14350
- ] }),
14351
- /* @__PURE__ */ jsxs(Tooltip, { children: [
14352
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("button", { onClick: handleSave, className: "text-icon3 hover:text-icon6", children: /* @__PURE__ */ jsx(Icon, { children: loading ? /* @__PURE__ */ jsx(Spinner, {}) : /* @__PURE__ */ jsx(CircleCheck, {}) }) }) }),
14353
- /* @__PURE__ */ jsx(TooltipContent, { children: loading ? "Saving..." : "Save new model" })
14354
- ] })
14355
- ] }) });
14440
+ infoMsg && /* @__PURE__ */ jsxs(
14441
+ "div",
14442
+ {
14443
+ className: cn(
14444
+ "text-[0.75rem] text-icon3 flex gap-[.5rem] mt-[0.5rem] ml-[.5rem]",
14445
+ "[&>svg]:w-[1.1em] [&>svg]:h-[1.1em] [&>svg]:opacity-7 [&>svg]:flex-shrink-0 [&>svg]:mt-[0.1rem]"
14446
+ ),
14447
+ children: [
14448
+ /* @__PURE__ */ jsx(InfoIcon$1, {}),
14449
+ " ",
14450
+ infoMsg
14451
+ ]
14452
+ }
14453
+ )
14454
+ ] });
14356
14455
  };
14357
14456
 
14358
14457
  const AgentMetadataNetworkList = ({ agents }) => {
@@ -14465,11 +14564,11 @@ const AgentMetadataWorkflowList = ({ workflows }) => {
14465
14564
  };
14466
14565
  const AgentMetadataScorerList = ({ entityId, entityType }) => {
14467
14566
  const { Link, paths } = useLinkComponent();
14468
- const { scorers, isLoading } = useScorers();
14567
+ const { data: scorers = {}, isLoading } = useScorers();
14469
14568
  const scorerList = Object.keys(scorers).filter((scorerKey) => {
14470
14569
  const scorer = scorers[scorerKey];
14471
14570
  if (entityType === "AGENT") {
14472
- return scorer.agentIds.includes(entityId);
14571
+ return scorer.agentNames.includes(entityId);
14473
14572
  }
14474
14573
  return scorer.workflowIds.includes(entityId);
14475
14574
  }).map((scorerKey) => ({ ...scorers[scorerKey], id: scorerKey }));
@@ -16258,7 +16357,7 @@ function TemplateForm({
16258
16357
  "h2",
16259
16358
  {
16260
16359
  className: cn(
16261
- "text-icon5 text-[1.125rem] font-semibold flex items-center gap-[0.5rem]",
16360
+ "text-icon4 text-[1.125rem] font-semibold flex items-center gap-[0.5rem]",
16262
16361
  "[&>svg]:w-[1.2em] [&_svg]:h-[1.2em] [&_svg]:opacity-70 "
16263
16362
  ),
16264
16363
  children: [
@@ -16271,29 +16370,13 @@ function TemplateForm({
16271
16370
  SelectField,
16272
16371
  {
16273
16372
  options: providerOptions,
16274
- label: "Provider",
16373
+ label: "Template AI Model Provider",
16275
16374
  onValueChange: onProviderChange,
16276
16375
  value: selectedProvider,
16277
- placeholder: "Select a provider"
16376
+ placeholder: "Select"
16278
16377
  }
16279
16378
  ),
16280
16379
  selectedProvider && Object.entries(variables || {}).length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
16281
- /* @__PURE__ */ jsxs("div", { className: "space-y-[0.5rem]", children: [
16282
- /* @__PURE__ */ jsx("h3", { className: "text-icon3 text-[0.875rem] font-medium", children: "Select AI Model for Template Installation *" }),
16283
- /* @__PURE__ */ jsx("p", { className: "text-icon4 text-[0.75rem]", children: "This model will be used by the workflow to process and install the template" }),
16284
- /* @__PURE__ */ jsx(
16285
- AgentMetadataModelSwitcher,
16286
- {
16287
- defaultProvider: defaultModelProvider || "",
16288
- defaultModel: defaultModelId || "",
16289
- updateModel: onModelUpdate || (() => Promise.resolve({ message: "Updated" })),
16290
- closeEditor: () => {
16291
- },
16292
- modelProviders: ["openai", "anthropic", "google", "xai", "groq"]
16293
- }
16294
- ),
16295
- (!defaultModelProvider || !defaultModelId) && /* @__PURE__ */ jsx("p", { className: "text-red-500 text-[0.75rem]", children: "Please select an AI model to continue" })
16296
- ] }),
16297
16380
  /* @__PURE__ */ jsx("h3", { className: "text-icon3 text-[0.875rem]", children: "Set required Environmental Variables" }),
16298
16381
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-[1fr_1fr] gap-[1rem] items-start", children: isLoadingEnvVars ? /* @__PURE__ */ jsxs(
16299
16382
  "div",
@@ -16333,13 +16416,31 @@ function TemplateForm({
16333
16416
  className: "w-full"
16334
16417
  }
16335
16418
  )
16336
- ] }, key)) })
16419
+ ] }, key)) }),
16420
+ /* @__PURE__ */ jsxs("div", { className: "border-t border-border1 pt-[3rem] mt-[0.875rem] relative", children: [
16421
+ /* @__PURE__ */ 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" }),
16422
+ /* @__PURE__ */ jsx("h3", { className: "text-icon4 text-[1rem]", children: "Set AI Model for Template Installation" }),
16423
+ /* @__PURE__ */ 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" }),
16424
+ /* @__PURE__ */ jsx(
16425
+ AgentMetadataModelSwitcher,
16426
+ {
16427
+ defaultProvider: defaultModelProvider || "",
16428
+ defaultModel: defaultModelId || "",
16429
+ updateModel: onModelUpdate || (() => Promise.resolve({ message: "Updated" })),
16430
+ closeEditor: () => {
16431
+ },
16432
+ modelProviders: ["openai", "anthropic", "google", "xai", "groq"],
16433
+ autoSave: true,
16434
+ selectProviderPlaceholder: "Provider"
16435
+ }
16436
+ )
16437
+ ] })
16337
16438
  ] }),
16338
16439
  selectedProvider && !isLoadingEnvVars && /* @__PURE__ */ jsxs(
16339
- "button",
16440
+ Button,
16340
16441
  {
16341
16442
  className: cn(
16342
- "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",
16443
+ "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",
16343
16444
  "[&>svg]:w-[1.1em] [&_svg]:h-[1.1em] [&_svg]:text-icon5"
16344
16445
  ),
16345
16446
  onClick: handleInstallTemplate,
@@ -16578,7 +16679,7 @@ function TemplateFailure({ errorMsg, validationErrors }) {
16578
16679
  };
16579
16680
  };
16580
16681
  const { icon, title } = getIconAndTitle();
16581
- return /* @__PURE__ */ jsxs(Container, { className: "space-y-4 text-icon3 mb-[2rem] content-center max-w-2xl mx-auto", children: [
16682
+ return /* @__PURE__ */ jsxs(Container, { className: "space-y-4 text-icon3 mb-[2rem] content-center", children: [
16582
16683
  /* @__PURE__ */ jsxs(
16583
16684
  "div",
16584
16685
  {
@@ -17676,10 +17777,14 @@ function TraceTimeline({
17676
17777
  ) : /* @__PURE__ */ jsx(
17677
17778
  "div",
17678
17779
  {
17679
- className: cn("grid items-start content-start gap-y-[2px]", "xl:gap-x-[1rem] xl:py-[1rem]", {
17680
- "xl:grid-cols-[3fr_auto]": !overallEndTime,
17681
- "xl:grid-cols-[3fr_2fr]": overallEndTime
17682
- }),
17780
+ className: cn(
17781
+ "grid items-start content-start gap-y-[2px] bg-surface2 rounded-lg overflow-hidden pl-[1.5rem] py-[1.5rem]",
17782
+ "xl:gap-x-[1rem] xl:py-[1rem]",
17783
+ {
17784
+ "xl:grid-cols-[3fr_auto]": !overallEndTime,
17785
+ "xl:grid-cols-[3fr_2fr]": overallEndTime
17786
+ }
17787
+ ),
17683
17788
  children: hierarchicalSpans?.map((span) => /* @__PURE__ */ jsx(
17684
17789
  TraceTimelineSpan,
17685
17790
  {
@@ -17953,7 +18058,24 @@ function getSpanInfo({ span, withTraceId = true, withSpanId = true }) {
17953
18058
  return baseInfo;
17954
18059
  }
17955
18060
 
17956
- function SpanDetails({ span }) {
18061
+ const ScoreTable = ({ scores, onItemClick }) => {
18062
+ return /* @__PURE__ */ jsxs(Table$1, { children: [
18063
+ /* @__PURE__ */ jsxs(Thead, { children: [
18064
+ /* @__PURE__ */ jsx(Th, { children: "Type" }),
18065
+ /* @__PURE__ */ jsx(Th, { children: "Scorer" }),
18066
+ /* @__PURE__ */ jsx(Th, { children: "Score" }),
18067
+ /* @__PURE__ */ jsx(Th, { children: "Created At" })
18068
+ ] }),
18069
+ /* @__PURE__ */ jsx(Tbody, { children: scores.map((score) => /* @__PURE__ */ jsxs(Row, { onClick: () => onItemClick(score.scorerName), children: [
18070
+ /* @__PURE__ */ jsx(TxtCell, { children: /* @__PURE__ */ jsx(Badge$1, { children: score.type }) }),
18071
+ /* @__PURE__ */ jsx(TxtCell, { children: score.scorerName }),
18072
+ /* @__PURE__ */ jsx(TxtCell, { children: score.score }),
18073
+ /* @__PURE__ */ jsx(DateTimeCell, { dateTime: new Date(score.createdAt) })
18074
+ ] }, score.scoreId)) })
18075
+ ] });
18076
+ };
18077
+
18078
+ function SpanDetails({ span, onScorerTriggered }) {
17957
18079
  if (!span) {
17958
18080
  return null;
17959
18081
  }
@@ -17961,18 +18083,226 @@ function SpanDetails({ span }) {
17961
18083
  /* @__PURE__ */ jsx(SideDialogCodeSection, { title: "Input", codeStr: JSON.stringify(span.input || null, null, 2) }),
17962
18084
  /* @__PURE__ */ jsx(SideDialogCodeSection, { title: "Output", codeStr: JSON.stringify(span.output || null, null, 2) }),
17963
18085
  /* @__PURE__ */ jsx(SideDialogCodeSection, { title: "Metadata", codeStr: JSON.stringify(span.metadata || null, null, 2) }),
17964
- /* @__PURE__ */ jsx(SideDialogCodeSection, { title: "Attributes", codeStr: JSON.stringify(span.attributes || null, null, 2) })
18086
+ /* @__PURE__ */ jsx(SideDialogCodeSection, { title: "Attributes", codeStr: JSON.stringify(span.attributes || null, null, 2) }),
18087
+ span?.links?.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pt-[2.5rem] pr-[2.5rem]", children: [
18088
+ /* @__PURE__ */ jsxs(SideDialogHeading, { as: "h2", className: "pb-[1rem]", children: [
18089
+ /* @__PURE__ */ jsx(GaugeIcon, {}),
18090
+ " Scores"
18091
+ ] }),
18092
+ /* @__PURE__ */ jsx("div", { className: "bg-surface2 rounded-lg overflow-hidden border-sm border-border1", children: /* @__PURE__ */ jsx(
18093
+ ScoreTable,
18094
+ {
18095
+ scores: span?.links,
18096
+ onItemClick: (scorerName) => onScorerTriggered(scorerName, span.traceId, span.spanId)
18097
+ }
18098
+ ) })
18099
+ ] })
17965
18100
  ] });
17966
18101
  }
17967
18102
 
18103
+ const DropdownMenu = DropdownMenuPrimitive.Root;
18104
+ const DropdownMenuGroup = DropdownMenuPrimitive.Group;
18105
+ const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
18106
+ const DropdownMenuSub = DropdownMenuPrimitive.Sub;
18107
+ const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
18108
+ const DropdownMenuTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Trigger, { ref, className: cn("cursor-pointer focus-visible:rounded", className), ...props, children }));
18109
+ DropdownMenuTrigger.displayName = DropdownMenuPrimitive.Trigger.displayName;
18110
+ const DropdownMenuSubTrigger = React.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ jsxs(
18111
+ DropdownMenuPrimitive.SubTrigger,
18112
+ {
18113
+ ref,
18114
+ className: cn(
18115
+ "focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm",
18116
+ inset && "pl-8",
18117
+ className
18118
+ ),
18119
+ ...props,
18120
+ children: [
18121
+ children,
18122
+ /* @__PURE__ */ jsx(ChevronDown, { className: "ml-auto -rotate-90" })
18123
+ ]
18124
+ }
18125
+ ));
18126
+ DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
18127
+ const DropdownMenuSubContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
18128
+ DropdownMenuPrimitive.SubContent,
18129
+ {
18130
+ ref,
18131
+ className: cn(
18132
+ "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",
18133
+ className
18134
+ ),
18135
+ ...props
18136
+ }
18137
+ ));
18138
+ DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
18139
+ const DropdownMenuContent = React.forwardRef(({ className, container, sideOffset = 4, ...props }, ref) => {
18140
+ return /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { container, children: /* @__PURE__ */ jsx(
18141
+ DropdownMenuPrimitive.Content,
18142
+ {
18143
+ ref,
18144
+ sideOffset,
18145
+ className: clsx(
18146
+ "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",
18147
+ className
18148
+ ),
18149
+ ...props
18150
+ }
18151
+ ) });
18152
+ });
18153
+ DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
18154
+ const DropdownMenuItem = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
18155
+ DropdownMenuPrimitive.Item,
18156
+ {
18157
+ ref,
18158
+ className: cn(
18159
+ "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",
18160
+ inset && "pl-8",
18161
+ className
18162
+ ),
18163
+ ...props
18164
+ }
18165
+ ));
18166
+ DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
18167
+ const DropdownMenuCheckboxItem = React.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ jsxs(
18168
+ DropdownMenuPrimitive.CheckboxItem,
18169
+ {
18170
+ ref,
18171
+ className: cn(
18172
+ "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",
18173
+ className
18174
+ ),
18175
+ checked,
18176
+ ...props,
18177
+ children: [
18178
+ /* @__PURE__ */ jsx("div", { className: "border-sm border-border1 flex h-4 w-4 items-center justify-center rounded-sm", children: checked && /* @__PURE__ */ jsx(Icon, { size: "sm", children: /* @__PURE__ */ jsx(Check, {}) }) }),
18179
+ children
18180
+ ]
18181
+ }
18182
+ ));
18183
+ DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
18184
+ const DropdownMenuRadioItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
18185
+ DropdownMenuPrimitive.RadioItem,
18186
+ {
18187
+ ref,
18188
+ className: cn(
18189
+ "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",
18190
+ className
18191
+ ),
18192
+ ...props,
18193
+ children: [
18194
+ /* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Circle, { className: "h-2 w-2 fill-current" }) }) }),
18195
+ children
18196
+ ]
18197
+ }
18198
+ ));
18199
+ DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
18200
+ const DropdownMenuLabel = React.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
18201
+ DropdownMenuPrimitive.Label,
18202
+ {
18203
+ ref,
18204
+ className: cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className),
18205
+ ...props
18206
+ }
18207
+ ));
18208
+ DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
18209
+ const DropdownMenuSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
18210
+ DropdownMenuPrimitive.Separator,
18211
+ {
18212
+ ref,
18213
+ className: cn("popover-dividers-bg -mx-1 my-1 h-px", className),
18214
+ ...props
18215
+ }
18216
+ ));
18217
+ DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
18218
+ const DropdownMenuShortcut = ({ className, ...props }) => {
18219
+ return /* @__PURE__ */ jsx("span", { className: cn("ml-auto text-xs tracking-widest opacity-60", className), ...props });
18220
+ };
18221
+ DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
18222
+ function Dropdown({
18223
+ open,
18224
+ onOpenChange,
18225
+ children,
18226
+ modal
18227
+ }) {
18228
+ return /* @__PURE__ */ jsx(DropdownMenu, { modal, open, onOpenChange, children });
18229
+ }
18230
+ Dropdown.Trigger = DropdownMenuTrigger;
18231
+ Dropdown.Content = DropdownMenuContent;
18232
+ Dropdown.Group = DropdownMenuGroup;
18233
+ Dropdown.Portal = DropdownMenuPortal;
18234
+ Dropdown.Item = DropdownMenuItem;
18235
+ Dropdown.CheckboxItem = DropdownMenuCheckboxItem;
18236
+ Dropdown.RadioItem = DropdownMenuRadioItem;
18237
+ Dropdown.Label = DropdownMenuLabel;
18238
+ Dropdown.Separator = DropdownMenuSeparator;
18239
+ Dropdown.Shortcut = DropdownMenuShortcut;
18240
+ Dropdown.Sub = DropdownMenuSub;
18241
+ Dropdown.SubContent = DropdownMenuSubContent;
18242
+ Dropdown.SubTrigger = DropdownMenuSubTrigger;
18243
+ Dropdown.RadioGroup = DropdownMenuRadioGroup;
18244
+
18245
+ const useTriggerScorer = (onScorerTriggered) => {
18246
+ const client = useMastraClient();
18247
+ return useMutation({
18248
+ mutationFn: async ({ scorerName, traceId, spanId }) => {
18249
+ const response = await client.score({
18250
+ scorerName,
18251
+ targets: [{ traceId, spanId }]
18252
+ });
18253
+ return response;
18254
+ },
18255
+ onSuccess: (_, variables) => {
18256
+ toast.success("Scorer triggered successfully");
18257
+ onScorerTriggered(variables.scorerName, variables.traceId, variables.spanId);
18258
+ },
18259
+ onError: () => {
18260
+ toast.error("Error triggering scorer");
18261
+ }
18262
+ });
18263
+ };
18264
+
18265
+ const ScorersDropdown = ({ trace, spanId, onScorerTriggered, entityType }) => {
18266
+ const { data: scorers = {}, isLoading } = useScorers();
18267
+ const { mutate: triggerScorer, isPending } = useTriggerScorer(onScorerTriggered);
18268
+ let scorerList = Object.entries(scorers).map(([key, scorer]) => ({
18269
+ id: key,
18270
+ name: scorer.scorer.config.name,
18271
+ description: scorer.scorer.config.description,
18272
+ isRegistered: scorer.isRegistered,
18273
+ type: scorer.scorer.config.type
18274
+ })).filter((scorer) => scorer.isRegistered);
18275
+ if (entityType !== "Agent" || spanId) {
18276
+ scorerList = scorerList.filter((scorer) => scorer.type !== "agent");
18277
+ }
18278
+ const isWaiting = isPending || isLoading;
18279
+ return /* @__PURE__ */ jsxs(Dropdown, { children: [
18280
+ /* @__PURE__ */ jsx(Dropdown.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button$1, { variant: "light", disabled: isWaiting, children: [
18281
+ isWaiting ? /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(GaugeIcon, {}) }),
18282
+ "Run scorer",
18283
+ /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(ChevronDown, {}) })
18284
+ ] }) }),
18285
+ /* @__PURE__ */ jsx(Dropdown.Content, { children: scorerList.map((scorer) => /* @__PURE__ */ jsx(
18286
+ Dropdown.Item,
18287
+ {
18288
+ onClick: () => triggerScorer({ scorerName: scorer.name, traceId: trace.traceId, spanId }),
18289
+ children: /* @__PURE__ */ jsx("span", { children: scorer.name })
18290
+ },
18291
+ scorer.id
18292
+ )) })
18293
+ ] });
18294
+ };
18295
+
17968
18296
  function SpanDialog({
18297
+ trace,
17969
18298
  span,
17970
18299
  isOpen,
17971
18300
  onClose,
17972
18301
  onNext,
17973
18302
  onPrevious,
17974
18303
  onViewToggle,
17975
- spanInfo = []
18304
+ spanInfo = [],
18305
+ onScorerTriggered
17976
18306
  }) {
17977
18307
  const { Link } = useLinkComponent();
17978
18308
  return /* @__PURE__ */ jsxs(
@@ -18001,21 +18331,24 @@ function SpanDialog({
18001
18331
  /* @__PURE__ */ jsx("button", { className: "flex items-center gap-1", onClick: onViewToggle, children: /* @__PURE__ */ jsx(PanelTopIcon, {}) })
18002
18332
  ] }),
18003
18333
  /* @__PURE__ */ jsxs("div", { className: "p-[1.5rem] px-[2.5rem] overflow-y-auto grid gap-[1.5rem] content-start", children: [
18004
- /* @__PURE__ */ jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
18005
- /* @__PURE__ */ jsxs(SideDialogHeading, { children: [
18006
- /* @__PURE__ */ jsx(ChevronsLeftRightEllipsisIcon, {}),
18007
- " ",
18008
- span?.name
18334
+ /* @__PURE__ */ jsxs("div", { children: [
18335
+ /* @__PURE__ */ jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
18336
+ /* @__PURE__ */ jsxs(SideDialogHeading, { children: [
18337
+ /* @__PURE__ */ jsx(ChevronsLeftRightEllipsisIcon, {}),
18338
+ " ",
18339
+ span?.name
18340
+ ] }),
18341
+ /* @__PURE__ */ jsxs(TextAndIcon, { children: [
18342
+ /* @__PURE__ */ jsx(HashIcon, {}),
18343
+ " ",
18344
+ span?.spanId
18345
+ ] })
18009
18346
  ] }),
18010
- /* @__PURE__ */ jsxs(TextAndIcon, { children: [
18011
- /* @__PURE__ */ jsx(HashIcon, {}),
18012
- " ",
18013
- span?.spanId
18014
- ] })
18347
+ span?.traceId && span?.spanId && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ScorersDropdown, { trace, spanId: span?.spanId, onScorerTriggered }) })
18015
18348
  ] }),
18016
18349
  span?.attributes?.usage && /* @__PURE__ */ jsx(TraceSpanUsage, { spanUsage: span.attributes.usage, className: "mt-[1.5rem]" }),
18017
18350
  /* @__PURE__ */ jsx(KeyValueList, { data: spanInfo, LinkComponent: Link, className: "mt-[1.5rem]" }),
18018
- /* @__PURE__ */ jsx(SpanDetails, { span })
18351
+ /* @__PURE__ */ jsx(SpanDetails, { span, onScorerTriggered })
18019
18352
  ] })
18020
18353
  ]
18021
18354
  }
@@ -18030,11 +18363,15 @@ function TraceDialog({
18030
18363
  onClose,
18031
18364
  onNext,
18032
18365
  onPrevious,
18033
- isLoadingSpans
18366
+ isLoadingSpans,
18367
+ computeAgentsLink,
18368
+ computeWorkflowsLink,
18369
+ onScorerTriggered,
18370
+ initialSpanId
18034
18371
  }) {
18035
18372
  const { Link } = useLinkComponent();
18036
- const [dialogIsOpen, setDialogIsOpen] = useState(false);
18037
- const [selectedSpanId, setSelectedSpanId] = useState(void 0);
18373
+ const [dialogIsOpen, setDialogIsOpen] = useState(Boolean(initialSpanId));
18374
+ const [selectedSpanId, setSelectedSpanId] = useState(initialSpanId);
18038
18375
  const [combinedView, setCombinedView] = useState(false);
18039
18376
  const selectedSpan = traceSpans.find((span) => span.spanId === selectedSpanId);
18040
18377
  const traceInfo = useTraceInfo(traceDetails);
@@ -18082,6 +18419,12 @@ function TraceDialog({
18082
18419
  return currentIndex > 0;
18083
18420
  };
18084
18421
  const selectedSpanInfo = getSpanInfo({ span: selectedSpan, withTraceId: !combinedView, withSpanId: combinedView });
18422
+ let entityType;
18423
+ if (traceDetails?.attributes?.agentId) {
18424
+ entityType = "Agent";
18425
+ } else if (traceDetails?.attributes?.workflowId) {
18426
+ entityType = "Workflow";
18427
+ }
18085
18428
  return /* @__PURE__ */ jsxs(Fragment, { children: [
18086
18429
  /* @__PURE__ */ jsxs(
18087
18430
  SideDialog,
@@ -18105,7 +18448,7 @@ function TraceDialog({
18105
18448
  "grid-rows-[auto_1fr_1fr]": selectedSpan && combinedView
18106
18449
  }),
18107
18450
  children: [
18108
- /* @__PURE__ */ jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
18451
+ /* @__PURE__ */ jsxs(SideDialogHeader, { className: "pr-[2.5rem]", children: [
18109
18452
  /* @__PURE__ */ jsxs(SideDialogHeading, { children: [
18110
18453
  /* @__PURE__ */ jsx(EyeIcon, {}),
18111
18454
  " ",
@@ -18118,6 +18461,15 @@ function TraceDialog({
18118
18461
  ] })
18119
18462
  ] }),
18120
18463
  /* @__PURE__ */ jsxs("div", { className: cn("overflow-y-auto pb-[2.5rem]"), children: [
18464
+ traceDetails && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
18465
+ ScorersDropdown,
18466
+ {
18467
+ trace: traceDetails,
18468
+ spanId: selectedSpanId,
18469
+ onScorerTriggered,
18470
+ entityType
18471
+ }
18472
+ ) }),
18121
18473
  traceDetails?.metadata?.usage && /* @__PURE__ */ jsx(
18122
18474
  TraceSpanUsage,
18123
18475
  {
@@ -18137,7 +18489,20 @@ function TraceDialog({
18137
18489
  isLoading: isLoadingSpans,
18138
18490
  className: "pr-[2.5rem] pt-[2.5rem]"
18139
18491
  }
18140
- )
18492
+ ),
18493
+ traceDetails?.links?.length > 0 && /* @__PURE__ */ jsxs("div", { className: "pt-[2.5rem] pr-[2.5rem]", children: [
18494
+ /* @__PURE__ */ jsxs(SideDialogHeading, { as: "h2", className: "pb-[1rem]", children: [
18495
+ /* @__PURE__ */ jsx(GaugeIcon, {}),
18496
+ " Scores"
18497
+ ] }),
18498
+ /* @__PURE__ */ jsx("div", { className: "bg-surface2 rounded-lg overflow-hidden border-sm border-border1", children: /* @__PURE__ */ jsx(
18499
+ ScoreTable,
18500
+ {
18501
+ scores: traceDetails?.links,
18502
+ onItemClick: (scorerName) => onScorerTriggered(scorerName, traceDetails.traceId, selectedSpanId)
18503
+ }
18504
+ ) })
18505
+ ] })
18141
18506
  ] }),
18142
18507
  selectedSpan && combinedView && /* @__PURE__ */ jsxs("div", { className: "overflow-y-auto grid grid-rows-[auto_1fr] relative", children: [
18143
18508
  /* @__PURE__ */ jsx("div", { className: "absolute left-0 right-[2.5rem] h-[.5rem] bg-surface1 rounded-full top-0" }),
@@ -18168,11 +18533,11 @@ function TraceDialog({
18168
18533
  ] }),
18169
18534
  /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[20rem_1fr] gap-[1rem] overflow-y-auto", children: [
18170
18535
  /* @__PURE__ */ jsxs("div", { className: "overflow-y-auto grid content-start p-[1.5rem] pl-0 gap-[2rem]", children: [
18171
- /* @__PURE__ */ jsxs(SideDialogHeading, { as: "h2", children: [
18536
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(SideDialogHeading, { as: "h2", children: [
18172
18537
  /* @__PURE__ */ jsx(ChevronsLeftRightEllipsisIcon, {}),
18173
18538
  " ",
18174
18539
  selectedSpan?.name
18175
- ] }),
18540
+ ] }) }),
18176
18541
  selectedSpan?.attributes?.usage && /* @__PURE__ */ jsx(
18177
18542
  TraceSpanUsage,
18178
18543
  {
@@ -18182,7 +18547,7 @@ function TraceDialog({
18182
18547
  ),
18183
18548
  /* @__PURE__ */ jsx(KeyValueList, { data: selectedSpanInfo, LinkComponent: Link })
18184
18549
  ] }),
18185
- /* @__PURE__ */ jsx("div", { className: "overflow-y-auto pr-[2.5rem] pt-[2rem]", children: /* @__PURE__ */ jsx(SpanDetails, { span: selectedSpan }) })
18550
+ /* @__PURE__ */ jsx("div", { className: "overflow-y-auto pr-[2.5rem] pt-[2rem]", children: /* @__PURE__ */ jsx(SpanDetails, { span: selectedSpan, onScorerTriggered }) })
18186
18551
  ] })
18187
18552
  ] })
18188
18553
  ]
@@ -18191,16 +18556,21 @@ function TraceDialog({
18191
18556
  ]
18192
18557
  }
18193
18558
  ),
18194
- /* @__PURE__ */ jsx(
18559
+ traceDetails && /* @__PURE__ */ jsx(
18195
18560
  SpanDialog,
18196
18561
  {
18562
+ trace: traceDetails,
18197
18563
  span: selectedSpan,
18198
18564
  isOpen: Boolean(dialogIsOpen && selectedSpanId && !combinedView),
18199
- onClose: () => setDialogIsOpen(false),
18565
+ onClose: () => {
18566
+ setDialogIsOpen(false);
18567
+ setSelectedSpanId(void 0);
18568
+ },
18200
18569
  onNext: thereIsNextSpan() ? toNextSpan : void 0,
18201
18570
  onPrevious: thereIsPreviousSpan() ? toPreviousSpan : void 0,
18202
18571
  onViewToggle: () => setCombinedView(!combinedView),
18203
- spanInfo: selectedSpanInfo
18572
+ spanInfo: selectedSpanInfo,
18573
+ onScorerTriggered
18204
18574
  }
18205
18575
  )
18206
18576
  ] });