@shuffleio/shuffle-mcps 0.0.5 → 0.0.7

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.js CHANGED
@@ -1,10 +1,34 @@
1
1
  // ShuffleMCP.tsx
2
2
  import React, { useState as useState8, useEffect as useEffect6, useRef as useRef5, useCallback as useCallback7, useMemo as useMemo4, useImperativeHandle } from "react";
3
3
  import { algoliasearch } from "algoliasearch";
4
+ import { Tooltip as Tooltip4 } from "@mui/material";
4
5
 
5
6
  // AppDetailDrawer.tsx
6
7
  import { useState as useState7, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef4 } from "react";
7
- import { toast as toast3 } from "sonner";
8
+
9
+ // toast.ts
10
+ var defaultImpl = (arg, opts) => {
11
+ const isObj = typeof arg === "object" && arg !== null;
12
+ const title = isObj ? arg.title : arg;
13
+ const description = isObj ? arg.description : opts?.description;
14
+ const variant = (isObj ? arg.variant : void 0) || "default";
15
+ const msg = [title, description].filter(Boolean).join(" \u2014 ");
16
+ if (variant === "destructive" || variant === "error") console.error("[toast]", msg);
17
+ else if (variant === "warning") console.warn("[toast]", msg);
18
+ else console.log("[toast]", msg);
19
+ };
20
+ var _impl = defaultImpl;
21
+ function setToastImpl(fn) {
22
+ _impl = fn;
23
+ }
24
+ var base = ((arg, opts) => _impl(arg, opts));
25
+ base.success = (msg, opts) => _impl({ title: msg, description: opts?.description, variant: "success" }, opts);
26
+ base.error = (msg, opts) => _impl({ title: msg, description: opts?.description, variant: "destructive" }, opts);
27
+ base.info = (msg, opts) => _impl({ title: msg, description: opts?.description, variant: "info" }, opts);
28
+ base.warning = (msg, opts) => _impl({ title: msg, description: opts?.description, variant: "warning" }, opts);
29
+ var toast = base;
30
+
31
+ // AppDetailDrawer.tsx
8
32
  import { Download, Forward } from "lucide-react";
9
33
 
10
34
  // api.ts
@@ -315,7 +339,7 @@ var DATASTORE_CATEGORIES = {
315
339
  import {
316
340
  Box as Box8,
317
341
  Typography as Typography8,
318
- IconButton as IconButton3,
342
+ IconButton as IconButton4,
319
343
  Skeleton,
320
344
  Drawer
321
345
  } from "@mui/material";
@@ -339,6 +363,7 @@ import {
339
363
  CircularProgress
340
364
  } from "@mui/material";
341
365
  import AddIcon from "@mui/icons-material/Add";
366
+ import { Link as RouterLink } from "react-router-dom";
342
367
 
343
368
  // authenticatedApps.ts
344
369
  var TTL_MS = 3e4;
@@ -787,7 +812,7 @@ var IntegrationStatus = ({ collapsed, filterApps, onAddClick, iconSize = 26, onD
787
812
  color: "hsl(var(--muted-foreground))",
788
813
  cursor: "pointer",
789
814
  "&:hover": {
790
- backgroundColor: "hsl(var(--accent))"
815
+ backgroundColor: "hsl(var(--muted))"
791
816
  }
792
817
  },
793
818
  children: [
@@ -808,7 +833,7 @@ var IntegrationStatus = ({ collapsed, filterApps, onAddClick, iconSize = 26, onD
808
833
  color: "hsl(var(--muted-foreground))",
809
834
  cursor: "pointer",
810
835
  "&:hover": {
811
- backgroundColor: "hsl(var(--accent))"
836
+ backgroundColor: "hsl(var(--muted))"
812
837
  }
813
838
  },
814
839
  children: "\u2212"
@@ -836,8 +861,8 @@ var IntegrationStatus = ({ collapsed, filterApps, onAddClick, iconSize = 26, onD
836
861
  IconButton,
837
862
  {
838
863
  size: "small",
839
- component: "a",
840
- href: "/onboarding",
864
+ component: RouterLink,
865
+ to: "/onboarding",
841
866
  sx: {
842
867
  width: 26,
843
868
  height: 26,
@@ -1234,19 +1259,6 @@ import { motion as motion3 } from "framer-motion";
1234
1259
 
1235
1260
  // AppAuthConfig.tsx
1236
1261
  import { useState as useState4, useEffect as useEffect3, useRef } from "react";
1237
-
1238
- // toast.ts
1239
- var _impl = ({ title, description, variant }) => {
1240
- const msg = [title, description].filter(Boolean).join(" \u2014 ");
1241
- if (variant === "destructive") console.error("[toast]", msg);
1242
- else console.log("[toast]", msg);
1243
- };
1244
- function setToastImpl(fn) {
1245
- _impl = fn;
1246
- }
1247
- var toast = (arg) => _impl(arg);
1248
-
1249
- // AppAuthConfig.tsx
1250
1262
  import {
1251
1263
  Box as Box3,
1252
1264
  Typography as Typography3,
@@ -3598,7 +3610,6 @@ function TryMcpSection({ appName, appIcon, appId, categories }) {
3598
3610
 
3599
3611
  // SingulActionsPreview.tsx
3600
3612
  import { useState as useState6, useEffect as useEffect4, useMemo as useMemo2, useCallback as useCallback5, useRef as useRef3 } from "react";
3601
- import { toast as toast2 } from "sonner";
3602
3613
  import {
3603
3614
  Box as Box7,
3604
3615
  Typography as Typography7,
@@ -3606,10 +3617,13 @@ import {
3606
3617
  Button as Button3,
3607
3618
  Autocomplete,
3608
3619
  TextField as TextField2,
3609
- ToggleButton,
3610
- ToggleButtonGroup
3620
+ IconButton as IconButton3,
3621
+ Tooltip as Tooltip3
3611
3622
  } from "@mui/material";
3612
3623
  import PlayArrowIcon from "@mui/icons-material/PlayArrow";
3624
+ import ContentCopyIcon from "@mui/icons-material/ContentCopy";
3625
+ import CheckIcon from "@mui/icons-material/Check";
3626
+ import { Code2, Terminal } from "lucide-react";
3613
3627
  import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
3614
3628
  import { createElement } from "react";
3615
3629
  var ACTION_DEFAULT_FIELDS = {
@@ -3865,14 +3879,16 @@ var SingulActionsPreview = ({
3865
3879
  const handleCopy = async () => {
3866
3880
  try {
3867
3881
  await navigator.clipboard.writeText(snippet);
3868
- toast2.success("Copied snippet");
3882
+ setCopied(true);
3883
+ setTimeout(() => setCopied(false), 2e3);
3869
3884
  } catch {
3870
- toast2.error("Copy failed");
3885
+ toast.error("Copy failed");
3871
3886
  }
3872
3887
  };
3873
3888
  const [playLoading, setPlayLoading] = useState6(false);
3874
3889
  const [playResult, setPlayResult] = useState6(null);
3875
3890
  const responseRef = useRef3(null);
3891
+ const [copied, setCopied] = useState6(false);
3876
3892
  const scrollToResponse = () => {
3877
3893
  requestAnimationFrame(() => {
3878
3894
  responseRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" });
@@ -3927,14 +3943,14 @@ var SingulActionsPreview = ({
3927
3943
  }
3928
3944
  })();
3929
3945
  if (parsed?.success === false) {
3930
- toast2.error(parsed.reason || "Run failed");
3946
+ toast.error(parsed.reason || "Run failed");
3931
3947
  } else {
3932
- toast2.success(`Ran ${selected?.name || lang}`);
3948
+ toast.success(`Ran ${selected?.name || lang}`);
3933
3949
  }
3934
3950
  } catch (err) {
3935
3951
  const msg = err?.message || "Run failed";
3936
3952
  setPlayResult(msg);
3937
- toast2.error(msg);
3953
+ toast.error(msg);
3938
3954
  } finally {
3939
3955
  setPlayLoading(false);
3940
3956
  scrollToResponse();
@@ -3979,86 +3995,54 @@ var SingulActionsPreview = ({
3979
3995
  },
3980
3996
  children: [
3981
3997
  isDisabled ? /* @__PURE__ */ jsx9(Typography7, { sx: { fontSize: "0.75rem", color: "hsl(var(--muted-foreground))", fontStyle: "italic", textAlign: "center", py: 1 }, children: "No category detected for this app" }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
3982
- /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", gap: 1, mb: 1.5, alignItems: "center" }, children: [
3983
- /* @__PURE__ */ jsx9(
3984
- Autocomplete,
3985
- {
3986
- size: "small",
3987
- disableClearable: true,
3988
- options: sortedActions,
3989
- value: selected ?? sortedActions[0],
3990
- onChange: (_, v) => v && handleSelect(v),
3991
- groupBy: (o) => o.category,
3992
- getOptionLabel: (o) => o?.label ?? "",
3993
- isOptionEqualToValue: (a, b) => a?.name === b?.name && a?.category === b?.category,
3994
- renderOption: (props, option) => /* @__PURE__ */ createElement("li", { ...props, key: `${option.category}-${option.name}` }, /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", flexDirection: "column" }, children: [
3995
- /* @__PURE__ */ jsx9(Typography7, { sx: { fontSize: "0.78rem", color: "hsl(var(--foreground))" }, children: option.label }),
3996
- /* @__PURE__ */ jsx9(Typography7, { sx: { fontFamily: "'JetBrains Mono', monospace", fontSize: "0.65rem", color: "hsl(var(--muted-foreground))" }, children: option.name })
3997
- ] })),
3998
- sx: {
3999
- flex: 1,
4000
- "& .MuiOutlinedInput-root": {
3998
+ /* @__PURE__ */ jsx9(Box7, { sx: { display: "flex", gap: 1, mb: 1.5, alignItems: "center" }, children: /* @__PURE__ */ jsx9(
3999
+ Autocomplete,
4000
+ {
4001
+ size: "small",
4002
+ disableClearable: true,
4003
+ options: sortedActions,
4004
+ value: selected ?? sortedActions[0],
4005
+ onChange: (_, v) => v && handleSelect(v),
4006
+ groupBy: (o) => o.category,
4007
+ getOptionLabel: (o) => o?.label ?? "",
4008
+ isOptionEqualToValue: (a, b) => a?.name === b?.name && a?.category === b?.category,
4009
+ renderOption: (props, option) => /* @__PURE__ */ createElement("li", { ...props, key: `${option.category}-${option.name}` }, /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", flexDirection: "column" }, children: [
4010
+ /* @__PURE__ */ jsx9(Typography7, { sx: { fontSize: "0.78rem", color: "hsl(var(--foreground))" }, children: option.label }),
4011
+ /* @__PURE__ */ jsx9(Typography7, { sx: { fontFamily: "'JetBrains Mono', monospace", fontSize: "0.65rem", color: "hsl(var(--muted-foreground))" }, children: option.name })
4012
+ ] })),
4013
+ sx: {
4014
+ flex: 1,
4015
+ "& .MuiOutlinedInput-root": {
4016
+ backgroundColor: "hsl(var(--card))",
4017
+ fontFamily: "'JetBrains Mono', monospace",
4018
+ fontSize: "0.75rem",
4019
+ color: "hsl(var(--foreground))",
4020
+ "& fieldset": { borderColor: "hsl(var(--border))" },
4021
+ "&:hover fieldset": { borderColor: "hsl(var(--primary))" },
4022
+ "&.Mui-focused fieldset": { borderColor: "hsl(var(--primary))" }
4023
+ }
4024
+ },
4025
+ slotProps: {
4026
+ paper: {
4027
+ sx: {
4001
4028
  backgroundColor: "hsl(var(--card))",
4002
- fontFamily: "'JetBrains Mono', monospace",
4003
- fontSize: "0.75rem",
4004
4029
  color: "hsl(var(--foreground))",
4005
- "& fieldset": { borderColor: "hsl(var(--border))" },
4006
- "&:hover fieldset": { borderColor: "hsl(var(--primary))" },
4007
- "&.Mui-focused fieldset": { borderColor: "hsl(var(--primary))" }
4008
- }
4009
- },
4010
- slotProps: {
4011
- paper: {
4012
- sx: {
4013
- backgroundColor: "hsl(var(--card))",
4014
- color: "hsl(var(--foreground))",
4015
- border: "1px solid hsl(var(--border))",
4016
- "& .MuiAutocomplete-groupLabel": {
4017
- backgroundColor: "hsl(var(--muted) / 0.6)",
4018
- color: "hsl(var(--muted-foreground))",
4019
- fontSize: "0.65rem",
4020
- fontWeight: 600,
4021
- textTransform: "uppercase",
4022
- letterSpacing: 0.6,
4023
- lineHeight: "24px"
4024
- }
4025
- }
4026
- }
4027
- },
4028
- renderInput: (params) => /* @__PURE__ */ jsx9(TextField2, { ...params, placeholder: "Select action" })
4029
- }
4030
- ),
4031
- /* @__PURE__ */ jsxs7(
4032
- ToggleButtonGroup,
4033
- {
4034
- size: "small",
4035
- exclusive: true,
4036
- value: lang,
4037
- onChange: (_, v) => v && setLang(v),
4038
- sx: {
4039
- "& .MuiToggleButton-root": {
4040
- height: 36,
4041
- px: 1.5,
4042
- fontSize: "0.7rem",
4043
- textTransform: "none",
4044
- fontFamily: "'JetBrains Mono', monospace",
4045
- color: "hsl(var(--muted-foreground))",
4046
4030
  border: "1px solid hsl(var(--border))",
4047
- "&.Mui-selected": {
4048
- backgroundColor: "hsl(var(--primary) / 0.15)",
4049
- color: "hsl(var(--primary))",
4050
- borderColor: "hsl(var(--primary))",
4051
- "&:hover": { backgroundColor: "hsl(var(--primary) / 0.2)" }
4031
+ "& .MuiAutocomplete-groupLabel": {
4032
+ backgroundColor: "hsl(var(--muted) / 0.6)",
4033
+ color: "hsl(var(--muted-foreground))",
4034
+ fontSize: "0.65rem",
4035
+ fontWeight: 600,
4036
+ textTransform: "uppercase",
4037
+ letterSpacing: 0.6,
4038
+ lineHeight: "24px"
4052
4039
  }
4053
4040
  }
4054
- },
4055
- children: [
4056
- /* @__PURE__ */ jsx9(ToggleButton, { value: "curl", children: "curl" }),
4057
- /* @__PURE__ */ jsx9(ToggleButton, { value: "python", children: "python" })
4058
- ]
4059
- }
4060
- )
4061
- ] }),
4041
+ }
4042
+ },
4043
+ renderInput: (params) => /* @__PURE__ */ jsx9(TextField2, { ...params, placeholder: "Select action" })
4044
+ }
4045
+ ) }),
4062
4046
  /* @__PURE__ */ jsxs7(
4063
4047
  Box7,
4064
4048
  {
@@ -4077,82 +4061,95 @@ var SingulActionsPreview = ({
4077
4061
  sx: {
4078
4062
  display: "flex",
4079
4063
  alignItems: "center",
4080
- justifyContent: "space-between",
4081
- px: 1.25,
4082
- py: 0.75,
4064
+ gap: 1,
4065
+ px: 2,
4066
+ py: 1,
4083
4067
  borderBottom: "1px solid hsl(var(--border))",
4084
- backgroundColor: "hsl(var(--muted) / 0.4)"
4068
+ backgroundColor: "hsl(var(--card))"
4085
4069
  },
4086
4070
  children: [
4087
- /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", alignItems: "center", gap: 0.75 }, children: [
4088
- /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", gap: 0.4 }, children: [
4089
- /* @__PURE__ */ jsx9(Box7, { sx: { width: 8, height: 8, borderRadius: "50%", backgroundColor: "hsl(0 70% 60% / 0.6)" } }),
4090
- /* @__PURE__ */ jsx9(Box7, { sx: { width: 8, height: 8, borderRadius: "50%", backgroundColor: "hsl(40 80% 60% / 0.6)" } }),
4091
- /* @__PURE__ */ jsx9(Box7, { sx: { width: 8, height: 8, borderRadius: "50%", backgroundColor: "hsl(140 60% 55% / 0.6)" } })
4092
- ] }),
4093
- /* @__PURE__ */ jsxs7(
4094
- Typography7,
4095
- {
4096
- sx: {
4097
- ml: 1,
4098
- fontFamily: "'JetBrains Mono', monospace",
4099
- fontSize: "0.65rem",
4100
- color: "hsl(var(--muted-foreground))",
4101
- letterSpacing: 0.4
4102
- },
4103
- children: [
4104
- lang === "python" ? "singul.py" : "request.sh",
4105
- selected ? ` \xB7 ${selected.name}` : ""
4106
- ]
4107
- }
4108
- )
4109
- ] }),
4110
- /* @__PURE__ */ jsxs7(Box7, { sx: { display: "flex", gap: 0.75 }, children: [
4111
- /* @__PURE__ */ jsx9(
4112
- Button3,
4113
- {
4114
- size: "small",
4115
- onClick: handleCopy,
4116
- sx: {
4117
- height: 26,
4118
- minWidth: 0,
4119
- px: 1.25,
4120
- fontSize: "0.65rem",
4121
- textTransform: "none",
4122
- color: "hsl(var(--muted-foreground))",
4123
- backgroundColor: "hsl(var(--card))",
4124
- border: "1px solid hsl(var(--border))",
4125
- "&:hover": { backgroundColor: "hsl(var(--muted))", color: "hsl(var(--foreground))" }
4126
- },
4127
- children: "Copy"
4071
+ /* @__PURE__ */ jsx9(Code2, { size: 14, style: { color: "hsl(var(--muted-foreground))" } }),
4072
+ /* @__PURE__ */ jsx9(
4073
+ Typography7,
4074
+ {
4075
+ sx: {
4076
+ fontSize: "0.7rem",
4077
+ fontWeight: 600,
4078
+ color: "hsl(var(--muted-foreground))",
4079
+ textTransform: "uppercase",
4080
+ letterSpacing: "0.05em"
4081
+ },
4082
+ children: "Action"
4083
+ }
4084
+ ),
4085
+ selected && /* @__PURE__ */ jsx9(
4086
+ Chip4,
4087
+ {
4088
+ label: selected.name,
4089
+ size: "small",
4090
+ sx: {
4091
+ height: 18,
4092
+ fontSize: "0.6rem",
4093
+ fontWeight: 700,
4094
+ fontFamily: "'JetBrains Mono', monospace",
4095
+ bgcolor: "hsla(var(--severity-medium) / 0.15)",
4096
+ color: "hsl(var(--severity-medium))",
4097
+ "& .MuiChip-label": { px: 0.75 }
4128
4098
  }
4129
- ),
4130
- /* @__PURE__ */ jsx9(
4131
- Button3,
4132
- {
4133
- size: "small",
4134
- onClick: handlePlay,
4135
- disabled: playLoading,
4136
- startIcon: !playLoading && /* @__PURE__ */ jsx9(PlayArrowIcon, { sx: { fontSize: 14 } }),
4137
- sx: {
4138
- height: 26,
4139
- minWidth: 0,
4140
- px: 1.5,
4141
- fontSize: "0.65rem",
4142
- fontWeight: 600,
4143
- textTransform: "none",
4144
- color: "hsl(var(--primary-foreground))",
4145
- backgroundColor: "hsl(var(--primary))",
4146
- border: "1px solid hsl(var(--primary))",
4147
- boxShadow: "0 0 12px -2px hsl(var(--primary) / 0.6)",
4148
- "& .MuiButton-startIcon": { mr: 0.5 },
4149
- "&:hover": { backgroundColor: "hsl(var(--primary) / 0.9)", boxShadow: "0 0 16px -2px hsl(var(--primary) / 0.7)" },
4150
- "&.Mui-disabled": { color: "hsl(var(--primary-foreground) / 0.7)", backgroundColor: "hsl(var(--primary) / 0.45)", boxShadow: "none", borderColor: "hsl(var(--primary) / 0.45)" }
4099
+ }
4100
+ ),
4101
+ /* @__PURE__ */ jsx9(Box7, { sx: { flex: 1 } }),
4102
+ /* @__PURE__ */ jsx9(Box7, { sx: { display: "flex", gap: 0.5 }, children: ["curl", "python"].map((m) => /* @__PURE__ */ jsx9(
4103
+ Chip4,
4104
+ {
4105
+ label: m === "curl" ? "cURL" : "Python",
4106
+ icon: m === "curl" ? /* @__PURE__ */ jsx9(Terminal, { size: 12 }) : /* @__PURE__ */ jsx9(Code2, { size: 12 }),
4107
+ size: "small",
4108
+ onClick: () => setLang(m),
4109
+ sx: {
4110
+ height: 22,
4111
+ fontSize: "0.6rem",
4112
+ fontWeight: 600,
4113
+ cursor: "pointer",
4114
+ bgcolor: lang === m ? "hsl(var(--primary) / 0.12)" : "transparent",
4115
+ color: lang === m ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))",
4116
+ border: lang === m ? "1px solid hsl(var(--primary) / 0.3)" : "1px solid transparent",
4117
+ "& .MuiChip-icon": {
4118
+ color: lang === m ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))"
4151
4119
  },
4152
- children: playLoading ? "Running\u2026" : "Play"
4120
+ "&:hover": {
4121
+ bgcolor: lang === m ? "hsl(var(--primary) / 0.15)" : "hsl(var(--muted))"
4122
+ }
4153
4123
  }
4154
- )
4155
- ] })
4124
+ },
4125
+ m
4126
+ )) }),
4127
+ /* @__PURE__ */ jsx9(Tooltip3, { title: copied ? "Copied!" : "Copy", arrow: true, children: /* @__PURE__ */ jsx9(IconButton3, { size: "small", onClick: handleCopy, sx: { color: "hsl(var(--muted-foreground))" }, children: copied ? /* @__PURE__ */ jsx9(CheckIcon, { sx: { fontSize: 14 } }) : /* @__PURE__ */ jsx9(ContentCopyIcon, { sx: { fontSize: 14 } }) }) }),
4128
+ /* @__PURE__ */ jsx9(
4129
+ Button3,
4130
+ {
4131
+ size: "small",
4132
+ onClick: handlePlay,
4133
+ disabled: playLoading,
4134
+ startIcon: !playLoading && /* @__PURE__ */ jsx9(PlayArrowIcon, { sx: { fontSize: 14 } }),
4135
+ sx: {
4136
+ height: 26,
4137
+ minWidth: 0,
4138
+ px: 1.5,
4139
+ fontSize: "0.65rem",
4140
+ fontWeight: 600,
4141
+ textTransform: "none",
4142
+ color: "hsl(var(--primary-foreground))",
4143
+ backgroundColor: "hsl(var(--primary))",
4144
+ border: "1px solid hsl(var(--primary))",
4145
+ boxShadow: "0 0 12px -2px hsl(var(--primary) / 0.6)",
4146
+ "& .MuiButton-startIcon": { mr: 0.5 },
4147
+ "&:hover": { backgroundColor: "hsl(var(--primary) / 0.9)", boxShadow: "0 0 16px -2px hsl(var(--primary) / 0.7)" },
4148
+ "&.Mui-disabled": { color: "hsl(var(--primary-foreground) / 0.7)", backgroundColor: "hsl(var(--primary) / 0.45)", boxShadow: "none", borderColor: "hsl(var(--primary) / 0.45)" }
4149
+ },
4150
+ children: playLoading ? "Running\u2026" : "Play"
4151
+ }
4152
+ )
4156
4153
  ]
4157
4154
  }
4158
4155
  ),
@@ -4277,6 +4274,7 @@ function AppDetailDrawer({
4277
4274
  open,
4278
4275
  onClose,
4279
4276
  appName,
4277
+ appId,
4280
4278
  anchor = "right",
4281
4279
  width = 520,
4282
4280
  onRefresh,
@@ -4307,33 +4305,35 @@ function AppDetailDrawer({
4307
4305
  setAppLoading(true);
4308
4306
  setAppInfo(null);
4309
4307
  setIsActivated(null);
4310
- setResolvedAlgoliaId(null);
4308
+ setResolvedAlgoliaId(appId || null);
4311
4309
  refreshAuth();
4312
4310
  const normalizedName = appName.toLowerCase().replace(/[\s_\-]+/g, "_");
4313
4311
  const searchName = appName.replace(/_/g, " ");
4314
4312
  (async () => {
4315
- let algoliaId = null;
4316
- try {
4317
- const { algoliasearch: algoliasearch2 } = await import("algoliasearch");
4318
- const client = algoliasearch2("JNSS5CFDZZ", "33e4e3564f4f060e96e0531957bed552");
4319
- const res = await client.search({
4320
- requests: [{ indexName: "appsearch", query: searchName, hitsPerPage: 10 }]
4321
- });
4322
- const hits = res?.results?.[0]?.hits || [];
4323
- const match = hits.find(
4324
- (h) => h.name?.toLowerCase().replace(/[\s_\-]+/g, "_") === normalizedName
4325
- ) || (hits.length > 0 ? hits[0] : null);
4326
- if (match) {
4327
- algoliaId = match.objectID;
4328
- setResolvedAlgoliaId(algoliaId);
4329
- setAppInfo({
4330
- name: match.name || searchName,
4331
- description: match.description || "",
4332
- large_image: match.image_url || "",
4333
- categories: match.categories || []
4313
+ let algoliaId = appId || null;
4314
+ if (!algoliaId) {
4315
+ try {
4316
+ const { algoliasearch: algoliasearch2 } = await import("algoliasearch");
4317
+ const client = algoliasearch2("JNSS5CFDZZ", "33e4e3564f4f060e96e0531957bed552");
4318
+ const res = await client.search({
4319
+ requests: [{ indexName: "appsearch", query: searchName, hitsPerPage: 10 }]
4334
4320
  });
4321
+ const hits = res?.results?.[0]?.hits || [];
4322
+ const match = hits.find(
4323
+ (h) => h.name?.toLowerCase().replace(/[\s_\-]+/g, "_") === normalizedName
4324
+ ) || (hits.length > 0 ? hits[0] : null);
4325
+ if (match) {
4326
+ algoliaId = match.objectID;
4327
+ setResolvedAlgoliaId(algoliaId);
4328
+ setAppInfo({
4329
+ name: match.name || searchName,
4330
+ description: match.description || "",
4331
+ large_image: match.image_url || "",
4332
+ categories: match.categories || []
4333
+ });
4334
+ }
4335
+ } catch {
4335
4336
  }
4336
- } catch {
4337
4337
  }
4338
4338
  let appsList = null;
4339
4339
  if (API_CONFIG.apiKey) {
@@ -4397,7 +4397,7 @@ function AppDetailDrawer({
4397
4397
  });
4398
4398
  setAppLoading(false);
4399
4399
  })();
4400
- }, [open, appName]);
4400
+ }, [open, appName, appId]);
4401
4401
  useEffect5(() => {
4402
4402
  if (!open || !appName || !isAuthenticated) {
4403
4403
  setIncidentStats(null);
@@ -4489,22 +4489,22 @@ function AppDetailDrawer({
4489
4489
  });
4490
4490
  if (!res.ok) throw new Error("Deactivate failed");
4491
4491
  setActivatedAppId(null);
4492
- toast3.success(`${displayName} deactivated`);
4492
+ toast.success(`${displayName} deactivated`);
4493
4493
  } else {
4494
- const appId = resolvedAlgoliaId;
4495
- if (!appId) throw new Error("App ID not resolved yet");
4496
- const activateRes = await fetch(getApiUrl(`/api/v1/apps/${appId}/activate`), {
4494
+ const appId2 = resolvedAlgoliaId;
4495
+ if (!appId2) throw new Error("App ID not resolved yet");
4496
+ const activateRes = await fetch(getApiUrl(`/api/v1/apps/${appId2}/activate`), {
4497
4497
  method: "GET",
4498
4498
  credentials: "include",
4499
4499
  headers: { ...getAuthHeader() }
4500
4500
  });
4501
4501
  if (!activateRes.ok) throw new Error(`Activate failed (${activateRes.status})`);
4502
- setActivatedAppId(appId);
4503
- toast3.success(`${displayName} activated`);
4502
+ setActivatedAppId(appId2);
4503
+ toast.success(`${displayName} activated`);
4504
4504
  }
4505
4505
  } catch (err) {
4506
4506
  console.error("[Activate] Error:", err);
4507
- toast3.error(err?.message || "Activation failed");
4507
+ toast.error(err?.message || "Activation failed");
4508
4508
  setIsActivated(wasActivated);
4509
4509
  setActivatedAppId(prevAppId);
4510
4510
  } finally {
@@ -4546,7 +4546,7 @@ function AppDetailDrawer({
4546
4546
  /* @__PURE__ */ jsx10(Typography8, { sx: { color: "hsl(var(--muted-foreground))", fontSize: "0.75rem" }, children: "App configuration" })
4547
4547
  ] }),
4548
4548
  /* @__PURE__ */ jsx10(
4549
- IconButton3,
4549
+ IconButton4,
4550
4550
  {
4551
4551
  component: "a",
4552
4552
  href: `/apps/${encodeURIComponent(appName || "")}`,
@@ -4556,7 +4556,7 @@ function AppDetailDrawer({
4556
4556
  }
4557
4557
  ),
4558
4558
  /* @__PURE__ */ jsx10(
4559
- IconButton3,
4559
+ IconButton4,
4560
4560
  {
4561
4561
  size: "small",
4562
4562
  onClick: handleClose,
@@ -4632,8 +4632,8 @@ function AppDetailDrawer({
4632
4632
  isAuthenticated,
4633
4633
  matchingEntries,
4634
4634
  onAuthChange: handleAuthChange,
4635
- onTestConnection: (appId, authId) => handleTestConnection(appName || appId, authId),
4636
- onSaveAuth: (appId, creds) => handleSaveAuth(appId, creds, appName || void 0),
4635
+ onTestConnection: (appId2, authId) => handleTestConnection(appName || appId2, authId),
4636
+ onSaveAuth: (appId2, creds) => handleSaveAuth(appId2, creds, appName || void 0),
4637
4637
  onRefreshAuth: refreshAuth
4638
4638
  }
4639
4639
  ),
@@ -4965,6 +4965,10 @@ var ShuffleMCP = React.forwardRef(({
4965
4965
  merged = results;
4966
4966
  } else if (sourceFilter === "private") {
4967
4967
  merged = filteredPrivateApps;
4968
+ } else if (sourceFilter === "authenticated") {
4969
+ const privateNames = new Set(filteredPrivateApps.map((a) => norm2(a.name)));
4970
+ const publicOnly = results.filter((a) => !privateNames.has(norm2(a.name)));
4971
+ merged = [...filteredPrivateApps, ...publicOnly].filter(isAppConfigured);
4968
4972
  } else {
4969
4973
  const privateNames = new Set(filteredPrivateApps.map((a) => norm2(a.name)));
4970
4974
  const publicOnly = results.filter((a) => !privateNames.has(norm2(a.name)));
@@ -4973,7 +4977,7 @@ var ShuffleMCP = React.forwardRef(({
4973
4977
  if (!pinnedApps || pinnedApps.length === 0) return merged;
4974
4978
  const pinnedNames = new Set(pinnedApps.map((a) => norm2(a.name)));
4975
4979
  return [...pinnedApps, ...merged.filter((a) => !pinnedNames.has(norm2(a.name)))];
4976
- }, [pinnedApps, results, filteredPrivateApps, sourceFilter]);
4980
+ }, [pinnedApps, results, filteredPrivateApps, sourceFilter, isAppConfigured]);
4977
4981
  const getGridColumnsStyle = useMemo4(() => {
4978
4982
  if (layout !== "grid") return {};
4979
4983
  const cols = typeof gridColumns === "number" ? gridColumns : gridColumns.md || 3;
@@ -5024,7 +5028,18 @@ var ShuffleMCP = React.forwardRef(({
5024
5028
  /* @__PURE__ */ jsxs9("div", { className: "singul-app-details", style: customStyles.appDetails, children: [
5025
5029
  /* @__PURE__ */ jsxs9("span", { className: "singul-app-name", style: customStyles.appName, children: [
5026
5030
  app.name.replace(/_/g, " "),
5027
- app.source === "private" && /* @__PURE__ */ jsx11("span", { className: "singul-private-badge", title: "From your private apps", children: "Private" })
5031
+ app.source === "private" && /* @__PURE__ */ jsx11(
5032
+ Tooltip4,
5033
+ {
5034
+ title: "Private apps are apps you have activated in your organization, or your own custom apps \u2014 not just from the public Algolia catalog.",
5035
+ arrow: true,
5036
+ enterDelay: 100,
5037
+ enterNextDelay: 100,
5038
+ placement: "top",
5039
+ slotProps: { popper: { style: { zIndex: 1e4 } } },
5040
+ children: /* @__PURE__ */ jsx11("span", { className: "singul-private-badge", children: "Private" })
5041
+ }
5042
+ )
5028
5043
  ] }),
5029
5044
  showDescription && app.description && /* @__PURE__ */ jsx11("span", { className: "singul-app-description", style: customStyles.appDescription, children: app.description }),
5030
5045
  showCategories && app.categories?.[0] && /* @__PURE__ */ jsx11("span", { className: "singul-app-category", style: customStyles.appCategory, children: app.categories[0] })
@@ -5077,21 +5092,33 @@ var ShuffleMCP = React.forwardRef(({
5077
5092
  isLoading && /* @__PURE__ */ jsx11("div", { className: "singul-loading-spinner", style: customStyles.loadingSpinner, children: renderLoadingState ? renderLoadingState() : /* @__PURE__ */ jsx11("div", { className: "singul-spinner", style: customStyles.spinner }) })
5078
5093
  ] }),
5079
5094
  showSourceFilter && privateApps.length > 0 && /* @__PURE__ */ jsx11("div", { className: "singul-source-filter", role: "tablist", "aria-label": "Filter by app source", children: [
5080
- { key: "all", label: "All", count: results.length + filteredPrivateApps.length },
5081
- { key: "public", label: "Public", count: results.length },
5082
- { key: "private", label: "Private", count: filteredPrivateApps.length }
5083
- ].map((opt) => /* @__PURE__ */ jsxs9(
5084
- "button",
5095
+ { key: "all", label: "All", count: results.length + filteredPrivateApps.length, title: "All available apps \u2014 both the public catalog and your private apps." },
5096
+ { key: "public", label: "Public", count: results.length, title: "Public apps from the Shuffle catalog (powered by Algolia)." },
5097
+ { key: "private", label: "Private", count: filteredPrivateApps.length, title: "Private apps are apps you have activated in your organization, or your own custom apps \u2014 not just from the public Algolia catalog." },
5098
+ { key: "authenticated", label: "Authenticated", count: [...filteredPrivateApps, ...results].filter((a, i, arr) => arr.findIndex((x) => x.name?.toLowerCase() === a.name?.toLowerCase()) === i).filter(isAppConfigured).length, title: "Apps you have authenticated and that are ready to use." }
5099
+ ].map((opt) => /* @__PURE__ */ jsx11(
5100
+ Tooltip4,
5085
5101
  {
5086
- type: "button",
5087
- role: "tab",
5088
- "aria-selected": sourceFilter === opt.key,
5089
- className: `singul-source-pill ${sourceFilter === opt.key ? "singul-source-pill-active" : ""}`,
5090
- onClick: () => setSourceFilter(opt.key),
5091
- children: [
5092
- opt.label,
5093
- /* @__PURE__ */ jsx11("span", { className: "singul-source-count", children: opt.count })
5094
- ]
5102
+ title: opt.title,
5103
+ arrow: true,
5104
+ enterDelay: 100,
5105
+ enterNextDelay: 100,
5106
+ placement: "top",
5107
+ slotProps: { popper: { style: { zIndex: 1e4 } } },
5108
+ children: /* @__PURE__ */ jsx11("span", { style: { display: "inline-flex" }, children: /* @__PURE__ */ jsxs9(
5109
+ "button",
5110
+ {
5111
+ type: "button",
5112
+ role: "tab",
5113
+ "aria-selected": sourceFilter === opt.key,
5114
+ className: `singul-source-pill ${sourceFilter === opt.key ? "singul-source-pill-active" : ""}`,
5115
+ onClick: () => setSourceFilter(opt.key),
5116
+ children: [
5117
+ opt.label,
5118
+ /* @__PURE__ */ jsx11("span", { className: "singul-source-count", children: opt.count })
5119
+ ]
5120
+ }
5121
+ ) })
5095
5122
  },
5096
5123
  opt.key
5097
5124
  )) }),
@@ -5157,7 +5184,7 @@ var ShuffleMCP_default = ShuffleMCP;
5157
5184
 
5158
5185
  // AppSearchDrawer.tsx
5159
5186
  import { useState as useState9 } from "react";
5160
- import { Box as Box10, Typography as Typography10, IconButton as IconButton4, Drawer as Drawer2, Avatar as Avatar5, Tooltip as Tooltip3 } from "@mui/material";
5187
+ import { Box as Box10, Typography as Typography10, IconButton as IconButton5, Drawer as Drawer2, Avatar as Avatar5, Tooltip as Tooltip5 } from "@mui/material";
5161
5188
  import CloseIcon3 from "@mui/icons-material/Close";
5162
5189
  import { motion as motion7, AnimatePresence as AnimatePresence2 } from "framer-motion";
5163
5190
 
@@ -5325,16 +5352,19 @@ function AppSearchDrawer({
5325
5352
  pinnedApps
5326
5353
  }) {
5327
5354
  const [detailAppName, setDetailAppName] = useState9(null);
5355
+ const [detailAppId, setDetailAppId] = useState9(null);
5328
5356
  const handleClose = () => {
5329
5357
  setDetailAppName(null);
5358
+ setDetailAppId(null);
5330
5359
  onClose();
5331
5360
  };
5332
5361
  const handleAppSelected = (detail) => {
5362
+ const algoliaId = detail.app.objectID || null;
5333
5363
  const appInfo = {
5334
5364
  name: detail.app.name,
5335
5365
  icon: detail.app.image_url || "",
5336
5366
  categories: detail.app.categories || [],
5337
- id: detail.app.objectID || null
5367
+ id: algoliaId
5338
5368
  };
5339
5369
  if (onQuickSelect) {
5340
5370
  onQuickSelect(appInfo);
@@ -5345,6 +5375,7 @@ function AppSearchDrawer({
5345
5375
  return;
5346
5376
  }
5347
5377
  setDetailAppName(detail.app.name);
5378
+ setDetailAppId(algoliaId);
5348
5379
  };
5349
5380
  return /* @__PURE__ */ jsxs11(Fragment6, { children: [
5350
5381
  /* @__PURE__ */ jsxs11(
@@ -5358,6 +5389,10 @@ function AppSearchDrawer({
5358
5389
  "& .MuiDrawer-paper": {
5359
5390
  width,
5360
5391
  maxWidth: "100vw",
5392
+ height: "100vh",
5393
+ display: "flex",
5394
+ flexDirection: "column",
5395
+ overflow: "hidden",
5361
5396
  background: "linear-gradient(180deg, hsl(var(--card)) 0%, hsl(var(--background)) 100%)",
5362
5397
  borderLeft: anchor === "right" ? "1px solid hsl(var(--border))" : "none",
5363
5398
  borderRight: anchor === "left" ? "1px solid hsl(var(--border))" : "none"
@@ -5382,7 +5417,7 @@ function AppSearchDrawer({
5382
5417
  /* @__PURE__ */ jsx13(Typography10, { sx: { color: "hsl(var(--muted-foreground))", fontSize: "0.75rem" }, children: subtitle })
5383
5418
  ] }),
5384
5419
  /* @__PURE__ */ jsx13(
5385
- IconButton4,
5420
+ IconButton5,
5386
5421
  {
5387
5422
  size: "small",
5388
5423
  onClick: handleClose,
@@ -5393,12 +5428,12 @@ function AppSearchDrawer({
5393
5428
  ]
5394
5429
  }
5395
5430
  ),
5396
- /* @__PURE__ */ jsxs11(Box10, { sx: { flex: 1, overflowY: "auto", p: 3, minHeight: "92vh" }, children: [
5431
+ /* @__PURE__ */ jsxs11(Box10, { sx: { flex: 1, boxSizing: "border-box", overflow: "hidden", p: 3, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
5397
5432
  showPipelinesBanner && /* @__PURE__ */ jsx13(ShufflePipelinesBanner, {}),
5398
5433
  API_CONFIG.apiKey && /* @__PURE__ */ jsx13(Box10, { sx: { mb: 2.5 }, children: /* @__PURE__ */ jsx13(IntegrationStatus, { collapsed: false, showAll: true, hideAddButton: true, priorityCategory }) }),
5399
5434
  connectionPathApps && connectionPathApps.length > 0 && /* @__PURE__ */ jsxs11(Box10, { sx: { mb: 2.5 }, children: [
5400
5435
  /* @__PURE__ */ jsx13(Typography10, { sx: { color: "hsl(var(--muted-foreground))", fontSize: "0.7rem", fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.05em", mb: 1 }, children: "In this usecase" }),
5401
- /* @__PURE__ */ jsx13(Box10, { sx: { display: "flex", gap: 1.5, flexWrap: "wrap" }, children: connectionPathApps.map((app) => /* @__PURE__ */ jsx13(Tooltip3, { title: app.name.replace(/_/g, " "), arrow: true, placement: "bottom", children: /* @__PURE__ */ jsxs11(
5436
+ /* @__PURE__ */ jsx13(Box10, { sx: { display: "flex", gap: 1.5, flexWrap: "wrap" }, children: connectionPathApps.map((app) => /* @__PURE__ */ jsx13(Tooltip5, { title: app.name.replace(/_/g, " "), arrow: true, placement: "bottom", children: /* @__PURE__ */ jsxs11(
5402
5437
  Box10,
5403
5438
  {
5404
5439
  onClick: () => handleAppSelected({ app: { name: app.name, image_url: app.icon, categories: [] } }),
@@ -5437,55 +5472,99 @@ function AppSearchDrawer({
5437
5472
  }
5438
5473
  ) }, app.name)) })
5439
5474
  ] }),
5440
- /* @__PURE__ */ jsx13(AnimatePresence2, { mode: "wait", children: /* @__PURE__ */ jsx13(
5441
- motion7.div,
5475
+ /* @__PURE__ */ jsx13(
5476
+ Box10,
5442
5477
  {
5443
- initial: { opacity: 0, x: -20 },
5444
- animate: { opacity: 1, x: 0 },
5445
- exit: { opacity: 0, x: -20 },
5446
- transition: { duration: 0.2 },
5447
- children: /* @__PURE__ */ jsx13(
5448
- ShuffleMCP,
5449
- {
5450
- apiKey: API_CONFIG.apiKey || void 0,
5451
- apiBaseUrl: API_CONFIG.baseUrl,
5452
- placeholder: initialQuery ? `Search ${initialQuery} integrations...` : "Search integrations...",
5453
- layout: "grid",
5454
- gridColumns: 2,
5455
- inline: true,
5456
- initialFilterQuery: initialQuery,
5457
- hitsPerPage: 12,
5458
- showDescription: false,
5459
- showCategories: true,
5460
- showCheckbox: false,
5461
- multiSelect: false,
5462
- preventDefault: true,
5463
- onAppSelected: handleAppSelected,
5464
- pinnedApps: pinnedApps?.map((p) => ({
5465
- name: p.name,
5466
- image_url: p.image_url,
5467
- categories: p.categories || [],
5468
- objectID: p.objectID || `pinned-${p.name}`,
5469
- description: "",
5470
- creator: "",
5471
- app_version: "1.0.0",
5472
- time_edited: 0,
5473
- generated: false,
5474
- invalid: false,
5475
- priority: 0,
5476
- actions: 0,
5477
- tags: [],
5478
- accessible_by: [],
5479
- action_labels: [],
5480
- triggers: [],
5481
- verified: true
5482
- })),
5483
- customStyles: singulStyles
5478
+ sx: {
5479
+ flex: 1,
5480
+ minHeight: 0,
5481
+ overflow: "hidden",
5482
+ "& .singul-container, & .singul-search-bar-container": {
5483
+ height: "100%",
5484
+ minHeight: 0
5485
+ },
5486
+ "& .singul-search-bar-container": {
5487
+ display: "flex",
5488
+ flexDirection: "column"
5489
+ },
5490
+ "& .singul-results-container": {
5491
+ flex: 1,
5492
+ minHeight: 0,
5493
+ maxHeight: "none",
5494
+ overflowY: "auto"
5495
+ },
5496
+ "& .singul-results-grid": {
5497
+ gridAutoRows: "1fr",
5498
+ gap: "12px"
5499
+ },
5500
+ "& .singul-results-grid .singul-dropdown-item": {
5501
+ minHeight: 75,
5502
+ padding: "14px 16px",
5503
+ alignItems: "center"
5504
+ },
5505
+ "& .singul-results-grid .singul-app-info": {
5506
+ alignItems: "center",
5507
+ gap: "12px"
5508
+ },
5509
+ "& .singul-results-grid .singul-app-icon": {
5510
+ width: 40,
5511
+ height: 40,
5512
+ borderRadius: 8,
5513
+ padding: 4
5484
5514
  }
5485
- )
5486
- },
5487
- "search"
5488
- ) })
5515
+ },
5516
+ children: /* @__PURE__ */ jsx13(AnimatePresence2, { mode: "wait", children: /* @__PURE__ */ jsx13(
5517
+ motion7.div,
5518
+ {
5519
+ initial: { opacity: 0, x: -20 },
5520
+ animate: { opacity: 1, x: 0 },
5521
+ exit: { opacity: 0, x: -20 },
5522
+ transition: { duration: 0.2 },
5523
+ style: { height: "100%", minHeight: 0 },
5524
+ children: /* @__PURE__ */ jsx13(
5525
+ ShuffleMCP,
5526
+ {
5527
+ apiKey: API_CONFIG.apiKey || void 0,
5528
+ apiBaseUrl: API_CONFIG.baseUrl,
5529
+ placeholder: initialQuery ? `Search ${initialQuery} integrations...` : "Search integrations...",
5530
+ layout: "grid",
5531
+ gridColumns: 2,
5532
+ inline: true,
5533
+ initialFilterQuery: initialQuery,
5534
+ hitsPerPage: 12,
5535
+ showDescription: false,
5536
+ showCategories: true,
5537
+ showCheckbox: false,
5538
+ multiSelect: false,
5539
+ preventDefault: true,
5540
+ onAppSelected: handleAppSelected,
5541
+ pinnedApps: pinnedApps?.map((p) => ({
5542
+ name: p.name,
5543
+ image_url: p.image_url,
5544
+ categories: p.categories || [],
5545
+ objectID: p.objectID || `pinned-${p.name}`,
5546
+ description: "",
5547
+ creator: "",
5548
+ app_version: "1.0.0",
5549
+ time_edited: 0,
5550
+ generated: false,
5551
+ invalid: false,
5552
+ priority: 0,
5553
+ actions: 0,
5554
+ tags: [],
5555
+ accessible_by: [],
5556
+ action_labels: [],
5557
+ triggers: [],
5558
+ verified: true
5559
+ })),
5560
+ customStyles: singulStyles
5561
+ }
5562
+ )
5563
+ },
5564
+ "search"
5565
+ ) })
5566
+ }
5567
+ )
5489
5568
  ] })
5490
5569
  ]
5491
5570
  }
@@ -5497,9 +5576,11 @@ function AppSearchDrawer({
5497
5576
  onClose: () => {
5498
5577
  const name = detailAppName;
5499
5578
  setDetailAppName(null);
5579
+ setDetailAppId(null);
5500
5580
  if (name) onDetailClose?.(name);
5501
5581
  },
5502
5582
  appName: detailAppName,
5583
+ appId: detailAppId,
5503
5584
  anchor,
5504
5585
  width,
5505
5586
  onRefresh: onClose,
@@ -5509,22 +5590,1978 @@ function AppSearchDrawer({
5509
5590
  ] });
5510
5591
  }
5511
5592
 
5512
- // useAppLookup.ts
5513
- import { useEffect as useEffect7, useMemo as useMemo5, useState as useState10 } from "react";
5514
- var norm = (s) => s.toLowerCase().replace(/[\s_\-]+/g, "_");
5515
- function useAppLookup(appName) {
5516
- const [loading, setLoading] = useState10(false);
5517
- const [info, setInfo] = useState10(null);
5518
- const [algoliaId, setAlgoliaId] = useState10(null);
5519
- const {
5520
- authStates,
5521
- authenticatedApps,
5522
- handleAuthChange,
5523
- handleTestConnection,
5524
- handleSaveAuth,
5525
- refreshAuth
5526
- } = useAppAuth();
5527
- useEffect7(() => {
5593
+ // AgentUI.tsx
5594
+ import { useCallback as useCallback8, useEffect as useEffect7, useMemo as useMemo5, useRef as useRef6, useState as useState10 } from "react";
5595
+ import { useNavigate } from "react-router-dom";
5596
+ import {
5597
+ Avatar as Avatar6,
5598
+ AvatarGroup,
5599
+ Box as Box11,
5600
+ Button as Button5,
5601
+ Chip as Chip7,
5602
+ CircularProgress as CircularProgress4,
5603
+ IconButton as IconButton6,
5604
+ InputBase as InputBase2,
5605
+ TextField as TextField4,
5606
+ Tooltip as Tooltip6,
5607
+ Typography as Typography11
5608
+ } from "@mui/material";
5609
+ import AddIcon2 from "@mui/icons-material/Add";
5610
+ import AttachFileIcon from "@mui/icons-material/AttachFile";
5611
+ import CheckCircleIcon3 from "@mui/icons-material/CheckCircle";
5612
+ import CheckIcon2 from "@mui/icons-material/Check";
5613
+ import ErrorIcon from "@mui/icons-material/Error";
5614
+ import HourglassDisabledIcon from "@mui/icons-material/HourglassDisabled";
5615
+ import PauseIcon from "@mui/icons-material/Pause";
5616
+ import PlayArrowRoundedIcon2 from "@mui/icons-material/PlayArrowRounded";
5617
+ import RefreshIcon from "@mui/icons-material/Refresh";
5618
+ import RestartAltIcon2 from "@mui/icons-material/RestartAlt";
5619
+ import ThumbUpIcon from "@mui/icons-material/ThumbUp";
5620
+ import ThumbDownIcon from "@mui/icons-material/ThumbDown";
5621
+ import OpenInNewIcon2 from "@mui/icons-material/OpenInNew";
5622
+ import SendIcon from "@mui/icons-material/Send";
5623
+ import WarningIcon from "@mui/icons-material/Warning";
5624
+ import CloseIcon4 from "@mui/icons-material/Close";
5625
+ import Markdown from "react-markdown";
5626
+ import remarkGfm4 from "remark-gfm";
5627
+ import remarkBreaks from "remark-breaks";
5628
+ import JsonView from "react18-json-view";
5629
+ import "react18-json-view/src/style.css";
5630
+ import "react18-json-view/src/dark.css";
5631
+
5632
+ // agentRun.ts
5633
+ var resolveTarget = (path, opts = {}) => {
5634
+ const url = opts.apiBaseUrl ? `${opts.apiBaseUrl.replace(/\/+$/, "")}${path}` : getApiUrl(path);
5635
+ const headers = opts.apiKey ? { Authorization: `Bearer ${opts.apiKey}` } : { ...getAuthHeader() };
5636
+ if (opts.orgId) headers["Org-Id"] = opts.orgId;
5637
+ return { url, headers };
5638
+ };
5639
+ var parseDataUrl = (dataUrl) => {
5640
+ const match = /^data:([^;]+);base64,(.*)$/.exec(dataUrl);
5641
+ if (!match) return null;
5642
+ return { mimeType: match[1], data: match[2] };
5643
+ };
5644
+ var parseAgentResponse = (data) => {
5645
+ if (typeof data === "string") return data;
5646
+ if (data == null) return "No output returned.";
5647
+ const obj = data;
5648
+ if (obj.result !== void 0) {
5649
+ const result = obj.result;
5650
+ if (typeof result === "string") return result || "No output returned.";
5651
+ if (typeof result === "object" && result !== null) {
5652
+ const r = result;
5653
+ const parts = [];
5654
+ if (r.message && typeof r.message === "string") {
5655
+ parts.push(r.message);
5656
+ }
5657
+ const rest = { ...r };
5658
+ delete rest.message;
5659
+ if (Object.keys(rest).length > 0) {
5660
+ parts.push(JSON.stringify(rest, null, 2));
5661
+ }
5662
+ return parts.join("\n\n") || "No output returned.";
5663
+ }
5664
+ return String(result);
5665
+ }
5666
+ if (obj.message && typeof obj.message === "string") return obj.message;
5667
+ return JSON.stringify(data, null, 2);
5668
+ };
5669
+ var pollExecutionResult = async (executionId, {
5670
+ maxAttempts = 15,
5671
+ intervalMs = 2e3,
5672
+ apiKey,
5673
+ apiBaseUrl,
5674
+ orgId
5675
+ } = {}) => {
5676
+ const { url, headers } = resolveTarget("/api/v1/streams/results", { apiKey, apiBaseUrl, orgId });
5677
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
5678
+ try {
5679
+ const resp = await fetch(url, {
5680
+ method: "POST",
5681
+ credentials: "include",
5682
+ headers: {
5683
+ "Content-Type": "application/json",
5684
+ ...headers
5685
+ },
5686
+ body: JSON.stringify({
5687
+ execution_id: executionId,
5688
+ authorization: executionId
5689
+ })
5690
+ });
5691
+ if (!resp.ok) {
5692
+ if (resp.status >= 400 && resp.status < 500) {
5693
+ return {
5694
+ success: false,
5695
+ content: "",
5696
+ error: `Error ${resp.status}: Could not fetch execution result.`,
5697
+ status: resp.status
5698
+ };
5699
+ }
5700
+ await delay(intervalMs);
5701
+ continue;
5702
+ }
5703
+ const rawText = await resp.text();
5704
+ if (!rawText || rawText === "{}" || rawText === "null") {
5705
+ await delay(intervalMs);
5706
+ continue;
5707
+ }
5708
+ const contentType = resp.headers.get("content-type");
5709
+ if (!contentType?.includes("application/json")) {
5710
+ return { success: true, content: rawText, status: resp.status };
5711
+ }
5712
+ const data = JSON.parse(rawText);
5713
+ if (data?.status === "EXECUTING" || data?.status === "WAITING") {
5714
+ await delay(intervalMs);
5715
+ continue;
5716
+ }
5717
+ const content = parseAgentResponse(data);
5718
+ return {
5719
+ success: true,
5720
+ content,
5721
+ rawData: data,
5722
+ status: resp.status
5723
+ };
5724
+ } catch {
5725
+ await delay(intervalMs);
5726
+ }
5727
+ }
5728
+ return {
5729
+ success: false,
5730
+ content: "",
5731
+ error: `Timed out waiting for execution ${executionId} to complete.`,
5732
+ status: 0
5733
+ };
5734
+ };
5735
+ var delay = (ms) => new Promise((r) => setTimeout(r, ms));
5736
+ var isExecutionStub = (data) => {
5737
+ if (typeof data !== "object" || data === null) return false;
5738
+ const obj = data;
5739
+ return typeof obj.execution_id === "string" && obj.execution_id.length > 0 && // It's a stub if there's no result/message — just metadata
5740
+ obj.result === void 0 && obj.message === void 0;
5741
+ };
5742
+ var runAgent = async (request) => {
5743
+ const input = { text: request.input };
5744
+ const images = [];
5745
+ if (request.images && request.images.length > 0) {
5746
+ images.push(...request.images);
5747
+ } else if (request.image && request.image.length > 0) {
5748
+ const parsed = parseDataUrl(request.image);
5749
+ if (parsed) images.push(parsed);
5750
+ }
5751
+ if (images.length > 0) {
5752
+ input.images = images.map((img) => ({
5753
+ url: `data:${img.mimeType};base64,${img.data}`,
5754
+ detail: "auto"
5755
+ }));
5756
+ }
5757
+ const params = { input };
5758
+ if (request.toolName) params.tool_name = request.toolName;
5759
+ if (request.toolId) params.tool_id = request.toolId;
5760
+ if (request.toolNames && request.toolNames.length > 0) {
5761
+ params.tool_names = request.toolNames;
5762
+ }
5763
+ if (request.toolIds && request.toolIds.length > 0) {
5764
+ params.tool_ids = request.toolIds;
5765
+ }
5766
+ const payload = {
5767
+ jsonrpc: "2.0",
5768
+ id: crypto.randomUUID(),
5769
+ method: "tools/call",
5770
+ params
5771
+ };
5772
+ const { url: agentUrl, headers: agentHeaders } = resolveTarget("/api/v1/agent", {
5773
+ apiKey: request.apiKey,
5774
+ apiBaseUrl: request.apiBaseUrl,
5775
+ orgId: request.orgId
5776
+ });
5777
+ try {
5778
+ const response = await fetch(agentUrl, {
5779
+ method: "POST",
5780
+ credentials: "include",
5781
+ headers: {
5782
+ "Content-Type": "application/json",
5783
+ ...agentHeaders
5784
+ },
5785
+ body: JSON.stringify(payload)
5786
+ });
5787
+ const rawText = await response.text();
5788
+ const contentType = response.headers.get("content-type");
5789
+ if (!response.ok) {
5790
+ return {
5791
+ success: false,
5792
+ content: "",
5793
+ error: `Error ${response.status}: ${rawText || response.statusText}`,
5794
+ status: response.status
5795
+ };
5796
+ }
5797
+ if (!contentType?.includes("application/json")) {
5798
+ if (rawText.trim().startsWith("<!") || rawText.includes("<html")) {
5799
+ return {
5800
+ success: false,
5801
+ content: "",
5802
+ error: "Received an unexpected HTML response. This may indicate an auth redirect or server issue.",
5803
+ status: response.status
5804
+ };
5805
+ }
5806
+ return {
5807
+ success: true,
5808
+ content: rawText,
5809
+ status: response.status
5810
+ };
5811
+ }
5812
+ const data = JSON.parse(rawText);
5813
+ if (isExecutionStub(data)) {
5814
+ if (request.skipPolling) {
5815
+ return {
5816
+ success: true,
5817
+ content: "",
5818
+ rawData: data,
5819
+ status: response.status
5820
+ };
5821
+ }
5822
+ console.log(`[AgentRun] Got execution stub, polling for result: ${data.execution_id}`);
5823
+ return pollExecutionResult(data.execution_id, {
5824
+ apiKey: request.apiKey,
5825
+ apiBaseUrl: request.apiBaseUrl,
5826
+ orgId: request.orgId
5827
+ });
5828
+ }
5829
+ const content = parseAgentResponse(data);
5830
+ return {
5831
+ success: true,
5832
+ content,
5833
+ rawData: data,
5834
+ status: response.status
5835
+ };
5836
+ } catch (err) {
5837
+ return {
5838
+ success: false,
5839
+ content: "",
5840
+ error: `Network error \u2014 could not reach the agent. ${err instanceof Error ? err.message : ""}`,
5841
+ status: 0
5842
+ };
5843
+ }
5844
+ };
5845
+
5846
+ // AgentUI.tsx
5847
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
5848
+ var normalizeMarkdown = (raw) => {
5849
+ if (raw == null) return "";
5850
+ let s = typeof raw === "string" ? raw : (() => {
5851
+ try {
5852
+ return JSON.stringify(raw, null, 2);
5853
+ } catch {
5854
+ return String(raw);
5855
+ }
5856
+ })();
5857
+ if (s.length > 1 && s.startsWith('"') && s.endsWith('"')) {
5858
+ try {
5859
+ s = JSON.parse(s);
5860
+ } catch {
5861
+ }
5862
+ }
5863
+ s = s.replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\"/g, '"');
5864
+ return s.trim();
5865
+ };
5866
+ var deepParseJsonStrings = (obj, depth = 0) => {
5867
+ if (depth > 5) return obj;
5868
+ if (typeof obj === "string") {
5869
+ const trimmed = obj.trim();
5870
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
5871
+ try {
5872
+ const parsed = JSON.parse(trimmed);
5873
+ if (typeof parsed === "object" && parsed !== null) {
5874
+ return deepParseJsonStrings(parsed, depth + 1);
5875
+ }
5876
+ } catch {
5877
+ }
5878
+ }
5879
+ return obj;
5880
+ }
5881
+ if (Array.isArray(obj)) return obj.map((item) => deepParseJsonStrings(item, depth + 1));
5882
+ if (obj && typeof obj === "object") {
5883
+ const result = {};
5884
+ for (const [key, value] of Object.entries(obj)) {
5885
+ result[key] = deepParseJsonStrings(value, depth + 1);
5886
+ }
5887
+ return result;
5888
+ }
5889
+ return obj;
5890
+ };
5891
+ var validateJson = (raw) => {
5892
+ if (raw == null) return { valid: false, result: null };
5893
+ if (typeof raw === "object") return { valid: true, result: raw };
5894
+ if (typeof raw !== "string") return { valid: false, result: raw };
5895
+ try {
5896
+ return { valid: true, result: JSON.parse(raw) };
5897
+ } catch {
5898
+ return { valid: false, result: raw };
5899
+ }
5900
+ };
5901
+ var STATUS_COLORS = {
5902
+ finished: "hsl(142, 71%, 45%)",
5903
+ warning: "hsl(38, 92%, 50%)",
5904
+ error: "hsl(0, 72%, 55%)",
5905
+ running: "hsl(var(--primary))"
5906
+ };
5907
+ var buildToolName = (apps) => {
5908
+ if (!apps.length) return "API";
5909
+ return apps.map((a) => {
5910
+ const slug = a.name.toLowerCase().replace(/\s+/g, "_").replace(/-/g, "_");
5911
+ return a.id ? `app:${a.id}:${slug}` : slug;
5912
+ }).join(",");
5913
+ };
5914
+ var StatusIcon = ({ status }) => {
5915
+ const s = (status || "").toUpperCase();
5916
+ if (s === "RUNNING" || s === "EXECUTING" || s === "") {
5917
+ return /* @__PURE__ */ jsx14(CircularProgress4, { size: 18, sx: { color: STATUS_COLORS.running } });
5918
+ }
5919
+ if (s === "WAITING") {
5920
+ return /* @__PURE__ */ jsx14(Tooltip6, { title: "Waiting for input", children: /* @__PURE__ */ jsx14(PauseIcon, { sx: { color: STATUS_COLORS.running, fontSize: 20 } }) });
5921
+ }
5922
+ if (s === "FINISHED" || s === "SUCCESS") {
5923
+ return /* @__PURE__ */ jsx14(CheckCircleIcon3, { sx: { color: STATUS_COLORS.finished, fontSize: 20 } });
5924
+ }
5925
+ if (s === "ABORTED" || s === "FAILURE") {
5926
+ return /* @__PURE__ */ jsx14(ErrorIcon, { sx: { color: STATUS_COLORS.error, fontSize: 20 } });
5927
+ }
5928
+ if (s === "IGNORED" || s === "IGNORE") {
5929
+ return /* @__PURE__ */ jsx14(WarningIcon, { sx: { color: STATUS_COLORS.warning, fontSize: 20 } });
5930
+ }
5931
+ return /* @__PURE__ */ jsx14(HourglassDisabledIcon, { sx: { color: "hsl(var(--muted-foreground))", fontSize: 20 } });
5932
+ };
5933
+ var TimelineRow = ({
5934
+ item,
5935
+ index,
5936
+ open,
5937
+ onToggle,
5938
+ appsById,
5939
+ totalDuration,
5940
+ originalStartTime,
5941
+ maxWidth,
5942
+ questionAnswers,
5943
+ setQuestionAnswers,
5944
+ onSubmitQuestions,
5945
+ onRerunAgent,
5946
+ onRerunDecision,
5947
+ agentRequestLoading,
5948
+ getFormUrl,
5949
+ runFinished
5950
+ }) => {
5951
+ const [submitAttempted, setSubmitAttempted] = useState10(false);
5952
+ const validate = validateJson(item.details);
5953
+ const itemStart = item.start_time || 0;
5954
+ const itemEnd = item.end_time || itemStart;
5955
+ const dur = Math.max(0, itemEnd - itemStart);
5956
+ const offset = totalDuration > 0 ? (itemStart - originalStartTime) / totalDuration * maxWidth : 0;
5957
+ const width = totalDuration > 0 ? Math.max(4, dur / totalDuration * maxWidth) : 0;
5958
+ let displayType = item.type;
5959
+ let displayLabel = item.label?.replace(/_/g, " ") || "";
5960
+ const details = item.details;
5961
+ const isProcessing = item.category === "processing";
5962
+ if (isProcessing) {
5963
+ displayType = "processing";
5964
+ } else if (details?.reason) {
5965
+ displayLabel = details.reason;
5966
+ }
5967
+ if (!isProcessing) {
5968
+ if (details?.action === "finish" || item.category === "finish" || details?.action === "finalise") {
5969
+ displayType = "finalise";
5970
+ } else if (item.category === "ask" || details?.action === "ask") {
5971
+ displayType = "question";
5972
+ } else if (details?.action === "add_tool") {
5973
+ displayType = "add tool";
5974
+ }
5975
+ }
5976
+ let toolApp;
5977
+ if (details?.tool && typeof details.tool === "string" && details.tool !== "singul") {
5978
+ let tn = details.tool.toLowerCase().replace(/[\s-]+/g, "_");
5979
+ if (tn.startsWith("app:")) tn = tn.split(":")[2] || tn;
5980
+ toolApp = appsById[tn];
5981
+ }
5982
+ const questions = [];
5983
+ if (item.category === "ask" || details?.action === "ask") {
5984
+ for (const f of details?.fields || []) {
5985
+ if (f.key === "question" && f.value) {
5986
+ questions.push({ question: f.value, index: questions.length + 1 });
5987
+ }
5988
+ }
5989
+ }
5990
+ const questionsAnswered = questions.every(
5991
+ (q) => questionAnswers[q.question]?.value
5992
+ );
5993
+ const effectiveStatus = runFinished && (item.status === "RUNNING" || item.status === "WAITING") ? "IGNORED" : item.status;
5994
+ const barColor = isProcessing ? "hsl(var(--muted-foreground) / 0.45)" : effectiveStatus === "IGNORED" ? STATUS_COLORS.warning : effectiveStatus === "FINISHED" ? STATUS_COLORS.finished : effectiveStatus === "FAILURE" || effectiveStatus === "ABORTED" ? STATUS_COLORS.error : STATUS_COLORS.running;
5995
+ return /* @__PURE__ */ jsxs12(Box11, { sx: {
5996
+ borderTop: index === 0 ? "none" : "1px solid hsl(var(--border))",
5997
+ bgcolor: open ? "hsl(var(--muted) / 0.3)" : "transparent",
5998
+ transition: "background 0.15s ease"
5999
+ }, children: [
6000
+ /* @__PURE__ */ jsxs12(
6001
+ Box11,
6002
+ {
6003
+ onClick: onToggle,
6004
+ sx: {
6005
+ display: "flex",
6006
+ alignItems: "center",
6007
+ gap: 1.5,
6008
+ px: 2,
6009
+ py: 1.25,
6010
+ cursor: "pointer",
6011
+ "&:hover": { bgcolor: "hsl(var(--muted) / 0.4)" }
6012
+ },
6013
+ children: [
6014
+ /* @__PURE__ */ jsx14(Box11, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isProcessing ? /* @__PURE__ */ jsx14(Box11, { sx: { width: 6, height: 6, borderRadius: "50%", bgcolor: "hsl(var(--muted-foreground) / 0.5)" } }) : /* @__PURE__ */ jsx14(StatusIcon, { status: effectiveStatus }) }),
6015
+ /* @__PURE__ */ jsx14(Box11, { sx: { width: 24, display: "flex", justifyContent: "center" }, children: isProcessing ? /* @__PURE__ */ jsx14(Box11, { sx: { width: 22 } }) : toolApp?.icon ? /* @__PURE__ */ jsx14(Avatar6, { src: toolApp.icon, sx: { width: 22, height: 22, bgcolor: "transparent" }, variant: "rounded" }) : item.category === "finalise" || details?.action === "finish" ? /* @__PURE__ */ jsx14(CheckIcon2, { sx: { color: STATUS_COLORS.finished, fontSize: 18 } }) : /* @__PURE__ */ jsx14(Box11, { sx: { width: 22 } }) }),
6016
+ /* @__PURE__ */ jsx14(
6017
+ Chip7,
6018
+ {
6019
+ label: displayType,
6020
+ size: "small",
6021
+ sx: {
6022
+ height: 22,
6023
+ bgcolor: isProcessing ? "transparent" : "hsl(var(--muted))",
6024
+ color: isProcessing ? "hsl(var(--muted-foreground))" : "hsl(var(--foreground))",
6025
+ border: isProcessing ? "1px dashed hsl(var(--border))" : "none",
6026
+ fontSize: "0.7rem",
6027
+ fontWeight: 500,
6028
+ textTransform: "capitalize",
6029
+ minWidth: 80,
6030
+ fontStyle: isProcessing ? "italic" : "normal"
6031
+ }
6032
+ }
6033
+ ),
6034
+ /* @__PURE__ */ jsx14(Box11, { sx: {
6035
+ flex: 1,
6036
+ minWidth: 0,
6037
+ fontSize: "0.85rem",
6038
+ color: "hsl(var(--foreground))",
6039
+ maxHeight: 60,
6040
+ overflow: "hidden",
6041
+ "& p": { margin: 0 },
6042
+ "& pre, & code": { fontSize: "0.78rem" }
6043
+ }, children: /* @__PURE__ */ jsx14(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(displayLabel) }) }),
6044
+ /* @__PURE__ */ jsx14(Tooltip6, { title: `Duration: ${dur.toFixed(1)}s \xB7 ${itemStart ? new Date(itemStart * 1e3).toLocaleString() : ""}`, children: /* @__PURE__ */ jsx14(Box11, { sx: { width: maxWidth, position: "relative", height: 10, flexShrink: 0 }, children: dur > 0 && /* @__PURE__ */ jsx14(Box11, { sx: {
6045
+ position: "absolute",
6046
+ left: Math.max(0, offset),
6047
+ width,
6048
+ height: 8,
6049
+ top: 1,
6050
+ bgcolor: barColor,
6051
+ borderRadius: 1,
6052
+ transition: "all 0.2s ease"
6053
+ } }) }) }),
6054
+ /* @__PURE__ */ jsx14(Box11, { sx: { width: 60, fontSize: "0.7rem", color: "hsl(var(--muted-foreground))", textAlign: "right" }, children: dur > 0 ? `${dur.toFixed(1)}s` : "" }),
6055
+ /* @__PURE__ */ jsxs12(
6056
+ Box11,
6057
+ {
6058
+ sx: { display: "flex", alignItems: "center", gap: 0.25, ml: 1, minWidth: 96, justifyContent: "flex-end" },
6059
+ onClick: (e) => e.stopPropagation(),
6060
+ children: [
6061
+ item.type === "decision" && details?.run_details?.status === "WAITING" && (item.category === "ask" || details?.action === "ask") && questions.length === 0 && /* @__PURE__ */ jsxs12(Fragment7, { children: [
6062
+ /* @__PURE__ */ jsx14(Tooltip6, { title: "Approve this step", children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
6063
+ IconButton6,
6064
+ {
6065
+ size: "small",
6066
+ disabled: agentRequestLoading,
6067
+ onClick: () => {
6068
+ if (details?.run_details?.id) onSubmitQuestions(details.run_details.id, { approve: "true" });
6069
+ },
6070
+ sx: { color: STATUS_COLORS.finished },
6071
+ children: /* @__PURE__ */ jsx14(ThumbUpIcon, { sx: { fontSize: 16 } })
6072
+ }
6073
+ ) }) }),
6074
+ /* @__PURE__ */ jsx14(Tooltip6, { title: "Deny this step", children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
6075
+ IconButton6,
6076
+ {
6077
+ size: "small",
6078
+ disabled: agentRequestLoading,
6079
+ onClick: () => {
6080
+ if (details?.run_details?.id) onSubmitQuestions(details.run_details.id, { approve: "false" });
6081
+ },
6082
+ sx: { color: STATUS_COLORS.error },
6083
+ children: /* @__PURE__ */ jsx14(ThumbDownIcon, { sx: { fontSize: 16 } })
6084
+ }
6085
+ ) }) })
6086
+ ] }),
6087
+ item.type === "agent" && /* @__PURE__ */ jsx14(Tooltip6, { title: "Rerun the agent with the same input", children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
6088
+ IconButton6,
6089
+ {
6090
+ size: "small",
6091
+ disabled: agentRequestLoading,
6092
+ onClick: onRerunAgent,
6093
+ sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--primary))" } },
6094
+ children: /* @__PURE__ */ jsx14(RestartAltIcon2, { sx: { fontSize: 16 } })
6095
+ }
6096
+ ) }) }),
6097
+ item.type === "decision" && (() => {
6098
+ const action = details?.action;
6099
+ const cat = item.category;
6100
+ const isApiAction = action !== "ask" && cat !== "ask" && action !== "finish" && action !== "finalise" && cat !== "finish" && cat !== "finalise" && cat !== "processing" && action !== "add_tool";
6101
+ if (!isApiAction) return null;
6102
+ return /* @__PURE__ */ jsx14(Tooltip6, { title: "Rerun from this decision (clears all decisions after it)", children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
6103
+ IconButton6,
6104
+ {
6105
+ size: "small",
6106
+ disabled: agentRequestLoading || !details?.run_details?.id,
6107
+ onClick: () => details && onRerunDecision(details),
6108
+ sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--primary))" } },
6109
+ children: /* @__PURE__ */ jsx14(RestartAltIcon2, { sx: { fontSize: 16 } })
6110
+ }
6111
+ ) }) });
6112
+ })(),
6113
+ item.type === "decision" && details?.run_details?.debug_url && /* @__PURE__ */ jsx14(Tooltip6, { title: "Open debug URL", children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
6114
+ IconButton6,
6115
+ {
6116
+ size: "small",
6117
+ onClick: () => window.open(details.run_details.debug_url, "_blank", "noopener,noreferrer"),
6118
+ sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--primary))" } },
6119
+ children: /* @__PURE__ */ jsx14(OpenInNewIcon2, { sx: { fontSize: 16 } })
6120
+ }
6121
+ ) }) })
6122
+ ]
6123
+ }
6124
+ )
6125
+ ]
6126
+ }
6127
+ ),
6128
+ questions.length > 0 && !runFinished && (item.status === "RUNNING" || item.status === "WAITING") && /* @__PURE__ */ jsx14(Box11, { sx: { px: 4, pb: 2 }, children: (() => {
6129
+ const trySubmit = () => {
6130
+ if (agentRequestLoading) return;
6131
+ if (!questionsAnswered) {
6132
+ setSubmitAttempted(true);
6133
+ return;
6134
+ }
6135
+ if (details?.run_details?.id) {
6136
+ onSubmitQuestions(details.run_details.id, questionAnswers);
6137
+ }
6138
+ };
6139
+ return /* @__PURE__ */ jsxs12(Fragment7, { children: [
6140
+ questions.map((q, qi) => {
6141
+ const value = questionAnswers[q.question]?.value || "";
6142
+ const isMissing = submitAttempted && !value;
6143
+ return /* @__PURE__ */ jsxs12(Box11, { sx: { mt: 2 }, children: [
6144
+ /* @__PURE__ */ jsx14(Box11, { sx: { fontSize: "0.85rem", color: "hsl(var(--foreground))", mb: 1 }, children: /* @__PURE__ */ jsx14(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(q.question) }) }),
6145
+ /* @__PURE__ */ jsx14(
6146
+ TextField4,
6147
+ {
6148
+ fullWidth: true,
6149
+ multiline: true,
6150
+ minRows: 2,
6151
+ placeholder: "Your answer here\u2026",
6152
+ value,
6153
+ error: isMissing,
6154
+ helperText: isMissing ? "Please answer this question" : void 0,
6155
+ onChange: (e) => {
6156
+ const v = e.target.value;
6157
+ setQuestionAnswers((prev) => ({
6158
+ ...prev,
6159
+ [q.question]: { index: qi, value: v }
6160
+ }));
6161
+ },
6162
+ onKeyDown: (e) => {
6163
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
6164
+ e.preventDefault();
6165
+ trySubmit();
6166
+ }
6167
+ },
6168
+ size: "small",
6169
+ sx: {
6170
+ "& .MuiOutlinedInput-root": { bgcolor: "hsl(var(--card))" }
6171
+ }
6172
+ }
6173
+ )
6174
+ ] }, qi);
6175
+ }),
6176
+ /* @__PURE__ */ jsxs12(Box11, { sx: { display: "flex", alignItems: "center", gap: 1, mt: 2 }, children: [
6177
+ /* @__PURE__ */ jsx14(
6178
+ Button5,
6179
+ {
6180
+ variant: "contained",
6181
+ size: "small",
6182
+ disabled: agentRequestLoading,
6183
+ onClick: trySubmit,
6184
+ children: agentRequestLoading ? /* @__PURE__ */ jsx14(CircularProgress4, { size: 16 }) : "Submit"
6185
+ }
6186
+ ),
6187
+ details?.run_details?.id && getFormUrl && getFormUrl(details.run_details.id) && /* @__PURE__ */ jsx14(Tooltip6, { title: "Answer in the Form UI", placement: "right", children: /* @__PURE__ */ jsx14(
6188
+ IconButton6,
6189
+ {
6190
+ size: "small",
6191
+ onClick: () => {
6192
+ const url = getFormUrl(details.run_details.id);
6193
+ if (url) window.open(url, "_blank", "noopener,noreferrer");
6194
+ },
6195
+ sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--primary))" } },
6196
+ children: /* @__PURE__ */ jsx14(OpenInNewIcon2, { sx: { fontSize: 18 } })
6197
+ }
6198
+ ) })
6199
+ ] })
6200
+ ] });
6201
+ })() }),
6202
+ open && runFinished && questions.length > 0 && /* @__PURE__ */ jsxs12(Box11, { sx: { px: 4, pb: 2 }, children: [
6203
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.7rem", textTransform: "uppercase", letterSpacing: 0.5, color: "hsl(var(--muted-foreground))", mb: 1 }, children: questions.length === 1 ? "Question (unanswered)" : "Questions (unanswered)" }),
6204
+ /* @__PURE__ */ jsx14(Box11, { sx: {
6205
+ p: 2,
6206
+ borderRadius: 1.5,
6207
+ border: "1px solid hsl(var(--border))",
6208
+ bgcolor: "hsl(var(--background))",
6209
+ display: "flex",
6210
+ flexDirection: "column",
6211
+ gap: 1.5
6212
+ }, children: questions.map((q, qi) => /* @__PURE__ */ jsx14(Box11, { sx: { fontSize: "0.85rem", color: "hsl(var(--foreground))", "& p": { my: 0.5 } }, children: /* @__PURE__ */ jsx14(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(q.question) }) }, qi)) })
6213
+ ] }),
6214
+ open && /* @__PURE__ */ jsx14(Box11, { sx: { px: 4, pb: 2 }, children: /* @__PURE__ */ jsx14(
6215
+ Box11,
6216
+ {
6217
+ sx: {
6218
+ p: 2,
6219
+ borderRadius: 1.5,
6220
+ border: "1px solid hsl(var(--border))",
6221
+ bgcolor: "hsl(var(--background))",
6222
+ overflow: "auto",
6223
+ maxHeight: 400,
6224
+ fontFamily: '"JetBrains Mono", ui-monospace, monospace',
6225
+ "& .json-view": {
6226
+ fontSize: "0.72rem !important",
6227
+ fontFamily: "inherit !important",
6228
+ bgcolor: "transparent !important"
6229
+ }
6230
+ },
6231
+ children: validate.valid && validate.result && typeof validate.result === "object" ? /* @__PURE__ */ jsx14(
6232
+ JsonView,
6233
+ {
6234
+ src: deepParseJsonStrings(validate.result),
6235
+ dark: true,
6236
+ collapsed: 2,
6237
+ collapseStringMode: "word",
6238
+ collapseStringsAfterLength: 120,
6239
+ enableClipboard: true,
6240
+ displaySize: true
6241
+ }
6242
+ ) : /* @__PURE__ */ jsx14(Box11, { component: "pre", sx: { m: 0, fontSize: "0.72rem", color: "hsl(var(--foreground))" }, children: /* @__PURE__ */ jsx14("code", { children: String(item.details ?? "") }) })
6243
+ }
6244
+ ) })
6245
+ ] });
6246
+ };
6247
+ var AgentUI = ({
6248
+ apps,
6249
+ defaultApps,
6250
+ autoLoadApps = true,
6251
+ title = "What do you want to do?",
6252
+ subtitle,
6253
+ placeholder = 'Describe a task, e.g. "Get my emails for today and summarise them"',
6254
+ defaultInput = "",
6255
+ autoSubmit = false,
6256
+ hideHeroIcon = false,
6257
+ heroIcon,
6258
+ heroIconSize = 84,
6259
+ maxWidth = 900,
6260
+ compact = false,
6261
+ hideAppPicker = false,
6262
+ hideAttach = false,
6263
+ appPickerLabel = "Select Apps / MCPs",
6264
+ appPickerTitle = "Select Apps / MCPs",
6265
+ appPickerSubtitle = "Pick the tools the agent is allowed to use for this run",
6266
+ submitTooltip = "\u2318+Enter to send",
6267
+ submitIcon,
6268
+ continuationPlaceholder = "Add more details to continue this task\u2026",
6269
+ readUrlParams = true,
6270
+ executionId,
6271
+ authorization,
6272
+ onRun,
6273
+ apiKey,
6274
+ apiBaseUrl,
6275
+ orgId
6276
+ }) => {
6277
+ const resolveUrl = useCallback8(
6278
+ (path) => apiBaseUrl ? `${apiBaseUrl.replace(/\/+$/, "")}${path}` : getApiUrl(path),
6279
+ [apiBaseUrl]
6280
+ );
6281
+ const resolveHeaders = useCallback8(() => {
6282
+ const h = apiKey ? { Authorization: `Bearer ${apiKey}` } : { ...getAuthHeader() };
6283
+ if (orgId) h["Org-Id"] = orgId;
6284
+ return h;
6285
+ }, [apiKey, orgId]);
6286
+ const hasApiKey = !!apiKey || !!API_CONFIG.apiKey;
6287
+ const navigate = useNavigate();
6288
+ const [actionInput, setActionInput] = useState10(defaultInput);
6289
+ const BUILTIN_DEFAULT_APPS = [
6290
+ { name: "http" },
6291
+ { name: "shuffle_tools" }
6292
+ ];
6293
+ const [chosenApps, setChosenApps] = useState10(apps ?? defaultApps ?? BUILTIN_DEFAULT_APPS);
6294
+ const [availableApps, setAvailableApps] = useState10([]);
6295
+ const [appSearchOpen, setAppSearchOpen] = useState10(false);
6296
+ const [agentRequestLoading, setAgentRequestLoading] = useState10(false);
6297
+ const [execution, setExecution] = useState10(null);
6298
+ const [agentData, setAgentData] = useState10({});
6299
+ const [agentActionResult, setAgentActionResult] = useState10(null);
6300
+ const [showStarter, setShowStarter] = useState10(true);
6301
+ const [openIndexes, setOpenIndexes] = useState10(/* @__PURE__ */ new Set());
6302
+ const [questionAnswers, setQuestionAnswers] = useState10({});
6303
+ const [simpleSubmitAttempted, setSimpleSubmitAttempted] = useState10(false);
6304
+ const [continuationText, setContinuationText] = useState10("");
6305
+ const [error, setError] = useState10(null);
6306
+ const [viewMode, setViewMode] = useState10("simple");
6307
+ const [attachedImages, setAttachedImages] = useState10([]);
6308
+ const [nowTick, setNowTick] = useState10(() => Math.floor(Date.now() / 1e3));
6309
+ const [localRunStart, setLocalRunStart] = useState10(null);
6310
+ const inputRef = useRef6(null);
6311
+ const fileInputRef = useRef6(null);
6312
+ const activeExecutionIdRef = useRef6(null);
6313
+ const stateRef = useRef6({
6314
+ execution: null,
6315
+ agentData: {},
6316
+ agentActionResult: null,
6317
+ openIndexes: /* @__PURE__ */ new Set(),
6318
+ questionAnswers: {},
6319
+ continuationText: "",
6320
+ localRunStart: null,
6321
+ showStarter: true
6322
+ });
6323
+ stateRef.current.execution = execution;
6324
+ stateRef.current.agentData = agentData;
6325
+ stateRef.current.agentActionResult = agentActionResult;
6326
+ stateRef.current.openIndexes = openIndexes;
6327
+ stateRef.current.questionAnswers = questionAnswers;
6328
+ stateRef.current.continuationText = continuationText;
6329
+ stateRef.current.localRunStart = localRunStart;
6330
+ stateRef.current.showStarter = showStarter;
6331
+ useEffect7(() => {
6332
+ if (execution?.execution_id) {
6333
+ setLocalRunStart((prev) => prev ?? Math.floor(Date.now() / 1e3));
6334
+ } else if (!agentRequestLoading) {
6335
+ setLocalRunStart(null);
6336
+ }
6337
+ }, [execution?.execution_id, agentRequestLoading]);
6338
+ useEffect7(() => {
6339
+ const status = (execution?.status || agentData?.status || "").toUpperCase();
6340
+ const TERMINAL = ["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"];
6341
+ if (TERMINAL.includes(status)) return;
6342
+ if (!execution?.execution_id && !agentRequestLoading && !localRunStart) return;
6343
+ const id = setInterval(() => setNowTick(Math.floor(Date.now() / 1e3)), 1e3);
6344
+ return () => clearInterval(id);
6345
+ }, [execution?.execution_id, execution?.status, agentData?.status, agentRequestLoading, localRunStart]);
6346
+ const readImageAsDataUrl = (file) => new Promise((resolve) => {
6347
+ if (!file.type.startsWith("image/")) {
6348
+ resolve(null);
6349
+ return;
6350
+ }
6351
+ const reader = new FileReader();
6352
+ reader.onload = () => {
6353
+ const result = reader.result;
6354
+ resolve(typeof result === "string" ? { dataUrl: result, name: file.name || "Pasted image" } : null);
6355
+ };
6356
+ reader.onerror = () => resolve(null);
6357
+ reader.readAsDataURL(file);
6358
+ });
6359
+ const handleImagesSelected = async (files) => {
6360
+ if (!files) return;
6361
+ const arr = Array.from(files);
6362
+ const nonImages = arr.some((f) => !f.type.startsWith("image/"));
6363
+ if (nonImages) setError("Only image files can be attached.");
6364
+ const results = await Promise.all(arr.map(readImageAsDataUrl));
6365
+ const valid = results.filter((r) => r !== null);
6366
+ if (valid.length > 0) {
6367
+ setAttachedImages((prev) => [...prev, ...valid]);
6368
+ setError(null);
6369
+ }
6370
+ };
6371
+ const appsById = useMemo5(() => {
6372
+ const m = {};
6373
+ for (const a of chosenApps) {
6374
+ const slug = a.name.toLowerCase().replace(/\s+/g, "_").replace(/-/g, "_");
6375
+ m[slug] = a;
6376
+ }
6377
+ return m;
6378
+ }, [chosenApps]);
6379
+ useEffect7(() => {
6380
+ if (apps) setChosenApps(apps);
6381
+ }, [apps]);
6382
+ useEffect7(() => {
6383
+ const missing = chosenApps.filter((a) => !a.icon && a.name);
6384
+ if (missing.length === 0) return;
6385
+ let cancelled = false;
6386
+ const norm2 = (n) => n.toLowerCase().replace(/[\s_\-]+/g, "_");
6387
+ (async () => {
6388
+ const resolved = {};
6389
+ try {
6390
+ const { algoliasearch: algoliasearch2 } = await import("algoliasearch");
6391
+ const client = algoliasearch2("JNSS5CFDZZ", "33e4e3564f4f060e96e0531957bed552");
6392
+ await Promise.all(missing.map(async (a) => {
6393
+ const known = availableApps.find((x) => norm2(x.name) === norm2(a.name));
6394
+ if (known?.icon) {
6395
+ resolved[a.name] = known.icon;
6396
+ return;
6397
+ }
6398
+ try {
6399
+ const res = await client.searchSingleIndex({
6400
+ indexName: "appsearch",
6401
+ searchParams: { query: a.name.replace(/_/g, " "), hitsPerPage: 3 }
6402
+ });
6403
+ const match = res.hits.find((h) => norm2(h.name || "") === norm2(a.name)) || res.hits[0];
6404
+ if (match?.image_url) resolved[a.name] = match.image_url;
6405
+ } catch {
6406
+ }
6407
+ }));
6408
+ } catch {
6409
+ }
6410
+ const stillMissing = missing.filter((a) => !resolved[a.name]);
6411
+ if (stillMissing.length > 0) {
6412
+ try {
6413
+ const res = await fetch(resolveUrl("/api/v1/apps"), {
6414
+ credentials: "include",
6415
+ headers: { ...resolveHeaders() }
6416
+ });
6417
+ if (res.ok) {
6418
+ const apps2 = await res.json();
6419
+ if (Array.isArray(apps2)) {
6420
+ for (const a of stillMissing) {
6421
+ const m = apps2.find((x) => norm2(x.name || "") === norm2(a.name));
6422
+ const img = m?.large_image || m?.image_url || m?.image;
6423
+ if (img) resolved[a.name] = img;
6424
+ }
6425
+ }
6426
+ }
6427
+ } catch {
6428
+ }
6429
+ }
6430
+ if (cancelled) return;
6431
+ setChosenApps((prev) => prev.map((a) => {
6432
+ if (a.icon) return a;
6433
+ const icon = resolved[a.name];
6434
+ return icon ? { ...a, icon } : a;
6435
+ }));
6436
+ })();
6437
+ return () => {
6438
+ cancelled = true;
6439
+ };
6440
+ }, [chosenApps, availableApps, resolveUrl, resolveHeaders]);
6441
+ useEffect7(() => {
6442
+ if (!autoLoadApps) return;
6443
+ if (apps || defaultApps) return;
6444
+ if (!hasApiKey) return;
6445
+ let cancelled = false;
6446
+ (async () => {
6447
+ try {
6448
+ const resp = await fetch(resolveUrl("/api/v1/apps/authentication"), {
6449
+ credentials: "include",
6450
+ headers: { ...resolveHeaders() }
6451
+ });
6452
+ if (!resp.ok) return;
6453
+ const result = await resp.json();
6454
+ const list = Array.isArray(result) ? result : result?.data || [];
6455
+ const seen = /* @__PURE__ */ new Set();
6456
+ const loaded = [];
6457
+ for (const entry of list) {
6458
+ const app = entry?.app || entry;
6459
+ const name = app?.name;
6460
+ if (!name) continue;
6461
+ const valid = entry?.active || entry?.validation?.valid || entry?.hasValidAuth;
6462
+ if (valid === false) continue;
6463
+ const key = name.toLowerCase();
6464
+ if (seen.has(key)) continue;
6465
+ seen.add(key);
6466
+ loaded.push({
6467
+ name,
6468
+ id: app?.id || entry?.id,
6469
+ icon: app?.large_image || app?.image_url || app?.image || entry?.bestImage || ""
6470
+ });
6471
+ }
6472
+ if (!cancelled && loaded.length) setAvailableApps(loaded);
6473
+ } catch {
6474
+ }
6475
+ })();
6476
+ return () => {
6477
+ cancelled = true;
6478
+ };
6479
+ }, [autoLoadApps, apps, defaultApps, hasApiKey, resolveUrl, resolveHeaders]);
6480
+ const getExecution = useCallback8(async (executionId2, authorization2) => {
6481
+ if (!executionId2 || !authorization2) return;
6482
+ try {
6483
+ const resp = await fetch(resolveUrl("/api/v1/streams/results"), {
6484
+ method: "POST",
6485
+ credentials: "include",
6486
+ headers: { "Content-Type": "application/json", ...resolveHeaders() },
6487
+ body: JSON.stringify({ execution_id: executionId2, authorization: authorization2 })
6488
+ });
6489
+ if (activeExecutionIdRef.current && activeExecutionIdRef.current !== executionId2) return;
6490
+ if (!resp.ok) {
6491
+ setError(`Could not fetch execution (${resp.status}).`);
6492
+ return;
6493
+ }
6494
+ const json = await resp.json();
6495
+ if (activeExecutionIdRef.current && activeExecutionIdRef.current !== executionId2) return;
6496
+ if (json?.success === false) {
6497
+ setError(json.reason || "Failed to load agent data.");
6498
+ return;
6499
+ }
6500
+ setExecution({ ...json, execution_id: executionId2, authorization: authorization2 });
6501
+ let actionResult = null;
6502
+ if (Array.isArray(json?.results)) {
6503
+ actionResult = json.results.find((r) => r?.action?.app_name === "AI Agent") || json.results[0];
6504
+ } else {
6505
+ actionResult = json;
6506
+ }
6507
+ setAgentActionResult(actionResult);
6508
+ const v = validateJson(actionResult?.result);
6509
+ if (v.valid) setAgentData({ ...v.result, started_at: json.started_at, completed_at: json.completed_at, status: json.status });
6510
+ setError(null);
6511
+ } catch (err) {
6512
+ setError(err instanceof Error ? err.message : "Network error.");
6513
+ }
6514
+ }, []);
6515
+ useEffect7(() => {
6516
+ let eid = null;
6517
+ let auth = null;
6518
+ if (executionId && authorization) {
6519
+ eid = executionId;
6520
+ auth = authorization;
6521
+ } else if (readUrlParams) {
6522
+ const params = new URLSearchParams(window.location.search);
6523
+ eid = params.get("execution_id");
6524
+ auth = params.get("authorization");
6525
+ }
6526
+ if (eid && auth) {
6527
+ setShowStarter(false);
6528
+ activeExecutionIdRef.current = eid;
6529
+ setExecution({ execution_id: eid, authorization: auth, status: "EXECUTING" });
6530
+ getExecution(eid, auth);
6531
+ }
6532
+ }, [readUrlParams, executionId, authorization, getExecution]);
6533
+ useEffect7(() => {
6534
+ if (!execution?.execution_id || !execution?.authorization) return;
6535
+ const status = (execution.status || "").toUpperCase();
6536
+ const TERMINAL = ["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"];
6537
+ if (TERMINAL.includes(status)) return;
6538
+ const id = setInterval(() => {
6539
+ getExecution(execution.execution_id, execution.authorization);
6540
+ }, 3e3);
6541
+ return () => clearInterval(id);
6542
+ }, [execution?.execution_id, execution?.authorization, execution?.status, getExecution]);
6543
+ const submitInput = useCallback8(async (text) => {
6544
+ if (!text.trim()) return;
6545
+ setError(null);
6546
+ setAgentRequestLoading(true);
6547
+ const prevExecution = stateRef.current.execution;
6548
+ const prevAgentData = stateRef.current.agentData;
6549
+ const prevAgentActionResult = stateRef.current.agentActionResult;
6550
+ const prevOpenIndexes = stateRef.current.openIndexes;
6551
+ const prevQuestionAnswers = stateRef.current.questionAnswers;
6552
+ const prevContinuationText = stateRef.current.continuationText;
6553
+ const prevLocalRunStart = stateRef.current.localRunStart;
6554
+ const prevActiveExecutionId = activeExecutionIdRef.current;
6555
+ const prevShowStarter = stateRef.current.showStarter;
6556
+ const result = await runAgent({
6557
+ input: text.trim(),
6558
+ skipPolling: true,
6559
+ ...apiKey ? { apiKey } : {},
6560
+ ...apiBaseUrl ? { apiBaseUrl } : {},
6561
+ ...orgId ? { orgId } : {},
6562
+ // Send a single comma-separated `tool_name` in the format
6563
+ // `app:<objectID>:<slug>,app:<objectID>:<slug>` so the backend resolves
6564
+ // the exact app versions instead of guessing by slug.
6565
+ ...chosenApps.length > 0 ? { toolName: buildToolName(chosenApps) } : {},
6566
+ ...attachedImages.length > 0 ? { images: attachedImages.map((img) => {
6567
+ const m = /^data:([^;]+);base64,(.*)$/.exec(img.dataUrl);
6568
+ return m ? { mimeType: m[1], data: m[2], name: img.name } : { mimeType: "image/png", data: img.dataUrl, name: img.name };
6569
+ }) } : {}
6570
+ });
6571
+ setAgentRequestLoading(false);
6572
+ if (!result.success) {
6573
+ setError(result.error || "Agent run failed.");
6574
+ activeExecutionIdRef.current = prevActiveExecutionId;
6575
+ setExecution(prevExecution);
6576
+ setAgentData(prevAgentData);
6577
+ setAgentActionResult(prevAgentActionResult);
6578
+ setOpenIndexes(prevOpenIndexes);
6579
+ setQuestionAnswers(prevQuestionAnswers);
6580
+ setContinuationText(prevContinuationText);
6581
+ setLocalRunStart(prevLocalRunStart);
6582
+ setShowStarter(prevShowStarter);
6583
+ onRun?.({ input: text, success: false, error: result.error });
6584
+ return;
6585
+ }
6586
+ const browserStart = Math.floor(Date.now() / 1e3);
6587
+ setShowStarter(false);
6588
+ activeExecutionIdRef.current = null;
6589
+ setExecution(null);
6590
+ setAgentActionResult(null);
6591
+ setOpenIndexes(/* @__PURE__ */ new Set());
6592
+ setQuestionAnswers({});
6593
+ setContinuationText("");
6594
+ setNowTick(browserStart);
6595
+ setLocalRunStart(browserStart);
6596
+ setAgentData({ original_input: text.trim() });
6597
+ if (readUrlParams && typeof window !== "undefined") {
6598
+ try {
6599
+ const url = new URL(window.location.href);
6600
+ url.searchParams.delete("execution_id");
6601
+ url.searchParams.delete("authorization");
6602
+ window.history.replaceState({}, "", url.toString());
6603
+ } catch {
6604
+ }
6605
+ }
6606
+ const raw = result.rawData;
6607
+ const eid = raw?.execution_id;
6608
+ const auth = raw?.authorization;
6609
+ if (eid && auth) {
6610
+ activeExecutionIdRef.current = eid;
6611
+ setExecution({ execution_id: eid, authorization: auth, status: "EXECUTING" });
6612
+ if (readUrlParams && typeof window !== "undefined") {
6613
+ try {
6614
+ const url = new URL(window.location.href);
6615
+ url.searchParams.set("execution_id", eid);
6616
+ url.searchParams.set("authorization", auth);
6617
+ window.history.replaceState({}, "", url.toString());
6618
+ } catch {
6619
+ }
6620
+ }
6621
+ getExecution(eid, auth);
6622
+ onRun?.({ input: text, success: true, executionId: eid });
6623
+ } else {
6624
+ setExecution({
6625
+ execution_id: eid || crypto.randomUUID(),
6626
+ authorization: auth,
6627
+ status: "FINISHED",
6628
+ results: [{ action: { app_name: "AI Agent" }, result: raw }]
6629
+ });
6630
+ const v = validateJson(raw);
6631
+ if (v.valid) {
6632
+ setAgentData({ ...v.result, status: "FINISHED", original_input: text });
6633
+ } else {
6634
+ setAgentData({ original_input: text, status: "FINISHED", message: result.content });
6635
+ }
6636
+ onRun?.({ input: text, success: true, executionId: eid });
6637
+ }
6638
+ }, [chosenApps, getExecution, onRun, attachedImages, readUrlParams]);
6639
+ const autoSubmittedRef = useRef6(false);
6640
+ useEffect7(() => {
6641
+ if (autoSubmit && defaultInput && !autoSubmittedRef.current && !executionId) {
6642
+ autoSubmittedRef.current = true;
6643
+ submitInput(defaultInput);
6644
+ }
6645
+ }, [autoSubmit, defaultInput, executionId, submitInput]);
6646
+ const submitQuestions = useCallback8(async (decisionId, answers, isContinuation) => {
6647
+ if (!execution?.execution_id || !execution?.authorization) return;
6648
+ let newArgument = {};
6649
+ if (isContinuation) {
6650
+ newArgument = { ...answers };
6651
+ } else {
6652
+ for (const k in answers) {
6653
+ if (k === "approve") {
6654
+ newArgument[k] = answers[k];
6655
+ break;
6656
+ }
6657
+ const a = answers[k];
6658
+ newArgument[`question_${a.index}`] = a.value;
6659
+ }
6660
+ }
6661
+ setAgentRequestLoading(true);
6662
+ const wfId = execution.workflow?.id || execution.execution_id;
6663
+ const params = new URLSearchParams({
6664
+ reference_execution: execution.execution_id,
6665
+ authorization: execution.authorization,
6666
+ answer: "true",
6667
+ note: JSON.stringify(newArgument),
6668
+ agentic: "true",
6669
+ decision_id: decisionId
6670
+ });
6671
+ try {
6672
+ const resp = await fetch(resolveUrl(`/api/v1/workflows/${wfId}/run?${params.toString()}`), {
6673
+ method: "GET",
6674
+ credentials: "include",
6675
+ headers: { ...resolveHeaders() }
6676
+ });
6677
+ const json = await resp.json();
6678
+ if (json.success === false) {
6679
+ toast({ title: "Failed to submit", description: json.reason || "Try again later.", variant: "destructive" });
6680
+ } else {
6681
+ toast({ title: "Submitted", description: "Agent will continue shortly." });
6682
+ setQuestionAnswers({});
6683
+ setContinuationText("");
6684
+ setTimeout(() => {
6685
+ getExecution(execution.execution_id, execution.authorization);
6686
+ }, 600);
6687
+ }
6688
+ } catch (err) {
6689
+ toast({ title: "Network error", description: String(err), variant: "destructive" });
6690
+ } finally {
6691
+ setAgentRequestLoading(false);
6692
+ }
6693
+ }, [execution, getExecution]);
6694
+ const rerunAgent = useCallback8(() => {
6695
+ const input = agentData?.original_input || actionInput || (() => {
6696
+ const msgs = agentData?.input?.messages || [];
6697
+ const m = msgs.find((m2) => m2?.role === "user" && !String(m2?.role).includes("USER CONTEXT"));
6698
+ return m?.content || "";
6699
+ })();
6700
+ if (!input) {
6701
+ toast({ title: "Nothing to rerun", description: "No original input found for this execution.", variant: "destructive" });
6702
+ return;
6703
+ }
6704
+ setActionInput(input);
6705
+ submitInput(input);
6706
+ }, [agentData, actionInput, submitInput]);
6707
+ const getFormUrl = useCallback8((decisionId) => {
6708
+ const wfId = execution?.workflow?.id;
6709
+ const auth = execution?.authorization;
6710
+ const execId = execution?.execution_id;
6711
+ const sourceNode = agentActionResult?.action?.id;
6712
+ if (!wfId || !auth || !execId || !sourceNode || !decisionId) return null;
6713
+ const backend = apiBaseUrl || (typeof window !== "undefined" ? window.location.origin : "");
6714
+ const params = new URLSearchParams({
6715
+ authorization: auth,
6716
+ reference_execution: execId,
6717
+ source_node: sourceNode,
6718
+ decision_id: decisionId,
6719
+ ...backend ? { backend_url: backend } : {}
6720
+ });
6721
+ return `/forms/${wfId}?${params.toString()}`;
6722
+ }, [execution, agentActionResult, apiBaseUrl]);
6723
+ const rerunDecision = useCallback8(async (decision) => {
6724
+ if (!execution?.execution_id) {
6725
+ toast({ title: "No execution loaded", description: "Cannot rerun this decision.", variant: "destructive" });
6726
+ return;
6727
+ }
6728
+ if (!agentActionResult?.action) {
6729
+ toast({ title: "Missing action context", description: "Could not locate the agent action node.", variant: "destructive" });
6730
+ return;
6731
+ }
6732
+ const decisionId = decision?.run_details?.id;
6733
+ if (!decisionId) {
6734
+ toast({ title: "Missing decision id", description: "This decision cannot be rerun.", variant: "destructive" });
6735
+ return;
6736
+ }
6737
+ const body = { ...agentActionResult.action };
6738
+ body.source_execution = execution.execution_id;
6739
+ body.source_workflow = execution.workflow?.id;
6740
+ setAgentRequestLoading(true);
6741
+ try {
6742
+ const resp = await fetch(resolveUrl(`/api/v1/apps/agent/run?rerun=true&decision_id=${encodeURIComponent(decisionId)}`), {
6743
+ method: "POST",
6744
+ credentials: "include",
6745
+ headers: { "Content-Type": "application/json", ...resolveHeaders() },
6746
+ body: JSON.stringify(body)
6747
+ });
6748
+ const json = await resp.json().catch(() => ({}));
6749
+ if (json?.success === false) {
6750
+ toast({ title: "Rerun failed", description: json.reason || "Try again later.", variant: "destructive" });
6751
+ } else {
6752
+ toast({ title: "Rerunning decision", description: "The agent will continue from this step." });
6753
+ setTimeout(() => getExecution(execution.execution_id, execution.authorization), 800);
6754
+ setTimeout(() => getExecution(execution.execution_id, execution.authorization), 5e3);
6755
+ }
6756
+ } catch (err) {
6757
+ toast({ title: "Network error", description: String(err), variant: "destructive" });
6758
+ } finally {
6759
+ setAgentRequestLoading(false);
6760
+ }
6761
+ }, [execution, agentActionResult, getExecution]);
6762
+ const { timeline, originalStartTime, totalDuration, finishDecisionId, finishAnswer } = useMemo5(() => {
6763
+ const toSec = (t) => {
6764
+ const n = Number(t) || 0;
6765
+ return n > 1e12 ? Math.floor(n / 1e3) : n;
6766
+ };
6767
+ const overallStatus = (execution?.status || agentData?.status || "").toUpperCase();
6768
+ const runIsFinished = ["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"].includes(overallStatus);
6769
+ const runEndSec = toSec(agentData?.completed_at || execution?.completed_at);
6770
+ let fallbackEnd = Math.floor(Date.now() / 1e3);
6771
+ if (runIsFinished) {
6772
+ let maxKnown = runEndSec || 0;
6773
+ for (const dec of agentData?.decisions || []) {
6774
+ const rd = dec.run_details || {};
6775
+ maxKnown = Math.max(maxKnown, toSec(rd.completed_at), toSec(rd.started_at));
6776
+ }
6777
+ fallbackEnd = maxKnown || fallbackEnd;
6778
+ }
6779
+ const items = [
6780
+ {
6781
+ label: "AI Agent",
6782
+ type: "agent",
6783
+ category: "agent",
6784
+ details: agentData,
6785
+ status: execution?.status || agentData?.status,
6786
+ start_time: toSec(agentData?.started_at || execution?.started_at),
6787
+ end_time: toSec(agentData?.completed_at || execution?.completed_at)
6788
+ }
6789
+ ];
6790
+ let finishId = "";
6791
+ let finishAns = "";
6792
+ for (const dec of agentData?.decisions || []) {
6793
+ const rd = dec.run_details || {};
6794
+ items.push({
6795
+ label: dec.action,
6796
+ type: "decision",
6797
+ category: dec.category,
6798
+ status: rd.status,
6799
+ start_time: toSec(rd.started_at) || 0,
6800
+ end_time: toSec(rd.completed_at) || fallbackEnd,
6801
+ details: dec
6802
+ });
6803
+ if (dec.action === "finish" || dec.category === "finish" || dec.details?.action === "finalise" || dec.action === "finalise") {
6804
+ finishId = rd.id || "";
6805
+ finishAns = dec.reason || "";
6806
+ if (Array.isArray(dec.fields) && dec.fields.length > 0) {
6807
+ finishAns = dec.fields[0]?.value || finishAns;
6808
+ }
6809
+ }
6810
+ }
6811
+ items.sort((a, b) => (a.start_time || 0) - (b.start_time || 0));
6812
+ const decisionItems = items.filter((it) => it.type === "decision");
6813
+ const runStart = items.find((it) => it.type === "agent")?.start_time || 0;
6814
+ const processingRows = [];
6815
+ let prevEnd = runStart;
6816
+ for (const dec of decisionItems) {
6817
+ const decStart = dec.start_time || 0;
6818
+ const gap = decStart - prevEnd;
6819
+ if (prevEnd > 0 && decStart > 0 && gap >= 0.5) {
6820
+ processingRows.push({
6821
+ label: "Thinking",
6822
+ type: "decision",
6823
+ category: "processing",
6824
+ status: "FINISHED",
6825
+ start_time: prevEnd,
6826
+ end_time: decStart,
6827
+ details: void 0
6828
+ });
6829
+ }
6830
+ prevEnd = dec.end_time || decStart;
6831
+ }
6832
+ items.push(...processingRows);
6833
+ items.sort((a, b) => (a.start_time || 0) - (b.start_time || 0));
6834
+ const start = items.reduce((acc, it) => Math.min(acc, it.start_time || acc), Infinity);
6835
+ const end = items.reduce((acc, it) => Math.max(acc, it.end_time || acc), 0);
6836
+ const startSafe = start === Infinity ? 0 : start;
6837
+ const total = Math.max(1, end - startSafe);
6838
+ return { timeline: items, originalStartTime: startSafe, totalDuration: total, finishDecisionId: finishId, finishAnswer: finishAns };
6839
+ }, [agentData, execution?.status, execution?.started_at, execution?.completed_at]);
6840
+ const toggleOpen = (i) => setOpenIndexes((prev) => {
6841
+ const next = new Set(prev);
6842
+ if (next.has(i)) next.delete(i);
6843
+ else next.add(i);
6844
+ return next;
6845
+ });
6846
+ const onKeyDown = (e) => {
6847
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
6848
+ e.preventDefault();
6849
+ submitInput(actionInput);
6850
+ }
6851
+ };
6852
+ const activeTab = showStarter ? "start" : viewMode;
6853
+ const hasExecution = !!execution?.execution_id;
6854
+ const showRunSwitcher = hasExecution || agentRequestLoading;
6855
+ const goToTab = (t) => {
6856
+ if (t === "start") {
6857
+ setShowStarter(true);
6858
+ } else {
6859
+ setShowStarter(false);
6860
+ setViewMode(t);
6861
+ }
6862
+ };
6863
+ const tabBar = /* @__PURE__ */ jsxs12(Box11, { sx: {
6864
+ display: "flex",
6865
+ alignItems: "center",
6866
+ gap: 1.5,
6867
+ p: 1,
6868
+ borderRadius: 999,
6869
+ border: "1px solid hsl(var(--border))",
6870
+ bgcolor: "hsl(var(--card))",
6871
+ width: "fit-content",
6872
+ alignSelf: "center"
6873
+ }, children: [
6874
+ /* @__PURE__ */ jsx14(Box11, { sx: { display: "inline-flex", gap: 0.25, p: 0.25, borderRadius: 999, bgcolor: "hsl(var(--muted) / 0.6)" }, children: ["start", "simple", "detailed"].map((t) => {
6875
+ const active = activeTab === t;
6876
+ const label = t === "start" ? "Start" : t === "simple" ? "Simple" : "Detailed";
6877
+ return /* @__PURE__ */ jsx14(
6878
+ Box11,
6879
+ {
6880
+ component: "button",
6881
+ type: "button",
6882
+ onClick: () => goToTab(t),
6883
+ sx: {
6884
+ all: "unset",
6885
+ cursor: "pointer",
6886
+ px: 1.75,
6887
+ py: 0.5,
6888
+ borderRadius: 999,
6889
+ fontSize: "0.8rem",
6890
+ fontWeight: 600,
6891
+ color: active ? "hsl(var(--primary-foreground))" : "hsl(var(--muted-foreground))",
6892
+ bgcolor: active ? "hsl(var(--primary))" : "transparent",
6893
+ transition: "background 0.12s ease, color 0.12s ease",
6894
+ "&:hover": active ? {} : { color: "hsl(var(--foreground))", bgcolor: "hsl(var(--muted))" }
6895
+ },
6896
+ children: label
6897
+ },
6898
+ t
6899
+ );
6900
+ }) }),
6901
+ /* @__PURE__ */ jsx14(Tooltip6, { title: "Reload execution data", children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
6902
+ IconButton6,
6903
+ {
6904
+ size: "small",
6905
+ onClick: () => execution?.execution_id && execution?.authorization && getExecution(execution.execution_id, execution.authorization),
6906
+ disabled: !hasExecution,
6907
+ sx: {
6908
+ width: 30,
6909
+ height: 30,
6910
+ color: "hsl(var(--muted-foreground))",
6911
+ "&:hover": { color: "hsl(var(--foreground))", bgcolor: "hsl(var(--muted))" }
6912
+ },
6913
+ children: /* @__PURE__ */ jsx14(RefreshIcon, { sx: { fontSize: 16 } })
6914
+ }
6915
+ ) }) })
6916
+ ] });
6917
+ return /* @__PURE__ */ jsx14(Box11, { sx: { width: "100%", display: "flex", justifyContent: "center", pb: 4 }, children: /* @__PURE__ */ jsxs12(Box11, { sx: { width: "100%", maxWidth, display: "flex", flexDirection: "column", gap: 3 }, children: [
6918
+ showRunSwitcher && tabBar,
6919
+ showStarter ? /* @__PURE__ */ jsxs12(
6920
+ Box11,
6921
+ {
6922
+ component: "form",
6923
+ onSubmit: (e) => {
6924
+ e.preventDefault();
6925
+ submitInput(actionInput);
6926
+ },
6927
+ sx: { display: "flex", flexDirection: "column", alignItems: "center", gap: compact ? 2 : 3, py: compact ? 2 : 4 },
6928
+ children: [
6929
+ !hideHeroIcon && !compact && /* @__PURE__ */ jsx14(Box11, { sx: {
6930
+ width: heroIconSize,
6931
+ height: heroIconSize,
6932
+ borderRadius: 3,
6933
+ bgcolor: "hsl(var(--card))",
6934
+ border: "1px solid hsl(var(--border))",
6935
+ display: "flex",
6936
+ alignItems: "center",
6937
+ justifyContent: "center",
6938
+ boxShadow: "0 8px 24px rgba(0,0,0,0.25)"
6939
+ }, children: heroIcon ?? /* @__PURE__ */ jsx14(AgentIcon_default, { size: Math.round(heroIconSize * 0.67) }) }),
6940
+ /* @__PURE__ */ jsx14(Typography11, { component: "h1", sx: {
6941
+ fontSize: compact ? { xs: "1.25rem", md: "1.5rem" } : { xs: "1.75rem", md: "2.25rem" },
6942
+ fontWeight: 600,
6943
+ color: "hsl(var(--foreground))",
6944
+ textAlign: "center",
6945
+ letterSpacing: "-0.01em"
6946
+ }, children: title }),
6947
+ subtitle && /* @__PURE__ */ jsx14(Typography11, { sx: {
6948
+ fontSize: "0.95rem",
6949
+ color: "hsl(var(--muted-foreground))",
6950
+ textAlign: "center",
6951
+ mt: -1,
6952
+ maxWidth: 600
6953
+ }, children: subtitle }),
6954
+ /* @__PURE__ */ jsxs12(Box11, { sx: {
6955
+ width: "100%",
6956
+ display: "flex",
6957
+ flexDirection: "column",
6958
+ gap: 1,
6959
+ borderRadius: attachedImages.length > 0 ? 4 : 999,
6960
+ border: "1.5px solid hsl(var(--border))",
6961
+ bgcolor: "hsl(var(--card))",
6962
+ px: 3,
6963
+ py: 1.75,
6964
+ transition: "border-color 0.15s ease, box-shadow 0.15s ease, border-radius 0.15s ease",
6965
+ "&:focus-within": {
6966
+ borderColor: "hsl(var(--primary))",
6967
+ boxShadow: "0 0 0 3px hsla(var(--primary) / 0.12)"
6968
+ }
6969
+ }, children: [
6970
+ attachedImages.length > 0 && /* @__PURE__ */ jsx14(Box11, { sx: { display: "flex", flexWrap: "wrap", gap: 0.75 }, children: attachedImages.map((img, idx) => /* @__PURE__ */ jsxs12(Box11, { sx: {
6971
+ display: "inline-flex",
6972
+ alignItems: "center",
6973
+ gap: 1,
6974
+ p: 0.5,
6975
+ pr: 1,
6976
+ borderRadius: 1.5,
6977
+ border: "1px solid hsl(var(--border))",
6978
+ bgcolor: "hsl(var(--background))",
6979
+ maxWidth: "100%"
6980
+ }, children: [
6981
+ /* @__PURE__ */ jsx14(Box11, { component: "img", src: img.dataUrl, alt: img.name, sx: { width: 32, height: 32, borderRadius: 1, objectFit: "cover", flexShrink: 0 } }),
6982
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.72rem", color: "hsl(var(--foreground))", maxWidth: 190, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: img.name }),
6983
+ /* @__PURE__ */ jsx14(IconButton6, { size: "small", onClick: () => setAttachedImages((prev) => prev.filter((_, i) => i !== idx)), sx: { p: 0.25, color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--destructive))" } }, "aria-label": "Remove attached image", children: /* @__PURE__ */ jsx14(CloseIcon4, { sx: { fontSize: 12 } }) })
6984
+ ] }, `${img.name}-${idx}`)) }),
6985
+ /* @__PURE__ */ jsxs12(Box11, { sx: { display: "flex", alignItems: "flex-end", gap: 1, width: "100%" }, children: [
6986
+ /* @__PURE__ */ jsx14(
6987
+ InputBase2,
6988
+ {
6989
+ inputRef,
6990
+ autoFocus: true,
6991
+ multiline: true,
6992
+ minRows: 1,
6993
+ maxRows: 6,
6994
+ fullWidth: true,
6995
+ value: actionInput,
6996
+ onChange: (e) => setActionInput(e.target.value),
6997
+ placeholder,
6998
+ onKeyDown,
6999
+ onPaste: (e) => {
7000
+ const items = e.clipboardData?.items;
7001
+ if (!items) return;
7002
+ const files = [];
7003
+ for (const item of Array.from(items)) {
7004
+ if (item.kind === "file" && item.type.startsWith("image/")) {
7005
+ const file = item.getAsFile();
7006
+ if (file) files.push(file);
7007
+ }
7008
+ }
7009
+ if (files.length > 0) {
7010
+ e.preventDefault();
7011
+ handleImagesSelected(files);
7012
+ }
7013
+ },
7014
+ disabled: agentRequestLoading,
7015
+ sx: {
7016
+ fontSize: "1rem",
7017
+ color: "hsl(var(--foreground))",
7018
+ "& textarea::placeholder": { color: "hsl(var(--muted-foreground))", opacity: 0.7 }
7019
+ }
7020
+ }
7021
+ ),
7022
+ /* @__PURE__ */ jsx14(
7023
+ "input",
7024
+ {
7025
+ ref: fileInputRef,
7026
+ type: "file",
7027
+ accept: "image/*",
7028
+ multiple: true,
7029
+ style: { display: "none" },
7030
+ onChange: (e) => {
7031
+ handleImagesSelected(e.target.files);
7032
+ if (e.target) e.target.value = "";
7033
+ }
7034
+ }
7035
+ ),
7036
+ !hideAttach && /* @__PURE__ */ jsx14(
7037
+ IconButton6,
7038
+ {
7039
+ type: "button",
7040
+ onClick: () => fileInputRef.current?.click(),
7041
+ disabled: agentRequestLoading,
7042
+ title: attachedImages.length > 0 ? `Add image (${attachedImages.length} attached)` : "Attach image",
7043
+ sx: {
7044
+ width: 36,
7045
+ height: 36,
7046
+ color: attachedImages.length > 0 ? "hsl(var(--primary))" : "hsl(var(--muted-foreground))",
7047
+ bgcolor: attachedImages.length > 0 ? "hsla(var(--primary) / 0.1)" : "transparent",
7048
+ "&:hover": { color: "hsl(var(--foreground))", bgcolor: "hsl(var(--muted))" }
7049
+ },
7050
+ children: /* @__PURE__ */ jsx14(AttachFileIcon, { sx: { fontSize: 18 } })
7051
+ }
7052
+ ),
7053
+ /* @__PURE__ */ jsx14(Tooltip6, { title: submitTooltip, placement: "top", arrow: true, children: /* @__PURE__ */ jsx14("span", { children: /* @__PURE__ */ jsx14(
7054
+ IconButton6,
7055
+ {
7056
+ type: "submit",
7057
+ disabled: actionInput.trim().length < 3 || agentRequestLoading,
7058
+ sx: {
7059
+ width: 36,
7060
+ height: 36,
7061
+ bgcolor: actionInput.trim().length >= 3 ? "hsl(var(--primary))" : "hsl(var(--muted))",
7062
+ color: actionInput.trim().length >= 3 ? "hsl(var(--primary-foreground))" : "hsl(var(--muted-foreground))",
7063
+ "&:hover": actionInput.trim().length >= 3 ? { filter: "brightness(1.1)", bgcolor: "hsl(var(--primary))" } : {},
7064
+ "&.Mui-disabled": { bgcolor: "hsl(var(--muted))", color: "hsl(var(--muted-foreground))" }
7065
+ },
7066
+ children: agentRequestLoading ? /* @__PURE__ */ jsx14(CircularProgress4, { size: 16, sx: { color: "inherit" } }) : submitIcon ?? /* @__PURE__ */ jsx14(PlayArrowRoundedIcon2, {})
7067
+ }
7068
+ ) }) })
7069
+ ] })
7070
+ ] }),
7071
+ !hideAppPicker && /* @__PURE__ */ jsx14(Box11, { sx: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs12(Box11, { sx: {
7072
+ display: "inline-flex",
7073
+ flexWrap: "wrap",
7074
+ alignItems: "center",
7075
+ gap: 0.5,
7076
+ p: 0.5,
7077
+ borderRadius: 999,
7078
+ border: "1px solid hsl(var(--border))",
7079
+ bgcolor: "hsl(var(--card))",
7080
+ maxWidth: "100%"
7081
+ }, children: [
7082
+ /* @__PURE__ */ jsxs12(
7083
+ Box11,
7084
+ {
7085
+ component: "button",
7086
+ type: "button",
7087
+ onClick: () => setAppSearchOpen(true),
7088
+ sx: {
7089
+ all: "unset",
7090
+ cursor: "pointer",
7091
+ display: "inline-flex",
7092
+ alignItems: "center",
7093
+ gap: 0.5,
7094
+ px: 1.5,
7095
+ py: 0.5,
7096
+ borderRadius: 999,
7097
+ fontSize: "0.8rem",
7098
+ fontWeight: 500,
7099
+ color: "hsl(var(--muted-foreground))",
7100
+ bgcolor: "transparent",
7101
+ transition: "color 0.12s ease, background-color 0.12s ease",
7102
+ "&:hover": { color: "hsl(var(--foreground))", bgcolor: "hsl(var(--muted) / 0.5)" }
7103
+ },
7104
+ children: [
7105
+ /* @__PURE__ */ jsx14(AddIcon2, { sx: { fontSize: 14 } }),
7106
+ appPickerLabel
7107
+ ]
7108
+ }
7109
+ ),
7110
+ chosenApps.map((app, i) => /* @__PURE__ */ jsxs12(
7111
+ Box11,
7112
+ {
7113
+ sx: {
7114
+ display: "inline-flex",
7115
+ alignItems: "center",
7116
+ gap: 0.5,
7117
+ pl: 0.5,
7118
+ pr: 0.75,
7119
+ py: 0.25,
7120
+ borderRadius: 999,
7121
+ bgcolor: "hsl(var(--muted) / 0.6)",
7122
+ fontSize: "0.8rem",
7123
+ color: "hsl(var(--foreground))"
7124
+ },
7125
+ children: [
7126
+ /* @__PURE__ */ jsx14(
7127
+ Avatar6,
7128
+ {
7129
+ src: app.icon || void 0,
7130
+ alt: app.name,
7131
+ variant: "rounded",
7132
+ sx: { width: 18, height: 18, bgcolor: "transparent" }
7133
+ }
7134
+ ),
7135
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.8rem", mx: 0.25, textTransform: "capitalize" }, children: app.name.replace(/_/g, " ") }),
7136
+ /* @__PURE__ */ jsx14(
7137
+ IconButton6,
7138
+ {
7139
+ size: "small",
7140
+ onClick: () => setChosenApps((prev) => prev.filter((_, idx) => idx !== i)),
7141
+ sx: { p: 0.125, color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--destructive))" } },
7142
+ children: /* @__PURE__ */ jsx14(CloseIcon4, { sx: { fontSize: 12 } })
7143
+ }
7144
+ )
7145
+ ]
7146
+ },
7147
+ `${app.name}-${i}`
7148
+ ))
7149
+ ] }) }),
7150
+ error && /* @__PURE__ */ jsx14(Box11, { sx: {
7151
+ width: "100%",
7152
+ p: 1.5,
7153
+ borderRadius: 1.5,
7154
+ border: "1px solid hsl(var(--destructive) / 0.4)",
7155
+ bgcolor: "hsl(var(--destructive) / 0.08)",
7156
+ color: "hsl(var(--destructive))",
7157
+ fontSize: "0.85rem"
7158
+ }, children: error })
7159
+ ]
7160
+ }
7161
+ ) : /* @__PURE__ */ jsxs12(Box11, { children: [
7162
+ /* @__PURE__ */ jsxs12(Box11, { sx: {
7163
+ display: "flex",
7164
+ alignItems: "center",
7165
+ gap: 2,
7166
+ p: 2,
7167
+ borderRadius: 2,
7168
+ border: "1px solid hsl(var(--border))",
7169
+ bgcolor: "hsl(var(--card))",
7170
+ mb: 2
7171
+ }, children: [
7172
+ /* @__PURE__ */ jsxs12(Box11, { sx: { flex: 1, minWidth: 0 }, children: [
7173
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.85rem", color: "hsl(var(--foreground))", fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: agentData?.original_input || actionInput || "Agent run" }),
7174
+ /* @__PURE__ */ jsxs12(Typography11, { sx: { fontSize: "0.7rem", color: "hsl(var(--muted-foreground))" }, children: [
7175
+ "Status: ",
7176
+ execution?.status || agentData?.status || "\u2014",
7177
+ " \xB7 ",
7178
+ execution?.execution_id?.slice(0, 8) || ""
7179
+ ] })
7180
+ ] }),
7181
+ /* @__PURE__ */ jsx14(AvatarGroup, { max: 6, sx: { "& .MuiAvatar-root": { width: 28, height: 28, borderColor: "hsl(var(--border))" } }, children: chosenApps.map((app, i) => /* @__PURE__ */ jsx14(Tooltip6, { title: app.name.replace(/_/g, " "), children: /* @__PURE__ */ jsx14(
7182
+ Avatar6,
7183
+ {
7184
+ src: app.icon || void 0,
7185
+ alt: app.name,
7186
+ variant: "rounded",
7187
+ onClick: () => navigate(`/apps/${encodeURIComponent(app.name.toLowerCase().replace(/\s+/g, "_"))}`),
7188
+ sx: {
7189
+ bgcolor: "hsl(var(--muted))",
7190
+ cursor: "pointer",
7191
+ transition: "transform 0.15s ease, border-color 0.15s ease",
7192
+ "&:hover": { transform: "scale(1.08)", borderColor: "hsl(var(--primary)) !important" }
7193
+ }
7194
+ }
7195
+ ) }, i)) })
7196
+ ] }),
7197
+ error && /* @__PURE__ */ jsx14(Box11, { sx: {
7198
+ p: 1.5,
7199
+ borderRadius: 1.5,
7200
+ mb: 2,
7201
+ border: "1px solid hsl(var(--destructive) / 0.4)",
7202
+ bgcolor: "hsl(var(--destructive) / 0.08)",
7203
+ color: "hsl(var(--destructive))",
7204
+ fontSize: "0.85rem"
7205
+ }, children: error }),
7206
+ viewMode === "simple" && /* @__PURE__ */ jsx14(Box11, { sx: {
7207
+ borderRadius: 2,
7208
+ border: "1px solid hsl(var(--border))",
7209
+ bgcolor: "hsl(var(--card))",
7210
+ p: 2.5,
7211
+ display: "flex",
7212
+ flexDirection: "column",
7213
+ gap: 1.5
7214
+ }, children: (() => {
7215
+ const status = (execution?.status || agentData?.status || "EXECUTING").toUpperCase();
7216
+ const decisionCount = (agentData?.decisions || []).length;
7217
+ const isRunning = !["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"].includes(status);
7218
+ const rawStartedAt = agentData?.started_at || execution?.started_at || 0;
7219
+ const startedAtSec = rawStartedAt > 1e12 ? Math.floor(rawStartedAt / 1e3) : rawStartedAt;
7220
+ const effectiveStart = startedAtSec || localRunStart || 0;
7221
+ let durationSec = null;
7222
+ if (isRunning && effectiveStart) {
7223
+ durationSec = Math.max(0, nowTick - effectiveStart);
7224
+ } else if (totalDuration && totalDuration > 0) {
7225
+ durationSec = Math.round(totalDuration);
7226
+ }
7227
+ const pendingAsk = (agentData?.decisions || []).slice().reverse().find((d) => {
7228
+ const isAsk = d.category === "ask" || d.action === "ask";
7229
+ const st = (d.run_details?.status || "").toUpperCase();
7230
+ return isAsk && (st === "RUNNING" || st === "WAITING");
7231
+ });
7232
+ const pendingQuestions = [];
7233
+ if (pendingAsk) {
7234
+ for (const f of pendingAsk.fields || []) {
7235
+ if (f.key === "question" && f.value) {
7236
+ pendingQuestions.push({ question: f.value, index: pendingQuestions.length + 1 });
7237
+ }
7238
+ }
7239
+ }
7240
+ const pendingAnswered = pendingQuestions.every((q) => questionAnswers[q.question]?.value);
7241
+ return /* @__PURE__ */ jsxs12(Fragment7, { children: [
7242
+ /* @__PURE__ */ jsxs12(Box11, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
7243
+ isRunning ? /* @__PURE__ */ jsx14(CircularProgress4, { size: 16, sx: { color: "hsl(var(--primary))" } }) : status === "FINISHED" ? /* @__PURE__ */ jsx14(CheckCircleIcon3, { sx: { fontSize: 18, color: "hsl(142 70% 45%)" } }) : /* @__PURE__ */ jsx14(ErrorIcon, { sx: { fontSize: 18, color: "hsl(var(--destructive))" } }),
7244
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.9rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: isRunning ? "Agent is working\u2026" : status === "FINISHED" ? "Run finished" : `Run ${status.toLowerCase()}` }),
7245
+ /* @__PURE__ */ jsxs12(Typography11, { sx: { fontSize: "0.75rem", color: "hsl(var(--muted-foreground))" }, children: [
7246
+ decisionCount,
7247
+ " step",
7248
+ decisionCount === 1 ? "" : "s",
7249
+ durationSec != null ? ` \xB7 ${durationSec}s` : ""
7250
+ ] })
7251
+ ] }),
7252
+ finishAnswer ? /* @__PURE__ */ jsx14(Box11, { sx: {
7253
+ p: 2,
7254
+ borderRadius: 1.5,
7255
+ border: "1px solid hsl(var(--border))",
7256
+ bgcolor: "hsl(var(--background))",
7257
+ fontSize: "0.9rem",
7258
+ color: "hsl(var(--foreground))",
7259
+ "& > *:first-of-type": { mt: 0 },
7260
+ "& > *:last-child": { mb: 0 },
7261
+ "& p": { my: 1, lineHeight: 1.55 },
7262
+ "& h1, & h2, & h3, & h4": { mt: 2, mb: 1, fontWeight: 600, lineHeight: 1.3 },
7263
+ "& h1": { fontSize: "1.15rem" },
7264
+ "& h2": { fontSize: "1.05rem" },
7265
+ "& h3, & h4": { fontSize: "0.95rem" },
7266
+ "& ul": { my: 1, pl: 3, listStyleType: "disc", listStylePosition: "outside" },
7267
+ "& ol": { my: 1, pl: 3, listStyleType: "decimal", listStylePosition: "outside" },
7268
+ "& ul ul": { listStyleType: "circle" },
7269
+ "& ul ul ul": { listStyleType: "square" },
7270
+ "& li": { my: 0.25, display: "list-item" },
7271
+ "& li::marker": { color: "hsl(var(--muted-foreground))" },
7272
+ "& a": { color: "hsl(var(--primary))", textDecoration: "underline" },
7273
+ "& code": {
7274
+ px: 0.5,
7275
+ py: 0.125,
7276
+ borderRadius: 0.5,
7277
+ bgcolor: "hsl(var(--muted))",
7278
+ fontFamily: '"JetBrains Mono", ui-monospace, monospace',
7279
+ fontSize: "0.82em"
7280
+ },
7281
+ "& pre": {
7282
+ p: 1.5,
7283
+ my: 1,
7284
+ borderRadius: 1,
7285
+ bgcolor: "hsl(var(--muted))",
7286
+ overflowX: "auto",
7287
+ fontSize: "0.82rem"
7288
+ },
7289
+ "& pre code": { p: 0, bgcolor: "transparent" },
7290
+ "& blockquote": {
7291
+ borderLeft: "3px solid hsl(var(--border))",
7292
+ pl: 1.5,
7293
+ my: 1,
7294
+ color: "hsl(var(--muted-foreground))"
7295
+ },
7296
+ "& table": { borderCollapse: "collapse", my: 1, fontSize: "0.85rem" },
7297
+ "& th, & td": { border: "1px solid hsl(var(--border))", px: 1, py: 0.5 },
7298
+ "& hr": { border: 0, borderTop: "1px solid hsl(var(--border))", my: 1.5 }
7299
+ }, children: /* @__PURE__ */ jsx14(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(finishAnswer) }) }) : pendingAsk && pendingQuestions.length > 0 ? (() => {
7300
+ const trySimpleSubmit = () => {
7301
+ if (agentRequestLoading) return;
7302
+ if (!pendingAnswered) {
7303
+ setSimpleSubmitAttempted(true);
7304
+ return;
7305
+ }
7306
+ if (pendingAsk.run_details?.id) {
7307
+ submitQuestions(pendingAsk.run_details.id, questionAnswers);
7308
+ }
7309
+ };
7310
+ return /* @__PURE__ */ jsxs12(Box11, { sx: { display: "flex", flexDirection: "column", gap: 1.5 }, children: [
7311
+ pendingQuestions.map((q, qi) => {
7312
+ const value = questionAnswers[q.question]?.value || "";
7313
+ const isMissing = simpleSubmitAttempted && !value;
7314
+ return /* @__PURE__ */ jsxs12(Box11, { children: [
7315
+ /* @__PURE__ */ jsx14(Box11, { sx: { fontSize: "0.9rem", color: "hsl(var(--foreground))", mb: 1, "& p": { my: 0.5 } }, children: /* @__PURE__ */ jsx14(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(q.question) }) }),
7316
+ /* @__PURE__ */ jsx14(
7317
+ TextField4,
7318
+ {
7319
+ fullWidth: true,
7320
+ multiline: true,
7321
+ minRows: 2,
7322
+ placeholder: "Your answer here\u2026",
7323
+ value,
7324
+ error: isMissing,
7325
+ helperText: isMissing ? "Please answer this question" : void 0,
7326
+ onChange: (e) => {
7327
+ const v = e.target.value;
7328
+ setQuestionAnswers((prev) => ({
7329
+ ...prev,
7330
+ [q.question]: { index: qi, value: v }
7331
+ }));
7332
+ },
7333
+ onKeyDown: (e) => {
7334
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
7335
+ e.preventDefault();
7336
+ trySimpleSubmit();
7337
+ }
7338
+ },
7339
+ size: "small",
7340
+ sx: { "& .MuiOutlinedInput-root": { bgcolor: "hsl(var(--background))" } }
7341
+ }
7342
+ )
7343
+ ] }, qi);
7344
+ }),
7345
+ /* @__PURE__ */ jsxs12(Box11, { sx: { display: "flex", alignItems: "center", gap: 1 }, children: [
7346
+ /* @__PURE__ */ jsx14(
7347
+ Button5,
7348
+ {
7349
+ variant: "contained",
7350
+ size: "small",
7351
+ disabled: agentRequestLoading,
7352
+ onClick: trySimpleSubmit,
7353
+ children: agentRequestLoading ? /* @__PURE__ */ jsx14(CircularProgress4, { size: 16 }) : "Submit"
7354
+ }
7355
+ ),
7356
+ pendingAsk.run_details?.id && getFormUrl(pendingAsk.run_details.id) && /* @__PURE__ */ jsx14(Tooltip6, { title: "Answer in the Form UI", placement: "right", children: /* @__PURE__ */ jsx14(
7357
+ IconButton6,
7358
+ {
7359
+ size: "small",
7360
+ onClick: () => {
7361
+ const url = getFormUrl(pendingAsk.run_details.id);
7362
+ if (url) window.open(url, "_blank", "noopener,noreferrer");
7363
+ },
7364
+ sx: { color: "hsl(var(--muted-foreground))", "&:hover": { color: "hsl(var(--primary))" } },
7365
+ children: /* @__PURE__ */ jsx14(OpenInNewIcon2, { sx: { fontSize: 18 } })
7366
+ }
7367
+ ) })
7368
+ ] })
7369
+ ] });
7370
+ })() : isRunning ? /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.85rem", color: "hsl(var(--muted-foreground))" }, children: "Waiting for the agent to produce the first step." }) : /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.85rem", color: "hsl(var(--muted-foreground))" }, children: "No final answer was returned. Open Detailed to inspect each step." }),
7371
+ !isRunning && /* @__PURE__ */ jsx14(Box11, { children: /* @__PURE__ */ jsx14(
7372
+ Button5,
7373
+ {
7374
+ size: "small",
7375
+ variant: "text",
7376
+ onClick: () => setViewMode("detailed"),
7377
+ sx: { color: "hsl(var(--primary))", textTransform: "none", px: 0 },
7378
+ children: "View detailed timeline \u2192"
7379
+ }
7380
+ ) })
7381
+ ] });
7382
+ })() }),
7383
+ viewMode === "detailed" && (() => {
7384
+ const detailedStatus = (execution?.status || agentData?.status || "EXECUTING").toUpperCase();
7385
+ const detailedIsRunning = !["FINISHED", "FAILURE", "ABORTED", "CANCELLED", "CANCELED"].includes(detailedStatus);
7386
+ const detailedRunFinished = !detailedIsRunning;
7387
+ return /* @__PURE__ */ jsx14(Box11, { sx: {
7388
+ borderRadius: 2,
7389
+ border: "1px solid hsl(var(--border))",
7390
+ bgcolor: "hsl(var(--card))",
7391
+ overflow: "hidden"
7392
+ }, children: timeline.length === 0 || timeline.length === 1 && agentRequestLoading ? /* @__PURE__ */ jsxs12(Box11, { sx: { p: 4, textAlign: "center", color: "hsl(var(--muted-foreground))", fontSize: "0.85rem" }, children: [
7393
+ /* @__PURE__ */ jsx14(CircularProgress4, { size: 20, sx: { mb: 1 } }),
7394
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.85rem" }, children: "Waiting for agent response\u2026" })
7395
+ ] }) : /* @__PURE__ */ jsxs12(Fragment7, { children: [
7396
+ timeline.map((item, i) => /* @__PURE__ */ jsx14(
7397
+ TimelineRow,
7398
+ {
7399
+ item,
7400
+ index: i,
7401
+ open: openIndexes.has(i),
7402
+ onToggle: () => toggleOpen(i),
7403
+ appsById,
7404
+ totalDuration,
7405
+ originalStartTime,
7406
+ maxWidth: 260,
7407
+ questionAnswers,
7408
+ setQuestionAnswers,
7409
+ onSubmitQuestions: submitQuestions,
7410
+ onRerunAgent: rerunAgent,
7411
+ onRerunDecision: rerunDecision,
7412
+ agentRequestLoading,
7413
+ getFormUrl,
7414
+ runFinished: detailedRunFinished
7415
+ },
7416
+ i
7417
+ )),
7418
+ detailedRunFinished && /* @__PURE__ */ jsxs12(Box11, { sx: {
7419
+ borderTop: "1px solid hsl(var(--border))",
7420
+ p: 2.5,
7421
+ display: "flex",
7422
+ flexDirection: "column",
7423
+ gap: 1.5,
7424
+ bgcolor: "hsl(var(--muted) / 0.2)"
7425
+ }, children: [
7426
+ /* @__PURE__ */ jsxs12(Box11, { sx: { display: "flex", alignItems: "center", gap: 1, flexWrap: "wrap" }, children: [
7427
+ detailedStatus === "FINISHED" ? /* @__PURE__ */ jsx14(CheckCircleIcon3, { sx: { fontSize: 18, color: "hsl(142 70% 45%)" } }) : /* @__PURE__ */ jsx14(ErrorIcon, { sx: { fontSize: 18, color: "hsl(var(--destructive))" } }),
7428
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.9rem", fontWeight: 600, color: "hsl(var(--foreground))" }, children: detailedStatus === "FINISHED" ? "Run finished" : `Run ${detailedStatus.toLowerCase()}` })
7429
+ ] }),
7430
+ finishAnswer && /* @__PURE__ */ jsx14(Box11, { sx: {
7431
+ p: 2,
7432
+ borderRadius: 1.5,
7433
+ border: "1px solid hsl(var(--border))",
7434
+ bgcolor: "hsl(var(--background))",
7435
+ fontSize: "0.9rem",
7436
+ color: "hsl(var(--foreground))",
7437
+ "& > *:first-of-type": { mt: 0 },
7438
+ "& > *:last-child": { mb: 0 },
7439
+ "& p": { my: 1, lineHeight: 1.55 },
7440
+ "& a": { color: "hsl(var(--primary))", textDecoration: "underline" },
7441
+ "& code": {
7442
+ px: 0.5,
7443
+ py: 0.125,
7444
+ borderRadius: 0.5,
7445
+ bgcolor: "hsl(var(--muted))",
7446
+ fontFamily: '"JetBrains Mono", ui-monospace, monospace',
7447
+ fontSize: "0.82em"
7448
+ },
7449
+ "& pre": {
7450
+ p: 1.5,
7451
+ my: 1,
7452
+ borderRadius: 1,
7453
+ bgcolor: "hsl(var(--muted))",
7454
+ overflowX: "auto",
7455
+ fontSize: "0.82rem"
7456
+ },
7457
+ "& pre code": { p: 0, bgcolor: "transparent" }
7458
+ }, children: /* @__PURE__ */ jsx14(Markdown, { remarkPlugins: [remarkGfm4, remarkBreaks], children: normalizeMarkdown(finishAnswer) }) })
7459
+ ] })
7460
+ ] }) });
7461
+ })(),
7462
+ finishDecisionId && /* @__PURE__ */ jsx14(Box11, { sx: { mt: 3, display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs12(Box11, { sx: { width: "100%", maxWidth: 640 }, children: [
7463
+ /* @__PURE__ */ jsx14(Typography11, { sx: { fontSize: "0.75rem", color: "hsl(var(--muted-foreground))", mb: 0.75, textAlign: "center" }, children: "Continue this agent run with more details" }),
7464
+ /* @__PURE__ */ jsxs12(
7465
+ Box11,
7466
+ {
7467
+ component: "form",
7468
+ onSubmit: (e) => {
7469
+ e.preventDefault();
7470
+ if (continuationText.trim()) {
7471
+ submitQuestions(finishDecisionId, { continue: continuationText }, true);
7472
+ }
7473
+ },
7474
+ sx: {
7475
+ display: "flex",
7476
+ alignItems: "flex-end",
7477
+ gap: 1,
7478
+ p: 1.25,
7479
+ borderRadius: 999,
7480
+ border: "1.5px solid hsl(var(--border))",
7481
+ bgcolor: "hsl(var(--card))",
7482
+ "&:focus-within": {
7483
+ borderColor: "hsl(var(--primary))",
7484
+ boxShadow: "0 0 0 3px hsla(var(--primary) / 0.12)"
7485
+ }
7486
+ },
7487
+ children: [
7488
+ /* @__PURE__ */ jsx14(
7489
+ InputBase2,
7490
+ {
7491
+ fullWidth: true,
7492
+ multiline: true,
7493
+ minRows: 1,
7494
+ maxRows: 4,
7495
+ placeholder: continuationPlaceholder,
7496
+ value: continuationText,
7497
+ onChange: (e) => setContinuationText(e.target.value),
7498
+ onKeyDown: (e) => {
7499
+ if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
7500
+ e.preventDefault();
7501
+ if (continuationText.trim() && !agentRequestLoading) {
7502
+ submitQuestions(finishDecisionId, { continue: continuationText }, true);
7503
+ }
7504
+ }
7505
+ },
7506
+ disabled: agentRequestLoading,
7507
+ sx: { fontSize: "0.9rem", color: "hsl(var(--foreground))", px: 2 }
7508
+ }
7509
+ ),
7510
+ /* @__PURE__ */ jsx14(
7511
+ IconButton6,
7512
+ {
7513
+ type: "submit",
7514
+ disabled: !continuationText.trim() || agentRequestLoading,
7515
+ sx: {
7516
+ width: 36,
7517
+ height: 36,
7518
+ bgcolor: continuationText.trim() && !agentRequestLoading ? "hsl(var(--primary))" : "hsl(var(--muted))",
7519
+ color: continuationText.trim() && !agentRequestLoading ? "hsl(var(--primary-foreground))" : "hsl(var(--muted-foreground))",
7520
+ "&:hover": continuationText.trim() && !agentRequestLoading ? { filter: "brightness(1.1)", bgcolor: "hsl(var(--primary))" } : {}
7521
+ },
7522
+ children: agentRequestLoading ? /* @__PURE__ */ jsx14(CircularProgress4, { size: 16, sx: { color: "inherit" } }) : /* @__PURE__ */ jsx14(SendIcon, { sx: { fontSize: 18 } })
7523
+ }
7524
+ )
7525
+ ]
7526
+ }
7527
+ )
7528
+ ] }) })
7529
+ ] }),
7530
+ /* @__PURE__ */ jsx14(
7531
+ AppSearchDrawer,
7532
+ {
7533
+ open: appSearchOpen,
7534
+ onClose: () => setAppSearchOpen(false),
7535
+ title: appPickerTitle,
7536
+ subtitle: appPickerSubtitle,
7537
+ onQuickSelect: (app) => {
7538
+ const known = availableApps.find((a) => a.name?.toLowerCase() === app.name?.toLowerCase());
7539
+ setChosenApps(
7540
+ (prev) => prev.some((a) => a.name === app.name) ? prev : [...prev, { name: app.name, icon: app.icon || known?.icon, id: app.id || known?.id || void 0 }]
7541
+ );
7542
+ }
7543
+ }
7544
+ )
7545
+ ] }) });
7546
+ };
7547
+ var AgentUI_default = AgentUI;
7548
+
7549
+ // useAppLookup.ts
7550
+ import { useEffect as useEffect8, useMemo as useMemo6, useState as useState11 } from "react";
7551
+ var norm = (s) => s.toLowerCase().replace(/[\s_\-]+/g, "_");
7552
+ function useAppLookup(appName) {
7553
+ const [loading, setLoading] = useState11(false);
7554
+ const [info, setInfo] = useState11(null);
7555
+ const [algoliaId, setAlgoliaId] = useState11(null);
7556
+ const {
7557
+ authStates,
7558
+ authenticatedApps,
7559
+ handleAuthChange,
7560
+ handleTestConnection,
7561
+ handleSaveAuth,
7562
+ refreshAuth
7563
+ } = useAppAuth();
7564
+ useEffect8(() => {
5528
7565
  if (!appName) {
5529
7566
  setInfo(null);
5530
7567
  setAlgoliaId(null);
@@ -5609,13 +7646,13 @@ function useAppLookup(appName) {
5609
7646
  setLoading(false);
5610
7647
  })();
5611
7648
  }, [appName]);
5612
- const matchingEntries = useMemo5(() => {
7649
+ const matchingEntries = useMemo6(() => {
5613
7650
  if (!appName) return [];
5614
7651
  return authenticatedApps.filter(
5615
7652
  (auth) => auth.app?.name && norm(auth.app.name) === norm(appName)
5616
7653
  );
5617
7654
  }, [appName, authenticatedApps]);
5618
- const image = useMemo5(() => {
7655
+ const image = useMemo6(() => {
5619
7656
  if (info?.image) return info.image;
5620
7657
  for (const entry of matchingEntries) {
5621
7658
  const img = entry.app?.large_image || entry.large_image;
@@ -5623,7 +7660,7 @@ function useAppLookup(appName) {
5623
7660
  }
5624
7661
  return "";
5625
7662
  }, [info, matchingEntries]);
5626
- const algoliaApp = useMemo5(() => {
7663
+ const algoliaApp = useMemo6(() => {
5627
7664
  if (!appName) return null;
5628
7665
  return {
5629
7666
  objectID: algoliaId || appName,
@@ -5655,6 +7692,7 @@ function useAppLookup(appName) {
5655
7692
  }
5656
7693
  export {
5657
7694
  API_CONFIG,
7695
+ AgentUI_default as AgentUI,
5658
7696
  AppAuthSection,
5659
7697
  AppDetailDrawer,
5660
7698
  AppDetailProvider,