@mastra/playground-ui 7.0.0-beta.10 → 7.0.0-beta.11

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
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useAssistantState, useMessage, MessagePrimitive, ActionBarPrimitive, useComposerRuntime, useAttachment, ComposerPrimitive, AttachmentPrimitive, useComposer, ThreadPrimitive, CompositeAttachmentAdapter, SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, WebSpeechSynthesisAdapter, useExternalStoreRuntime, AssistantRuntimeProvider } from '@assistant-ui/react';
3
- import { CheckIcon as CheckIcon$1, CopyIcon, InfoIcon as InfoIcon$1, AlertCircle, TriangleAlert, ChevronUpIcon, X, Share2, Check, PlayCircle, Workflow, Layers, List, Clock as Clock$1, CalendarClock, Timer, CornerDownRight, GitBranch, RefreshCw, Repeat, Repeat1, Network, CalendarIcon, ChevronDown, Braces, ChevronDownIcon, Brackets, PlusIcon, TrashIcon, Plus, Loader2, Circle, EyeOffIcon, EyeIcon, PauseIcon, HourglassIcon, CircleDashed, Footprints, CircleCheck, CircleX, Minus, Maximize, AlertCircleIcon, CirclePause, StopCircle, SearchIcon, ChevronsUpDown, Search, BrainIcon, AudioLinesIcon, StopCircleIcon, FileText, CircleXIcon, Link, CloudUpload, Mic, ArrowUp, SaveIcon, ExternalLink, XIcon, TriangleAlertIcon, ChevronRightIcon, ArrowLeftIcon, ArrowRightIcon, ChevronsRightIcon, AlignLeftIcon, AlignJustifyIcon, ArrowUpIcon, ArrowDownIcon, CircleAlertIcon, PanelRightIcon, KeyboardIcon, GaugeIcon, ChevronsLeftRightEllipsisIcon, CalculatorIcon, HashIcon, FileInputIcon, FileOutputIcon, ReceiptText, Info, RotateCcw, GripVertical, RefreshCcwIcon, AlertTriangleIcon, ChevronRight, NetworkIcon, WorkflowIcon as WorkflowIcon$1, PackageIcon, GitBranchIcon, PackageOpenIcon, OctagonXIcon, FrownIcon, CircleChevronUpIcon, CircleChevronDownIcon, FileIcon, ChevronsUpIcon, ChevronsDownIcon, TimerIcon, ChevronsLeftRightIcon, ChevronFirstIcon, ChevronLastIcon, CircleDashedIcon, ArrowRightToLineIcon, CoinsIcon, BracesIcon, CircleGaugeIcon, PanelTopIcon, ListTreeIcon, PanelLeftIcon, CircleSlash, Trash, Link2 } from 'lucide-react';
3
+ import { CheckIcon as CheckIcon$1, CopyIcon, ShieldAlert, ChevronDown, ChevronRight, RefreshCw, Tag, InfoIcon as InfoIcon$1, AlertCircle, TriangleAlert, ChevronUpIcon, X, Share2, Check, PlayCircle, Workflow, Layers, List, Clock as Clock$1, CalendarClock, Timer, CornerDownRight, GitBranch, Repeat, Repeat1, Network, CalendarIcon, Braces, ChevronDownIcon, Brackets, PlusIcon, TrashIcon, Plus, Loader2, Circle, EyeOffIcon, EyeIcon, PauseIcon, HourglassIcon, CircleDashed, Footprints, CircleCheck, CircleX, Minus, Maximize, AlertCircleIcon, CirclePause, StopCircle, Cpu, SearchIcon, ChevronsUpDown, Search, BrainIcon, AudioLinesIcon, StopCircleIcon, FileText, CircleXIcon, Link, CloudUpload, Mic, ArrowUp, SaveIcon, ExternalLink, XIcon, TriangleAlertIcon, ChevronRightIcon, ArrowLeftIcon, ArrowRightIcon, ChevronsRightIcon, AlignLeftIcon, AlignJustifyIcon, ArrowUpIcon, ArrowDownIcon, CircleAlertIcon, PanelRightIcon, KeyboardIcon, GaugeIcon, ChevronsLeftRightEllipsisIcon, CalculatorIcon, HashIcon, FileInputIcon, FileOutputIcon, ReceiptText, Info, RotateCcw, GripVertical, RefreshCcwIcon, AlertTriangleIcon, NetworkIcon, WorkflowIcon as WorkflowIcon$1, PackageIcon, GitBranchIcon, PackageOpenIcon, OctagonXIcon, FrownIcon, CircleChevronUpIcon, CircleChevronDownIcon, FileIcon, ChevronsUpIcon, ChevronsDownIcon, TimerIcon, ChevronsLeftRightIcon, ChevronFirstIcon, ChevronLastIcon, CircleDashedIcon, ArrowRightToLineIcon, CoinsIcon, BracesIcon, CircleGaugeIcon, PanelTopIcon, ListTreeIcon, PanelLeftIcon, CircleSlash, Trash, Link2 } from 'lucide-react';
4
4
  import * as React from 'react';
5
5
  import React__default, { forwardRef, memo, useState, useEffect, useRef, useCallback, useMemo, createContext, useContext, Fragment as Fragment$1, useId, Suspense, useLayoutEffect } from 'react';
6
6
  import { Slot } from '@radix-ui/react-slot';
@@ -3430,6 +3430,55 @@ const defaultComponents = unstable_memoizeMarkdownComponents({
3430
3430
  img: ImageWithFallback
3431
3431
  });
3432
3432
 
3433
+ const TripwireNotice = ({ reason, tripwire }) => {
3434
+ const [isExpanded, setIsExpanded] = useState(false);
3435
+ const hasMetadata = tripwire && (tripwire.retry !== void 0 || tripwire.tripwirePayload || tripwire.processorId);
3436
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-amber-500/30 bg-amber-950/20 overflow-hidden", children: [
3437
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 p-4", children: [
3438
+ /* @__PURE__ */ jsx(ShieldAlert, { className: "w-5 h-5 text-amber-400 mt-0.5 flex-shrink-0" }),
3439
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
3440
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-amber-200 mb-1", children: "Content Blocked" }),
3441
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-amber-300/90", children: reason })
3442
+ ] })
3443
+ ] }),
3444
+ hasMetadata && /* @__PURE__ */ jsxs(Fragment, { children: [
3445
+ /* @__PURE__ */ jsxs(
3446
+ "button",
3447
+ {
3448
+ onClick: () => setIsExpanded(!isExpanded),
3449
+ className: "w-full flex items-center gap-2 px-4 py-2 text-xs text-amber-400/70 hover:text-amber-400 hover:bg-amber-900/20 transition-colors border-t border-amber-500/20",
3450
+ children: [
3451
+ isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-3.5 h-3.5" }),
3452
+ /* @__PURE__ */ jsx("span", { children: "Details" })
3453
+ ]
3454
+ }
3455
+ ),
3456
+ isExpanded && /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 space-y-3 border-t border-amber-500/20 bg-amber-950/10", children: [
3457
+ tripwire.retry !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-3", children: [
3458
+ /* @__PURE__ */ jsx(RefreshCw, { className: "w-3.5 h-3.5 text-amber-400/60" }),
3459
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-amber-300/70", children: [
3460
+ "Retry:",
3461
+ " ",
3462
+ tripwire.retry ? /* @__PURE__ */ jsx("span", { className: "text-green-400", children: "Allowed" }) : /* @__PURE__ */ jsx("span", { className: "text-red-400", children: "Not allowed" })
3463
+ ] })
3464
+ ] }),
3465
+ tripwire.processorId && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
3466
+ /* @__PURE__ */ jsx(Tag, { className: "w-3.5 h-3.5 text-amber-400/60" }),
3467
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-amber-300/70", children: [
3468
+ "Processor:",
3469
+ " ",
3470
+ /* @__PURE__ */ jsx("code", { className: "px-1.5 py-0.5 rounded bg-amber-900/30 text-amber-200 font-mono", children: tripwire.processorId })
3471
+ ] })
3472
+ ] }),
3473
+ tripwire.tripwirePayload !== void 0 && tripwire.tripwirePayload !== null && /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
3474
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-amber-400/60 mb-1.5", children: "Metadata:" }),
3475
+ /* @__PURE__ */ jsx("pre", { className: "text-xs text-amber-200/80 bg-amber-900/30 rounded p-2 overflow-x-auto font-mono", children: String(JSON.stringify(tripwire.tripwirePayload, null, 2)) })
3476
+ ] })
3477
+ ] })
3478
+ ] })
3479
+ ] });
3480
+ };
3481
+
3433
3482
  const AgentIcon = (props) => /* @__PURE__ */ jsxs("svg", { width: "17", height: "16", viewBox: "0 0 17 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", ...props, children: [
3434
3483
  /* @__PURE__ */ jsx(
3435
3484
  "path",
@@ -4220,6 +4269,9 @@ const ErrorAwareText = () => {
4220
4269
  const part = useAssistantState(({ part: part2 }) => part2);
4221
4270
  const text = part.text || "";
4222
4271
  const metadata = part.metadata || {};
4272
+ if (metadata?.status === "tripwire") {
4273
+ return /* @__PURE__ */ jsx(TripwireNotice, { reason: text, tripwire: metadata.tripwire });
4274
+ }
4223
4275
  if (metadata?.status === "warning") {
4224
4276
  return /* @__PURE__ */ jsxs(Alert$1, { variant: "warning", children: [
4225
4277
  /* @__PURE__ */ jsx(AlertTitle$1, { as: "h5", children: "Warning" }),
@@ -4652,6 +4704,7 @@ function convertWorkflowRunStateToStreamResult(runState) {
4652
4704
  Object.entries(context).forEach(([stepId, stepResult]) => {
4653
4705
  if (stepId !== "input" && "status" in stepResult) {
4654
4706
  const result = stepResult;
4707
+ const hasTripwire = result.status === "failed" && result.tripwire !== void 0;
4655
4708
  steps[stepId] = {
4656
4709
  status: result.status,
4657
4710
  output: "output" in result ? result.output : void 0,
@@ -4659,7 +4712,9 @@ function convertWorkflowRunStateToStreamResult(runState) {
4659
4712
  suspendPayload: "suspendPayload" in result ? result.suspendPayload : void 0,
4660
4713
  suspendOutput: "suspendOutput" in result ? result.suspendOutput : void 0,
4661
4714
  resumePayload: "resumePayload" in result ? result.resumePayload : void 0,
4662
- error: "error" in result ? result.error : void 0,
4715
+ // Don't include error when tripwire is present - tripwire takes precedence
4716
+ error: hasTripwire ? void 0 : "error" in result ? result.error : void 0,
4717
+ tripwire: hasTripwire ? result.tripwire : void 0,
4663
4718
  startedAt: "startedAt" in result ? result.startedAt : Date.now(),
4664
4719
  endedAt: "endedAt" in result ? result.endedAt : void 0,
4665
4720
  suspendedAt: "suspendedAt" in result ? result.suspendedAt : void 0,
@@ -4684,7 +4739,15 @@ function convertWorkflowRunStateToStreamResult(runState) {
4684
4739
  status: runState.status,
4685
4740
  ...runState.status === "success" ? { result: runState.result } : {},
4686
4741
  ...runState.status === "failed" ? { error: runState.error } : {},
4687
- ...runState.status === "suspended" ? { suspended: suspendedStepIds, suspendPayload } : {}
4742
+ ...runState.status === "suspended" ? { suspended: suspendedStepIds, suspendPayload } : {},
4743
+ ...runState.status === "tripwire" && runState.tripwire ? {
4744
+ tripwire: {
4745
+ reason: runState.tripwire.reason,
4746
+ retry: runState.tripwire.retry,
4747
+ metadata: runState.tripwire.metadata,
4748
+ processorId: runState.tripwire.processorId
4749
+ }
4750
+ } : {}
4688
4751
  };
4689
4752
  }
4690
4753
 
@@ -6117,10 +6180,13 @@ const useCurrentRun = () => {
6117
6180
  const context = useContext(WorkflowRunContext);
6118
6181
  const workflowCurrentSteps = context.result?.steps ?? {};
6119
6182
  const steps = Object.entries(workflowCurrentSteps).reduce((acc, [key, value]) => {
6183
+ const hasTripwire = "tripwire" in value && value.tripwire;
6120
6184
  return {
6121
6185
  ...acc,
6122
6186
  [key]: {
6123
- error: "error" in value ? value.error : void 0,
6187
+ // Don't include error when tripwire is present - tripwire takes precedence
6188
+ error: hasTripwire ? void 0 : "error" in value ? value.error : void 0,
6189
+ tripwire: hasTripwire ? value.tripwire : void 0,
6124
6190
  startedAt: value.startedAt,
6125
6191
  endedAt: "endedAt" in value ? value.endedAt : void 0,
6126
6192
  status: value.status,
@@ -7169,12 +7235,23 @@ function inferFieldType(schema, fieldConfig) {
7169
7235
  if (schema instanceof z.ZodDiscriminatedUnion) {
7170
7236
  return "discriminated-union";
7171
7237
  }
7238
+ if (schema instanceof z.ZodLiteral) {
7239
+ const v4Values = schema._zod?.def?.values;
7240
+ const v3Value = schema._def?.value;
7241
+ const literalValue = v4Values !== void 0 ? Array.isArray(v4Values) ? v4Values[0] : v4Values : v3Value;
7242
+ if (typeof literalValue === "number") return "number";
7243
+ if (typeof literalValue === "boolean") return "boolean";
7244
+ return "string";
7245
+ }
7172
7246
  return "string";
7173
7247
  }
7174
7248
 
7175
7249
  function getDefaultValueInZodStack(schema) {
7176
7250
  if (schema instanceof z$2.core.$ZodDefault) {
7177
7251
  return schema._zod.def.defaultValue;
7252
+ } else if (schema instanceof z$2.core.$ZodLiteral) {
7253
+ const values = schema._zod.def.values;
7254
+ return Array.isArray(values) ? values[0] : values;
7178
7255
  } else if ("innerType" in schema._zod.def) {
7179
7256
  return getDefaultValueInZodStack(schema._zod.def.innerType);
7180
7257
  } else if ("shape" in schema._zod.def) {
@@ -7791,6 +7868,7 @@ const WorkflowStepActionBar = ({
7791
7868
  resumeData,
7792
7869
  suspendOutput,
7793
7870
  error,
7871
+ tripwire,
7794
7872
  mapConfig,
7795
7873
  stepName,
7796
7874
  stepId,
@@ -7802,19 +7880,21 @@ const WorkflowStepActionBar = ({
7802
7880
  const [isOutputOpen, setIsOutputOpen] = useState(false);
7803
7881
  const [isResumeDataOpen, setIsResumeDataOpen] = useState(false);
7804
7882
  const [isErrorOpen, setIsErrorOpen] = useState(false);
7883
+ const [isTripwireOpen, setIsTripwireOpen] = useState(false);
7805
7884
  const [isMapConfigOpen, setIsMapConfigOpen] = useState(false);
7806
7885
  const [isTimeTravelOpen, setIsTimeTravelOpen] = useState(false);
7807
7886
  const { withoutTimeTravel } = useContext(WorkflowRunContext);
7808
7887
  const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
7809
7888
  const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
7810
7889
  const showTimeTravel = !withoutTimeTravel && stepKey && !mapConfig;
7811
- return /* @__PURE__ */ jsx(Fragment, { children: (input || output || error || mapConfig || resumeData || onShowNestedGraph || showTimeTravel) && /* @__PURE__ */ jsxs(
7890
+ return /* @__PURE__ */ jsx(Fragment, { children: (input || output || error || tripwire || mapConfig || resumeData || onShowNestedGraph || showTimeTravel) && /* @__PURE__ */ jsxs(
7812
7891
  "div",
7813
7892
  {
7814
7893
  className: cn(
7815
7894
  "flex flex-wrap items-center bg-surface4 border-t-sm border-border1 px-2 py-1 gap-2 rounded-b-lg",
7816
7895
  status === "success" && "bg-accent1Dark",
7817
7896
  status === "failed" && "bg-accent2Dark",
7897
+ status === "tripwire" && "bg-amber-900/40 border-amber-500/20",
7818
7898
  status === "suspended" && "bg-accent3Dark",
7819
7899
  status === "waiting" && "bg-accent5Dark",
7820
7900
  status === "running" && "bg-accent6Dark"
@@ -7883,6 +7963,26 @@ const WorkflowStepActionBar = ({
7883
7963
  ] }),
7884
7964
  /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: error }) })
7885
7965
  ] }) })
7966
+ ] }),
7967
+ tripwire && /* @__PURE__ */ jsxs(Fragment, { children: [
7968
+ /* @__PURE__ */ jsx(Button$1, { onClick: () => setIsTripwireOpen(true), className: "text-amber-400 hover:text-amber-300", children: "Tripwire" }),
7969
+ /* @__PURE__ */ jsx(Dialog, { open: isTripwireOpen, onOpenChange: setIsTripwireOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7970
+ /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7971
+ stepName,
7972
+ " tripwire"
7973
+ ] }),
7974
+ /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(
7975
+ CodeDialogContent,
7976
+ {
7977
+ data: {
7978
+ reason: tripwire.reason,
7979
+ retry: tripwire.retry,
7980
+ metadata: tripwire.metadata,
7981
+ processorId: tripwire.processorId
7982
+ }
7983
+ }
7984
+ ) })
7985
+ ] }) })
7886
7986
  ] })
7887
7987
  ]
7888
7988
  }
@@ -7898,6 +7998,8 @@ function WorkflowConditionNode({ data }) {
7898
7998
  const { steps } = useCurrentRun();
7899
7999
  const previousStep = steps[previousStepId];
7900
8000
  const nextStep = steps[nextStepId];
8001
+ const isPreviousTripwire = previousStep?.status === "failed" && previousStep?.tripwire !== void 0;
8002
+ const previousDisplayStatus = isPreviousTripwire ? "tripwire" : previousStep?.status;
7901
8003
  const { icon: IconComponent, color } = getConditionIconAndColor(type);
7902
8004
  return /* @__PURE__ */ jsxs(Fragment, { children: [
7903
8005
  !withoutTopHandle && /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: { visibility: "hidden" } }),
@@ -7905,12 +8007,13 @@ function WorkflowConditionNode({ data }) {
7905
8007
  "div",
7906
8008
  {
7907
8009
  "data-workflow-node": true,
7908
- "data-workflow-step-status": previousStep?.status,
8010
+ "data-workflow-step-status": previousDisplayStatus,
7909
8011
  "data-testid": "workflow-condition-node",
7910
8012
  className: cn(
7911
8013
  "bg-surface3 rounded-lg w-[300px] border-sm border-border1",
7912
- previousStep?.status === "success" && nextStep && "bg-accent1Darker",
7913
- previousStep?.status === "failed" && nextStep && "bg-accent2Darker",
8014
+ previousDisplayStatus === "success" && nextStep && "bg-accent1Darker",
8015
+ previousDisplayStatus === "failed" && nextStep && "bg-accent2Darker",
8016
+ previousDisplayStatus === "tripwire" && nextStep && "bg-amber-950/40 border-amber-500/30",
7914
8017
  !previousStep && Boolean(nextStep?.status) && "bg-accent1Darker"
7915
8018
  ),
7916
8019
  children: [
@@ -7964,8 +8067,9 @@ function WorkflowConditionNode({ data }) {
7964
8067
  className: cn(
7965
8068
  "relative font-mono p-3 w-full cursor-pointer rounded-lg text-xs !bg-surface4 overflow-scroll",
7966
8069
  className,
7967
- previousStep?.status === "success" && nextStep && "!bg-accent1Dark",
7968
- previousStep?.status === "failed" && nextStep && "!bg-accent2Dark"
8070
+ previousDisplayStatus === "success" && nextStep && "!bg-accent1Dark",
8071
+ previousDisplayStatus === "failed" && nextStep && "!bg-accent2Dark",
8072
+ previousDisplayStatus === "tripwire" && nextStep && "!bg-amber-900/40"
7969
8073
  ),
7970
8074
  onClick: () => setOpenDialog(true),
7971
8075
  style,
@@ -8021,7 +8125,8 @@ function WorkflowConditionNode({ data }) {
8021
8125
  stepName: nextStepId,
8022
8126
  input: previousStep?.output,
8023
8127
  mapConfig: data.mapConfig,
8024
- status: nextStep ? previousStep?.status : void 0
8128
+ tripwire: isPreviousTripwire ? previousStep?.tripwire : void 0,
8129
+ status: nextStep ? previousDisplayStatus : void 0
8025
8130
  }
8026
8131
  )
8027
8132
  ]
@@ -8067,6 +8172,8 @@ function WorkflowDefaultNode({ data, parentWorkflowName }) {
8067
8172
  } = data;
8068
8173
  const stepKey = parentWorkflowName ? `${parentWorkflowName}.${stepId || label}` : stepId || label;
8069
8174
  const step = steps[stepKey];
8175
+ const isTripwire = step?.status === "failed" && step?.tripwire !== void 0;
8176
+ const displayStatus = isTripwire ? "tripwire" : step?.status;
8070
8177
  const { isSleepNode, isForEachNode, isMapNode, hasSpecialBadge } = getNodeBadgeInfo({
8071
8178
  duration,
8072
8179
  date,
@@ -8081,16 +8188,17 @@ function WorkflowDefaultNode({ data, parentWorkflowName }) {
8081
8188
  "div",
8082
8189
  {
8083
8190
  "data-workflow-node": true,
8084
- "data-workflow-step-status": step?.status ?? "idle",
8191
+ "data-workflow-step-status": displayStatus ?? "idle",
8085
8192
  "data-testid": "workflow-default-node",
8086
8193
  className: cn(
8087
8194
  "bg-surface3 rounded-lg w-[274px] border-sm border-border1",
8088
8195
  hasSpecialBadge ? "pt-0" : "pt-2",
8089
- step?.status === "success" && "bg-accent1Darker",
8090
- step?.status === "failed" && "bg-accent2Darker",
8091
- step?.status === "suspended" && "bg-accent3Darker",
8092
- step?.status === "waiting" && "bg-accent5Darker",
8093
- step?.status === "running" && "bg-accent6Darker"
8196
+ displayStatus === "success" && "bg-accent1Darker",
8197
+ displayStatus === "failed" && "bg-accent2Darker",
8198
+ displayStatus === "tripwire" && "bg-amber-950/40 border-amber-500/30",
8199
+ displayStatus === "suspended" && "bg-accent3Darker",
8200
+ displayStatus === "waiting" && "bg-accent5Darker",
8201
+ displayStatus === "running" && "bg-accent6Darker"
8094
8202
  ),
8095
8203
  children: [
8096
8204
  hasSpecialBadge && /* @__PURE__ */ jsxs("div", { className: "px-3 pt-2 pb-1 flex gap-1.5 flex-wrap", children: [
@@ -8108,11 +8216,12 @@ function WorkflowDefaultNode({ data, parentWorkflowName }) {
8108
8216
  ] }),
8109
8217
  /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2 px-3", !description && "pb-2"), children: [
8110
8218
  /* @__PURE__ */ jsxs(Icon, { children: [
8111
- step?.status === "failed" && /* @__PURE__ */ jsx(CrossIcon, { className: "text-accent2" }),
8112
- step?.status === "success" && /* @__PURE__ */ jsx(CheckIcon, { className: "text-accent1" }),
8113
- step?.status === "suspended" && /* @__PURE__ */ jsx(PauseIcon, { className: "text-accent3" }),
8114
- step?.status === "waiting" && /* @__PURE__ */ jsx(HourglassIcon, { className: "text-accent5" }),
8115
- step?.status === "running" && /* @__PURE__ */ jsx(Loader2, { className: "text-accent6 animate-spin" }),
8219
+ displayStatus === "tripwire" && /* @__PURE__ */ jsx(ShieldAlert, { className: "text-amber-400" }),
8220
+ displayStatus === "failed" && /* @__PURE__ */ jsx(CrossIcon, { className: "text-accent2" }),
8221
+ displayStatus === "success" && /* @__PURE__ */ jsx(CheckIcon, { className: "text-accent1" }),
8222
+ displayStatus === "suspended" && /* @__PURE__ */ jsx(PauseIcon, { className: "text-accent3" }),
8223
+ displayStatus === "waiting" && /* @__PURE__ */ jsx(HourglassIcon, { className: "text-accent5" }),
8224
+ displayStatus === "running" && /* @__PURE__ */ jsx(Loader2, { className: "text-accent6 animate-spin" }),
8116
8225
  !step && /* @__PURE__ */ jsx(CircleDashed, { className: "text-icon2" })
8117
8226
  ] }),
8118
8227
  /* @__PURE__ */ jsxs(Txt, { variant: "ui-lg", className: "text-icon6 font-medium inline-flex items-center gap-1 justify-between w-full", children: [
@@ -8142,9 +8251,10 @@ function WorkflowDefaultNode({ data, parentWorkflowName }) {
8142
8251
  resumeData: step?.resumeData,
8143
8252
  output: step?.output,
8144
8253
  suspendOutput: step?.suspendOutput,
8145
- error: step?.error,
8254
+ error: isTripwire ? void 0 : step?.error,
8255
+ tripwire: isTripwire ? step?.tripwire : void 0,
8146
8256
  mapConfig,
8147
- status: step?.status,
8257
+ status: displayStatus,
8148
8258
  stepKey
8149
8259
  }
8150
8260
  )
@@ -8396,6 +8506,8 @@ function WorkflowNestedNode({ data, parentWorkflowName }) {
8396
8506
  const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
8397
8507
  const stepKey = parentWorkflowName ? `${parentWorkflowName}.${stepId || label}` : stepId || label;
8398
8508
  const step = steps[stepKey];
8509
+ const isTripwire = step?.status === "failed" && step?.tripwire !== void 0;
8510
+ const displayStatus = isTripwire ? "tripwire" : step?.status;
8399
8511
  const { isForEachNode, isMapNode, isNestedWorkflow, hasSpecialBadge } = getNodeBadgeInfo({
8400
8512
  isForEach,
8401
8513
  mapConfig,
@@ -8410,15 +8522,16 @@ function WorkflowNestedNode({ data, parentWorkflowName }) {
8410
8522
  {
8411
8523
  "data-testid": "workflow-nested-node",
8412
8524
  "data-workflow-node": true,
8413
- "data-workflow-step-status": step?.status,
8525
+ "data-workflow-step-status": displayStatus,
8414
8526
  className: cn(
8415
8527
  "bg-surface3 rounded-lg w-[274px] border-sm border-border1",
8416
8528
  hasSpecialBadge ? "pt-0" : "pt-2",
8417
- step?.status === "success" && "bg-accent1Darker",
8418
- step?.status === "failed" && "bg-accent2Darker",
8419
- step?.status === "suspended" && "bg-accent3Darker",
8420
- step?.status === "waiting" && "bg-accent5Darker",
8421
- step?.status === "running" && "bg-accent6Darker"
8529
+ displayStatus === "success" && "bg-accent1Darker",
8530
+ displayStatus === "failed" && "bg-accent2Darker",
8531
+ displayStatus === "tripwire" && "bg-amber-950/40 border-amber-500/30",
8532
+ displayStatus === "suspended" && "bg-accent3Darker",
8533
+ displayStatus === "waiting" && "bg-accent5Darker",
8534
+ displayStatus === "running" && "bg-accent6Darker"
8422
8535
  ),
8423
8536
  children: [
8424
8537
  hasSpecialBadge && /* @__PURE__ */ jsxs("div", { className: "px-3 pt-2 pb-1 flex gap-1.5 flex-wrap", children: [
@@ -8430,11 +8543,12 @@ function WorkflowNestedNode({ data, parentWorkflowName }) {
8430
8543
  ] }),
8431
8544
  /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2 px-3", !description && "pb-2"), children: [
8432
8545
  /* @__PURE__ */ jsxs(Icon, { children: [
8433
- step?.status === "failed" && /* @__PURE__ */ jsx(CrossIcon, { className: "text-accent2" }),
8434
- step?.status === "success" && /* @__PURE__ */ jsx(CheckIcon, { className: "text-accent1" }),
8435
- step?.status === "suspended" && /* @__PURE__ */ jsx(PauseIcon, { className: "text-accent3" }),
8436
- step?.status === "waiting" && /* @__PURE__ */ jsx(HourglassIcon, { className: "text-accent5" }),
8437
- step?.status === "running" && /* @__PURE__ */ jsx(Loader2, { className: "text-accent6 animate-spin" }),
8546
+ displayStatus === "failed" && /* @__PURE__ */ jsx(CrossIcon, { className: "text-accent2" }),
8547
+ displayStatus === "success" && /* @__PURE__ */ jsx(CheckIcon, { className: "text-accent1" }),
8548
+ displayStatus === "tripwire" && /* @__PURE__ */ jsx(ShieldAlert, { className: "text-amber-400" }),
8549
+ displayStatus === "suspended" && /* @__PURE__ */ jsx(PauseIcon, { className: "text-accent3" }),
8550
+ displayStatus === "waiting" && /* @__PURE__ */ jsx(HourglassIcon, { className: "text-accent5" }),
8551
+ displayStatus === "running" && /* @__PURE__ */ jsx(Loader2, { className: "text-accent6 animate-spin" }),
8438
8552
  !step && /* @__PURE__ */ jsx(CircleDashed, { className: "text-icon2" })
8439
8553
  ] }),
8440
8554
  /* @__PURE__ */ jsxs(Txt, { variant: "ui-lg", className: "text-icon6 font-medium inline-flex items-center gap-1 justify-between w-full", children: [
@@ -8454,9 +8568,10 @@ function WorkflowNestedNode({ data, parentWorkflowName }) {
8454
8568
  output: step?.output,
8455
8569
  suspendOutput: step?.suspendOutput,
8456
8570
  error: step?.error,
8571
+ tripwire: isTripwire ? step?.tripwire : void 0,
8457
8572
  mapConfig,
8458
8573
  onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }),
8459
- status: step?.status,
8574
+ status: displayStatus,
8460
8575
  stepKey
8461
8576
  }
8462
8577
  )
@@ -8562,7 +8677,12 @@ const WorkflowCard = ({ header, children, footer }) => {
8562
8677
  ] });
8563
8678
  };
8564
8679
 
8565
- const WorkflowStatus = ({ stepId, status, result }) => {
8680
+ const WorkflowStatus = ({ stepId, status, result, tripwire }) => {
8681
+ const [isTripwireExpanded, setIsTripwireExpanded] = useState(false);
8682
+ const isTripwire = status === "tripwire";
8683
+ const hasTripwireMetadata = Boolean(
8684
+ tripwire && (tripwire.retry !== void 0 || tripwire.metadata !== void 0 || tripwire.processorId !== void 0)
8685
+ );
8566
8686
  return /* @__PURE__ */ jsx(
8567
8687
  WorkflowCard,
8568
8688
  {
@@ -8570,19 +8690,74 @@ const WorkflowStatus = ({ stepId, status, result }) => {
8570
8690
  /* @__PURE__ */ jsxs(Icon, { children: [
8571
8691
  status === "success" && /* @__PURE__ */ jsx(CheckIcon, { className: "text-accent1" }),
8572
8692
  status === "failed" && /* @__PURE__ */ jsx(CrossIcon, { className: "text-accent2" }),
8693
+ status === "tripwire" && /* @__PURE__ */ jsx(ShieldAlert, { className: "text-amber-400" }),
8573
8694
  status === "suspended" && /* @__PURE__ */ jsx(CirclePause, { className: "text-accent3" }),
8574
8695
  status === "waiting" && /* @__PURE__ */ jsx(HourglassIcon, { className: "text-accent5" }),
8575
8696
  status === "running" && /* @__PURE__ */ jsx(Loader2, { className: "text-accent6 animate-spin" })
8576
8697
  ] }),
8577
8698
  /* @__PURE__ */ jsx(Txt, { as: "span", variant: "ui-lg", className: "text-icon6 font-medium", children: stepId.charAt(0).toUpperCase() + stepId.slice(1) })
8578
8699
  ] }),
8579
- children: /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-surface4 p-1 font-mono relative", children: [
8700
+ children: isTripwire && tripwire ? /* @__PURE__ */ jsx(
8701
+ TripwireDetails,
8702
+ {
8703
+ tripwire,
8704
+ isExpanded: isTripwireExpanded,
8705
+ onToggleExpand: () => setIsTripwireExpanded(!isTripwireExpanded),
8706
+ hasMetadata: hasTripwireMetadata
8707
+ }
8708
+ ) : /* @__PURE__ */ jsxs("div", { className: "rounded-md bg-surface4 p-1 font-mono relative", children: [
8580
8709
  /* @__PURE__ */ jsx(CopyButton, { content: JSON.stringify(result, null, 2), className: "absolute top-2 right-2 z-10" }),
8581
8710
  /* @__PURE__ */ jsx(SyntaxHighlighter$1, { data: result })
8582
8711
  ] })
8583
8712
  }
8584
8713
  );
8585
8714
  };
8715
+ const TripwireDetails = ({ tripwire, isExpanded, onToggleExpand, hasMetadata }) => {
8716
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-amber-500/30 bg-amber-950/20 overflow-hidden", children: [
8717
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 p-4", children: [
8718
+ /* @__PURE__ */ jsx(ShieldAlert, { className: "w-5 h-5 text-amber-400 mt-0.5 flex-shrink-0" }),
8719
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
8720
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-amber-200 mb-1", children: "Content Blocked" }),
8721
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-amber-300/90", children: tripwire.reason || "Tripwire triggered" })
8722
+ ] })
8723
+ ] }),
8724
+ hasMetadata && /* @__PURE__ */ jsxs(Fragment, { children: [
8725
+ /* @__PURE__ */ jsxs(
8726
+ "button",
8727
+ {
8728
+ onClick: onToggleExpand,
8729
+ className: "w-full flex items-center gap-2 px-4 py-2 text-xs text-amber-400/70 hover:text-amber-400 hover:bg-amber-900/20 transition-colors border-t border-amber-500/20",
8730
+ children: [
8731
+ isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-3.5 h-3.5" }),
8732
+ /* @__PURE__ */ jsx("span", { children: "Details" })
8733
+ ]
8734
+ }
8735
+ ),
8736
+ isExpanded && /* @__PURE__ */ jsxs("div", { className: "px-4 pb-4 space-y-3 border-t border-amber-500/20 bg-amber-950/10", children: [
8737
+ tripwire.retry !== void 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-3", children: [
8738
+ /* @__PURE__ */ jsx(RefreshCw, { className: "w-3.5 h-3.5 text-amber-400/60" }),
8739
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-amber-300/70", children: [
8740
+ "Retry:",
8741
+ " ",
8742
+ tripwire.retry ? /* @__PURE__ */ jsx("span", { className: "text-green-400", children: "Allowed" }) : /* @__PURE__ */ jsx("span", { className: "text-red-400", children: "Not allowed" })
8743
+ ] })
8744
+ ] }),
8745
+ tripwire.processorId && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8746
+ /* @__PURE__ */ jsx(Tag, { className: "w-3.5 h-3.5 text-amber-400/60" }),
8747
+ /* @__PURE__ */ jsxs("span", { className: "text-xs text-amber-300/70", children: [
8748
+ "Processor:",
8749
+ " ",
8750
+ /* @__PURE__ */ jsx("code", { className: "px-1.5 py-0.5 rounded bg-amber-900/30 text-amber-200 font-mono", children: tripwire.processorId })
8751
+ ] })
8752
+ ] }),
8753
+ tripwire.metadata !== void 0 && tripwire.metadata !== null && /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
8754
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-amber-400/60 mb-1.5", children: "Metadata:" }),
8755
+ /* @__PURE__ */ jsx("pre", { className: "text-xs text-amber-200/80 bg-amber-900/30 rounded p-2 overflow-x-auto font-mono", children: String(JSON.stringify(tripwire.metadata, null, 2)) })
8756
+ ] })
8757
+ ] })
8758
+ ] })
8759
+ ] });
8760
+ };
8586
8761
 
8587
8762
  const isObjectEmpty = (objectName) => {
8588
8763
  return objectName && Object.keys(objectName).length === 0 && objectName.constructor === Object;
@@ -8675,7 +8850,7 @@ function WorkflowTrigger({
8675
8850
  const zodInputSchema = triggerSchema ? resolveSerializedZodOutput(jsonSchemaToZod(parse(triggerSchema))) : null;
8676
8851
  const workflowActivePaths = streamResultToUse?.steps ?? {};
8677
8852
  const hasWorkflowActivePaths = Object.values(workflowActivePaths).length > 0;
8678
- const doneStatuses = ["success", "failed", "canceled"];
8853
+ const doneStatuses = ["success", "failed", "canceled", "tripwire"];
8679
8854
  return /* @__PURE__ */ jsxs("div", { className: "h-full pt-3 pb-12 overflow-y-auto", children: [
8680
8855
  /* @__PURE__ */ jsxs("div", { className: "space-y-4 px-5 pb-5 border-b-sm border-border1", children: [
8681
8856
  isSuspendedSteps && isStreamingWorkflow && /* @__PURE__ */ jsxs("div", { className: "py-2 px-5 flex items-center gap-2 bg-surface5 -mx-5 -mt-5 border-b-sm border-border1", children: [
@@ -8765,12 +8940,20 @@ function WorkflowTrigger({
8765
8940
  if (step.status === "success") {
8766
8941
  output = step.output;
8767
8942
  }
8943
+ const tripwireInfo = step.status === "failed" && step.tripwire ? step.tripwire : streamResultToUse?.status === "tripwire" ? {
8944
+ reason: streamResultToUse?.tripwire?.reason,
8945
+ retry: streamResultToUse?.tripwire?.retry,
8946
+ metadata: streamResultToUse?.tripwire?.metadata,
8947
+ processorId: streamResultToUse?.tripwire?.processorId
8948
+ } : void 0;
8949
+ const displayStatus = step.status === "failed" && step.tripwire ? "tripwire" : status;
8768
8950
  return /* @__PURE__ */ jsx(
8769
8951
  WorkflowStatus,
8770
8952
  {
8771
8953
  stepId,
8772
- status,
8773
- result: output ?? suspendOutput ?? {}
8954
+ status: displayStatus,
8955
+ result: output ?? suspendOutput ?? {},
8956
+ tripwire: tripwireInfo
8774
8957
  },
8775
8958
  stepId
8776
8959
  );
@@ -9119,10 +9302,14 @@ const columns$4 = [
9119
9302
  header: "Name",
9120
9303
  cell: ({ row }) => {
9121
9304
  const { Link, paths } = useLinkComponent();
9305
+ const workflow = row.original;
9122
9306
  return /* @__PURE__ */ jsx(
9123
9307
  EntryCell,
9124
9308
  {
9125
- name: /* @__PURE__ */ jsx(Link, { href: paths.workflowLink(row.original.id), children: row.original.name }),
9309
+ name: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
9310
+ /* @__PURE__ */ jsx(Link, { href: paths.workflowLink(row.original.id), children: row.original.name }),
9311
+ workflow.isProcessorWorkflow && /* @__PURE__ */ jsx(Badge, { icon: /* @__PURE__ */ jsx(Cpu, { className: "h-3 w-3" }), className: "!h-badge-sm bg-violet-500/20 text-violet-400", children: "Processor" })
9312
+ ] }),
9126
9313
  description: void 0,
9127
9314
  meta: void 0
9128
9315
  }
@@ -9346,7 +9533,7 @@ const Tab$1 = ({ children, value, onClick }) => {
9346
9533
  );
9347
9534
  };
9348
9535
  const TabContent$1 = ({ children, value }) => {
9349
- return /* @__PURE__ */ jsx(TabsContent, { value, className: "h-full overflow-hidden flex flex-col", children });
9536
+ return /* @__PURE__ */ jsx(TabsContent, { value, className: "h-full overflow-auto flex flex-col", children });
9350
9537
  };
9351
9538
 
9352
9539
  const TracingRunOptions = () => {
@@ -9425,7 +9612,8 @@ function WorkflowInformation({ workflowId, initialRunId }) {
9425
9612
  stepsCount,
9426
9613
  " step",
9427
9614
  stepsCount > 1 ? "s" : ""
9428
- ] })
9615
+ ] }),
9616
+ workflow?.isProcessorWorkflow && /* @__PURE__ */ jsx(Badge, { icon: /* @__PURE__ */ jsx(Cpu, { className: "h-3 w-3" }), className: "bg-violet-500/20 text-violet-400", children: "Processor" })
9429
9617
  ] }) }),
9430
9618
  /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden border-t-sm border-border1 flex flex-col", children: /* @__PURE__ */ jsxs(PlaygroundTabs, { defaultTab: "current-run", value: tab, onValueChange: setTab, children: [
9431
9619
  /* @__PURE__ */ jsxs(TabList$1, { children: [