Fixed agentUI reference
This commit is contained in:
@@ -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
|
||||
|
||||
+18
-18
@@ -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=
|
||||
|
||||
@@ -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={
|
||||
<ChatBot
|
||||
serverside={serverside}
|
||||
serverside={false}
|
||||
cookies={cookies}
|
||||
removeCookie={removeCookie}
|
||||
isLoaded={isLoaded}
|
||||
@@ -813,7 +817,7 @@ const App = (message, props) => {
|
||||
path="/conversation"
|
||||
element={
|
||||
<ChatBot
|
||||
serverside={serverside}
|
||||
serverside={false}
|
||||
cookies={cookies}
|
||||
removeCookie={removeCookie}
|
||||
isLoaded={isLoaded}
|
||||
@@ -861,7 +865,7 @@ const App = (message, props) => {
|
||||
path="/agents"
|
||||
element={
|
||||
<AgentUI
|
||||
serverside={serverside}
|
||||
serverside={false}
|
||||
isLoaded={isLoaded}
|
||||
isLoggedIn={isLoggedIn}
|
||||
globalUrl={globalUrl}
|
||||
|
||||
@@ -0,0 +1,542 @@
|
||||
import React, { useState, useEffect, useContext, memo } from "react";
|
||||
import { Context } from "../context/ContextApi.jsx";
|
||||
import { getTheme } from "../theme.jsx";
|
||||
import { toast } from "react-toastify"
|
||||
import ReactJson from "react-json-view-ssr";
|
||||
import { validateJson, collapseField, handleReactJsonClipboard, HandleJsonCopy } from "../views/Workflows.jsx";
|
||||
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Typography,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Tooltip,
|
||||
IconButton,
|
||||
} from '@mui/material'
|
||||
|
||||
import {
|
||||
CheckCircle as CheckCircleIcon,
|
||||
HourglassDisabled as HourglassDisabledIcon,
|
||||
RestartAlt as RestartAltIcon,
|
||||
ExpandMore as ExpandMoreIcon,
|
||||
ExpandLess as ExpandLessIcon,
|
||||
} from '@mui/icons-material'
|
||||
|
||||
import {
|
||||
green,
|
||||
red,
|
||||
} from '../views/AngularWorkflow.jsx'
|
||||
|
||||
const AgentUI = (props) => {
|
||||
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" ?
|
||||
<CircularProgress size={20} style={{marginRight: 10, }} />
|
||||
:
|
||||
item.status === "FINISHED" ?
|
||||
<Tooltip title="Finished" placement="top">
|
||||
<CheckCircleIcon style={{color: green, marginRight: 10, }} />
|
||||
</Tooltip>
|
||||
:
|
||||
<Tooltip title={`Not started yet: ${item.status}`} placement="top">
|
||||
<HourglassDisabledIcon style={{marginRight: 10, }} />
|
||||
</Tooltip>
|
||||
|
||||
const categoryStyle = {
|
||||
width: 20,
|
||||
height: 20,
|
||||
marginRight: 10,
|
||||
}
|
||||
|
||||
const parsedCategory = item.category === "singul" ?
|
||||
<Tooltip title="Singul" placement="top">
|
||||
<img src="/images/logos/singul.svg" style={categoryStyle} />
|
||||
</Tooltip>
|
||||
: item.category === "ask" ?
|
||||
<Tooltip title="Ask" placement="top">
|
||||
<img src="/images/workflows/UserInput2.svg" style={categoryStyle} />
|
||||
</Tooltip>
|
||||
:
|
||||
<div style={categoryStyle} />
|
||||
|
||||
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 (
|
||||
<div
|
||||
style={{
|
||||
minHeight: 45,
|
||||
cursor: hovered ? "pointer" : "default",
|
||||
borderTop: "1px solid " + theme.palette.surfaceColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
backgroundColor: hovered ? theme.palette.surfaceColor : "inherit",
|
||||
}}
|
||||
onMouseEnter={() => 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])
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div style={{minWidth: 50, maxWidth: 50, paddingTop: defaultTopPadding, }}>
|
||||
{parsedStatus}
|
||||
</div>
|
||||
<div style={{minWidth: 50, maxWidth: 50, paddingTop: defaultTopPadding, }}>
|
||||
{parsedCategory}
|
||||
</div>
|
||||
<div style={{minWidth: 200, maxWidth: 200, paddingTop: defaultTopPadding, }}>
|
||||
{/* To ISO string from unix time */}
|
||||
{new Date(item.start_time * 1000).toLocaleString()}
|
||||
</div>
|
||||
<div style={{minWidth: 100, maxWidth: 100, paddingTop: defaultTopPadding-5, }}>
|
||||
<Chip
|
||||
label={item.type}
|
||||
/>
|
||||
</div>
|
||||
<div style={{
|
||||
minWidth: 200,
|
||||
maxWidth: 200,
|
||||
paddingTop: defaultTopPadding,
|
||||
}}>
|
||||
{item.label}
|
||||
</div>
|
||||
|
||||
<Tooltip title={`Time taken: ${currentDuration*-1} seconds. Started: ${new Date(item.start_time * 1000).toLocaleString()}\nFinished: ${new Date(item.end_time * 1000).toLocaleString()}`} placement="right">
|
||||
<div style={{
|
||||
minWidth: maxTimelineWidth,
|
||||
maxWidth: maxTimelineWidth,
|
||||
paddingTop: defaultTopPadding*1.3,
|
||||
}}>
|
||||
{currentDuration !== 0 && !isNaN(timelineMarginLeft) && !isNaN(timelineWidth) && timelineWidth > 0 ?
|
||||
<div style={{
|
||||
backgroundColor: item.status === "FINISHED" ?
|
||||
green : item.status === "RUNNING" || item.status === "" ?
|
||||
theme.palette.main : theme.palette.surfaceColor,
|
||||
|
||||
marginLeft: timelineMarginLeft,
|
||||
minWidth: timelineWidth,
|
||||
maxWidth: timelineWidth,
|
||||
height: 10,
|
||||
}} />
|
||||
: null}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<div style={{
|
||||
minWidth: 100,
|
||||
maxWidth: 100,
|
||||
display: "flex",
|
||||
}}>
|
||||
<Tooltip title="Rerun JUST this decision. This can be used if an agent decision action somehow stopped and didn't get a result." placement="left">
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={item.type !== "decision" || disableButtons}
|
||||
style={{marginLeft: 20, }}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
toast.info("Attempting to rerun this decision by itself.")
|
||||
setDisableButtons(true)
|
||||
RerunDecision(item.details)
|
||||
}}
|
||||
>
|
||||
<RestartAltIcon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip title="Explore results" placement="right">
|
||||
<span>
|
||||
<IconButton
|
||||
disabled={item.details === undefined || item.details === null || item.details === ""}
|
||||
style={{marginLeft: 10, }}
|
||||
>
|
||||
{open ?
|
||||
<ExpandLessIcon />
|
||||
:
|
||||
<ExpandMoreIcon />
|
||||
}
|
||||
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{open ?
|
||||
<div style={{marginTop: 10, marginBottom: 10, }}>
|
||||
{validate.valid === true ?
|
||||
<ReactJson
|
||||
src={validate.result}
|
||||
theme={theme.palette.jsonTheme}
|
||||
style={theme.palette.reactJsonStyle}
|
||||
shouldCollapse={(jsonField) => {
|
||||
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}
|
||||
/>
|
||||
:
|
||||
<code>
|
||||
{item.details}
|
||||
</code>
|
||||
}
|
||||
</div>
|
||||
: null }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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 (
|
||||
<div style={{marginTop: 20, }}>
|
||||
{/*
|
||||
<div style={{display: "flex", }}>
|
||||
{agent_data?.status === "RUNNING" || agent_data?.status === "WAITING" ?
|
||||
<CircularProgress size={20} style={{marginRight: 10, }} />
|
||||
:
|
||||
agent_data?.status === "FINISHED" ?
|
||||
<CheckCircleIcon style={{color: green, marginRight: 10, }} />
|
||||
:
|
||||
<HourglassDisabledIcon style={{marginRight: 10, }} />
|
||||
}
|
||||
|
||||
<Typography variant="h6" style={{marginLeft: 20, }}>
|
||||
{agent_data?.status}
|
||||
</Typography>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
<div style={{marginTop: 10, }} />
|
||||
{timelineItems?.map((item, index) => {
|
||||
return (
|
||||
<TimelineItem
|
||||
item={item}
|
||||
index={index}
|
||||
key={index}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={agentWrapperStyle}>
|
||||
{/*
|
||||
<Typography variant="h4">
|
||||
Agent Input: {data.input}
|
||||
</Typography>
|
||||
*/}
|
||||
|
||||
<ButtonGroup style={{marginTop: 50, }}>
|
||||
<Button
|
||||
variant={buttonState === "default" ? "contained" : "outlined"}
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
setButtonState("default");
|
||||
}}
|
||||
>
|
||||
Default
|
||||
</Button>
|
||||
<Button
|
||||
variant={buttonState === "timeline" ? "contained" : "outlined"}
|
||||
color="secondary"
|
||||
onClick={() => {
|
||||
setButtonState("timeline");
|
||||
}}
|
||||
>
|
||||
Timeline
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
|
||||
{buttonState === "timeline" ?
|
||||
<TimelineRender agent_data={data} />
|
||||
:
|
||||
null
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default AgentUI
|
||||
Reference in New Issue
Block a user