From 6316fb8888740f5d08bc9a98d7791035ab258c4a Mon Sep 17 00:00:00 2001 From: Frikky Date: Mon, 19 May 2025 00:22:11 +0200 Subject: [PATCH] Fixed agentUI reference --- backend/go-app/go.mod | 16 +- backend/go-app/go.sum | 36 +-- frontend/src/App.jsx | 10 +- frontend/src/views/AgentUI.jsx | 542 +++++++++++++++++++++++++++++++++ 4 files changed, 575 insertions(+), 29 deletions(-) create mode 100644 frontend/src/views/AgentUI.jsx diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index 6e354ef6..c630b9ff 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -22,7 +22,7 @@ require ( github.com/gorilla/mux v1.8.1 github.com/h2non/filetype v1.1.3 github.com/satori/go.uuid v1.2.0 - github.com/shuffle/shuffle-shared v0.8.50 + github.com/shuffle/shuffle-shared v0.8.58 golang.org/x/crypto v0.37.0 google.golang.org/api v0.228.0 google.golang.org/grpc v1.71.1 @@ -69,7 +69,7 @@ require ( github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/frikky/schemaless v0.0.13 // indirect + github.com/frikky/schemaless v0.0.16 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -114,7 +114,7 @@ require ( github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect - github.com/sashabaranov/go-openai v1.19.2 // indirect + github.com/sashabaranov/go-openai v1.40.0 // indirect github.com/sendgrid/rest v2.6.9+incompatible // indirect github.com/sendgrid/sendgrid-go v3.14.0+incompatible // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect @@ -136,12 +136,12 @@ require ( go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/proto/otlp v1.5.0 // indirect go4.org v0.0.0-20201209231011-d4a079459e60 // indirect - golang.org/x/net v0.37.0 // indirect + golang.org/x/net v0.38.0 // indirect golang.org/x/oauth2 v0.28.0 // indirect - golang.org/x/sync v0.12.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/term v0.30.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/sync v0.13.0 // indirect + golang.org/x/sys v0.32.0 // indirect + golang.org/x/term v0.31.0 // indirect + golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.11.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect diff --git a/backend/go-app/go.sum b/backend/go-app/go.sum index ca216f74..e4b4e8e0 100644 --- a/backend/go-app/go.sum +++ b/backend/go-app/go.sum @@ -148,8 +148,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frikky/kin-openapi v0.42.0 h1:d5Z6vnuQ6RnCCPIxZaDL+TH2ODLxT8abytOt+Zh+Kd0= github.com/frikky/kin-openapi v0.42.0/go.mod h1:ev9OZAw7Bv5p0w93j91++6a1ElPzGcCofst+kmrWsj4= -github.com/frikky/schemaless v0.0.13 h1:ARiN9V7wr2VZXAr9JK5wvTbyPgpGrgeiL1VhR5MlgaQ= -github.com/frikky/schemaless v0.0.13/go.mod h1:mooDxY+D6weHjhKvjy3+IE9S7P4g4cpNnidkdRv/cHQ= +github.com/frikky/schemaless v0.0.16 h1:4d2ZktB9xGsAusbbKliOI8TuriSrdIMzD/6ToY3wkz8= +github.com/frikky/schemaless v0.0.16/go.mod h1:jT48kTcmr1q3o8i+8qe7g+eCsbwaz2Q9CjOJevQQzQs= github.com/fsouza/go-dockerclient v1.12.1 h1:FMoLq+Zhv9Oz/rFmu6JWkImfr6CBgZOPcL+bHW4gS0o= github.com/fsouza/go-dockerclient v1.12.1/go.mod h1:OqsgJJcpCwqyM3JED7TdfM9QVWS5O7jSYwXxYKmOooY= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= @@ -331,8 +331,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk= -github.com/sashabaranov/go-openai v1.19.2 h1:+dkuCADSnwXV02YVJkdphY8XD9AyHLUWwk6V7LB6EL8= -github.com/sashabaranov/go-openai v1.19.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.40.0 h1:Peg9Iag5mUJtPW00aYatlsn97YML0iNULiLNe74iPrU= +github.com/sashabaranov/go-openai v1.40.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekueiEMJ7NEoxJo0= @@ -341,8 +341,8 @@ github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fc github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shuffle/shuffle-shared v0.8.50 h1:Sy6o7Nrcd3QG+m28775STKS3uOfaXDzDcctTuaYfdYQ= -github.com/shuffle/shuffle-shared v0.8.50/go.mod h1:z+ISGBgNINmZvWNrtGTc51yVG+pMkpBFu9ZLVlTyuag= +github.com/shuffle/shuffle-shared v0.8.58 h1:QzCKtQjuaozb+xyLkw6IjwqCNVWzpuJJnxkpXkLCP9M= +github.com/shuffle/shuffle-shared v0.8.58/go.mod h1:OLAwH/Ym4941Jn5DF1oZaq6iBpmjG2SNrTZ9Xqck5So= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -412,8 +412,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= -golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -463,8 +463,8 @@ golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -480,8 +480,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -507,14 +507,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= -golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -525,8 +525,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 2192be04..8f718150 100755 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -18,6 +18,10 @@ import Apps2 from "./views/Apps2.jsx"; import AppCreator from "./views/AppCreator.jsx"; import DetectionDashBoard from "./views/DetectionDashboard.jsx"; +// LLM related tests +import ChatBot from "./components/ChatBot.jsx"; +import AgentUI from "./views/AgentUI.jsx"; + import Welcome from "./views/Welcome.jsx"; import Dashboard from "./views/Dashboard.jsx"; import DashboardView from "./views/DashboardViews.jsx"; @@ -796,7 +800,7 @@ const App = (message, props) => { path="/chat" element={ { path="/conversation" element={ { path="/agents" element={ { + const { globalUrl, isLoggedIn, isLoaded, userdata, } = props + const [buttonState, setButtonState] = useState("timeline") + const [execution, setExecution] = useState(null) + const [agentActionResult, setAgentActionResult] = useState(null) + const [data, setData] = useState({}) + const [openIndexes, setOpenIndexes] = useState([]) + const [disableButtons, setDisableButtons] = useState(false) + + const [originalStartTime, setOriginalStartTime] = useState(0) + const [latestEndTime, setLatestEndTime] = useState(0) + + const {themeMode} = useContext(Context) + const theme = getTheme(themeMode) + + const agentWrapperStyle = { + width: 1000, + height: 1000, + margin: "auto", + paddingTop: 100, + } + + if (data.input === undefined || data.input === null) { + data.input = "" + } else { + const verifiedInput = validateJson(data.input) + if (verifiedInput.valid === true) { + data.input = JSON.stringify(verifiedInput.result, null, 2) + } + } + + const findNodeData = (execution_data, node_id) => { + if (execution_data === undefined || execution_data === null) { + return + } + + var found = false + for (var key in execution_data.results) { + const item = execution_data.results[key] + if (item?.action?.id !== node_id) { + continue + } + + setAgentActionResult(item) + + found = true + const validate = validateJson(item.result) + if (validate.valid) { + setData(validate.result) + } else { + toast.warn("Action output result is not valid JSON!") + } + + break + } + + if (found === false) { + toast.warn("Failed to find the relevant AI Agent result") + } + } + + const GetExecution = (execution_id, node_id, authorization) => { + if (execution_id === undefined || execution_id === null) { + toast.error("No execution ID provided. Please provide execution_id in the URL.") + return + } + + if (node_id === undefined || node_id === null) { + toast.error("No node ID provided. Please provide node_id in the URL.") + return + } + + if (authorization === undefined || authorization === null) { + toast.error("No authorization provided. Please provide authorization in the URL.") + return + } + + const headers = {} + const executionRequest = { + "execution_id": execution_id, + "authorization": authorization, + } + + const url = `${globalUrl}/api/v1/streams/results` + fetch(url, { + method: "POST", + headers: headers, + body: JSON.stringify(executionRequest), + credentials: "include", + cors: "no-cors", + }) + .then((response) => { + return response.json() + }) + .then((responseJson) => { + if (responseJson.success !== false) { + if (responseJson.status === "EXECUTING") { + // Recursively looking for updates until it's not executing anymore + setTimeout(() => { + GetExecution(execution_id, node_id, authorization) + }, 3000) + } else { + setDisableButtons(false) + setDisableButtons(false) + } + + setExecution(responseJson) + findNodeData(responseJson, node_id) + } else { + setDisableButtons(false) + if (responseJson.reason === undefined || responseJson.reason === null) { + toast.error("Failed to load the agent data. Please try again and contact support@shuffler.io if this persists") + } else { + toast.error("Error: " + responseJson.reason) + } + } + }) + .catch((error) => { + setDisableButtons(false) + toast.error("Error: " + error) + }) + } + + const RerunDecision = (decision) => { + if (execution.execution_id === undefined || execution.execution_id === null) { + toast.error("No workflow run loaded. Please try again and contact support@shuffler.io if this persists.") + return + } + + if (agentActionResult === undefined || agentActionResult === null) { + toast.error("Failed to find the relevant agent action. Please try again, and contact support@shuffler.io if it persists.") + return + } + + console.log("DECISION: ", decision) + + const url = `${globalUrl}/api/v1/apps/agent/run?rerun=true&decision_id=${decision?.run_details?.id}` + var body = agentActionResult.action + body.source_execution = execution.execution_id + body.source_workflow = execution.workflow.id + + fetch(url, { + method: "POST", + body: JSON.stringify(body), + credentials: "include", + cors: "no-cors", + }) + .then((response) => { + return response.json() + }) + .then((responseJson) => { + console.log("RESP: ", responseJson) + if (responseJson.success !== false) { + } else { + if (responseJson.reason === undefined || responseJson.reason === null) { + toast.warn("Failed to restart the agent decision. Please try again and contact support@shuffler.io if this persists") + } else { + toast.warn(responseJson.reason) + + } + } + + GetExecution(execution.execution_id, agentActionResult.action.id, execution.authorization) + }) + .catch((error) => { + toast.error("Error: " + error) + }) + } + + useEffect(() => { + const params = new URLSearchParams(window.location.search) + const executionId = params.get("execution_id") + const nodeId = params.get("node_id") + const authorization = params.get("authorization") + if (executionId !== undefined && executionId !== null && nodeId !== undefined && nodeId !== null && authorization !== undefined && authorization !== null) { + GetExecution(executionId, nodeId, authorization) + } else { + toast.warn("No execution ID or node ID provided. Please provide execution_id and node_id in the URL.") + } + }, []) + + const maxTimelineWidth = 150 + const TimelineItem = (props) => { + const { item, index } = props; + const [hovered, setHovered] = useState(false); + + const parsedStatus = item.status === "RUNNING" || item.status === "WAITING" ? + + : + item.status === "FINISHED" ? + + + + : + + + + + const categoryStyle = { + width: 20, + height: 20, + marginRight: 10, + } + + const parsedCategory = item.category === "singul" ? + + + + : item.category === "ask" ? + + + + : +
+ + const validate = validateJson(item.details) + const itemStartTime = item.start_time + var itemEndTime = item.end_time + if (itemStartTime !== undefined && (itemStartTime < originalStartTime || originalStartTime === 0)) { + setOriginalStartTime(itemStartTime) + } + + if (itemEndTime !== undefined && itemEndTime > latestEndTime) { + setLatestEndTime(itemEndTime) + } + + if (itemEndTime === undefined || itemEndTime === null) { + // Set it to now + itemEndTime = latestEndTime + } + + const totalDuration = latestEndTime - originalStartTime + const currentDuration = itemStartTime - itemEndTime + var timelineMarginLeft = ((itemStartTime - originalStartTime) / totalDuration) * maxTimelineWidth + var timelineWidth = ((itemEndTime - itemStartTime) / totalDuration) * maxTimelineWidth + + if (totalDuration === currentDuration) { + timelineMarginLeft = 0 + timelineWidth = maxTimelineWidth + } + + const defaultTopPadding = 10 + const open = openIndexes.includes(index) + + return ( +
+
setHovered(true)} + onMouseLeave={() => setHovered(false)} + onClick={(e) => { + if (item.details === undefined || item.details === null || item.details === "") { + toast("No details to open") + return + } + + if (openIndexes.includes(index)) { + setOpenIndexes(openIndexes.filter((i) => i !== index)) + } else { + setOpenIndexes([...openIndexes, index]) + } + }} + > +
+ {parsedStatus} +
+
+ {parsedCategory} +
+
+ {/* To ISO string from unix time */} + {new Date(item.start_time * 1000).toLocaleString()} +
+
+ +
+
+ {item.label} +
+ + +
+ {currentDuration !== 0 && !isNaN(timelineMarginLeft) && !isNaN(timelineWidth) && timelineWidth > 0 ? +
+ : null} +
+ + +
+ + + { + e.preventDefault() + e.stopPropagation() + + toast.info("Attempting to rerun this decision by itself.") + setDisableButtons(true) + RerunDecision(item.details) + }} + > + + + + + + + + {open ? + + : + + } + + + + +
+
+ + {open ? +
+ {validate.valid === true ? + { + return collapseField(jsonField) + }} + iconStyle={theme.palette.jsonIconStyle} + collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength} + displayArrayKey={false} + enableClipboard={(copy) => { + handleReactJsonClipboard(copy); + }} + displayDataTypes={false} + onSelect={(select) => { + HandleJsonCopy(validate.result, select, "exec") + }} + name={false} + /> + : + + {item.details} + + } +
+ : null } +
+ ) + } + + const TimelineRender = (props) => { + const { agent_data } = props; + var timelineItems = [ + { + "label": "AI Agent 2", + "type": "agent", + "category": "agent", + + "status": agent_data.status, + "start_time": agent_data.started_at, + "end_time": agent_data.completed_at, + }, + ] + + var sortedTimelineItems = [] + for (var key in agent_data?.decisions) { + const item = agent_data.decisions[key] + + if (item.run_details.started_at === undefined || item.run_details.started_at === null) { + item.run_details.started_at = originalStartTime + } + + if (item.run_details.completed_at === undefined || item.run_details.completed_at === null) { + item.run_details.completed_at = Math.floor(Date.now() / 1000) + } + + var newTimelineItem = { + "label": item.action, + "type": "decision", + "category": item.category, + + "status": item.run_details.status, + "start_time": item.run_details.started_at, + "end_time": item.run_details.completed_at, + } + + newTimelineItem.details = item + timelineItems.push(newTimelineItem) + } + + timelineItems.sort((a, b) => { + if (a.start_time < b.start_time) { + return 1; + } + + return 0; + }) + + return ( +
+ {/* +
+ {agent_data?.status === "RUNNING" || agent_data?.status === "WAITING" ? + + : + agent_data?.status === "FINISHED" ? + + : + + } + + + {agent_data?.status} + +
+ */} + +
+ {timelineItems?.map((item, index) => { + return ( + + ) + })} + +
+ ) + } + + return ( +
+ {/* + + Agent Input: {data.input} + + */} + + + + + + + {buttonState === "timeline" ? + + : + null + } +
+ ) +} + +export default AgentUI