From 906a0b8660d702a454d4aaa87c97f8c5e73d3a55 Mon Sep 17 00:00:00 2001 From: Gabe Hamilton Date: Fri, 23 Feb 2024 16:18:37 -0700 Subject: [PATCH] Release AI Nexus agent features (#663) --- .github/workflows/release_notes.yml | 2 +- src/AI/Agent/AgentCard.jsx | 180 ++++++++ src/AI/Agent/AgentChat.jsx | 398 ++++++++++++++++++ .../Agent}/AgentCreate.jsx | 16 +- src/AI/Agent/AgentDetails.jsx | 118 ++++++ .../Agent}/AgentHeader.jsx | 17 +- src/AI/Agent/AgentSummary.jsx | 265 ++++++++++++ .../AgentPage.jsx => AI/Nexus.jsx} | 19 +- src/ComponentDetails/Sidebar.jsx | 4 +- src/DIG/InputSelect.jsx | 1 + src/Entities/AgentFramework/AgentCard.jsx | 98 ----- src/Entities/AgentFramework/AgentChat.jsx | 107 ----- .../QueryApi/DataPlatformIndexerStatuses.jsx | 8 +- src/Entities/Template/EntityList.jsx | 14 +- 14 files changed, 1013 insertions(+), 234 deletions(-) create mode 100644 src/AI/Agent/AgentCard.jsx create mode 100644 src/AI/Agent/AgentChat.jsx rename src/{Entities/AgentFramework => AI/Agent}/AgentCreate.jsx (94%) create mode 100644 src/AI/Agent/AgentDetails.jsx rename src/{Entities/AgentFramework => AI/Agent}/AgentHeader.jsx (95%) create mode 100644 src/AI/Agent/AgentSummary.jsx rename src/{Entities/AgentFramework/AgentPage.jsx => AI/Nexus.jsx} (80%) delete mode 100644 src/Entities/AgentFramework/AgentCard.jsx delete mode 100644 src/Entities/AgentFramework/AgentChat.jsx rename src/{ => Entities}/QueryApi/DataPlatformIndexerStatuses.jsx (90%) diff --git a/.github/workflows/release_notes.yml b/.github/workflows/release_notes.yml index 3a99c2d3..ca552164 100644 --- a/.github/workflows/release_notes.yml +++ b/.github/workflows/release_notes.yml @@ -3,7 +3,7 @@ name: Automatic Github Releases on: push: branches: - - "master" + - "main" jobs: update_release_draft: diff --git a/src/AI/Agent/AgentCard.jsx b/src/AI/Agent/AgentCard.jsx new file mode 100644 index 00000000..ccbf116e --- /dev/null +++ b/src/AI/Agent/AgentCard.jsx @@ -0,0 +1,180 @@ +const { href } = VM.require("devhub.near/widget/core.lib.url"); + +if (!href) { + return <>; +} + +const Card = styled.div` + cursor: pointer; + background-color: white; + border-radius: 0.5rem; + padding: 1.5rem; + gap: 1rem; + height: 100%; + min-height: 12rem; + + transition: all 300ms; + box-shadow: + 0 1px 3px 0 rgb(0 0 0 / 0.1), + 0 1px 2px -1px rgb(0 0 0 / 0.1); + + &:hover { + box-shadow: + 0 4px 6px -1px rgb(0 0 0 / 0.1), + 0 2px 4px -2px rgb(0 0 0 / 0.1); + } + + img.logo { + height: 6rem; + width: 6rem; + border-radius: 50%; + + object-fit: cover; + } + + h3, + p { + margin: 0; + } + + h3 { + font-size: 1.25rem; + font-weight: 600; + } + + p { + font-size: 1rem; + font-weight: 400; + } +`; +const CardBody = styled.div` + display: flex; + align-items: center; +`; +const Break = styled.div` + flex-basis: 100%; + height: 0; +`; +const Actions = styled.div` + padding-top: 16px; + display: flex; + align-items: center; + gap: 12px; +`; +const AgentCard = ({ item, editFunction }) => { + const { accountId, name, displayName, prompt, logoUrl } = item; + const imageUrl = + logoUrl ?? "https://ipfs.near.social/ipfs/bafkreibysr2mkwhb4j36h2t7mqwhynqdy4vzjfygfkfg65kuspd2bawauu"; + const chatLink = href({ + widgetSrc: `${REPL_ACCOUNT}/widget/AI.Agent.AgentChat`, + params: { src: `${accountId}/agent/${name}` }, + }); + const detailsLink = href({ + widgetSrc: `${REPL_ACCOUNT}/widget/AI.Agent.AgentDetails`, + params: { src: `${accountId}/agent/${name}` }, + }); + + const agentChatUrl = `https://${REPL_NEAR_URL}/${REPL_ACCOUNT}/widget/AI.Agent.AgentChat?src=${accountId}/agent/${item.name}`; + const editType = accountId === context.accountId ? "edit" : "fork"; + const editLabel = editType === "edit" ? "Edit" : "Fork"; + const editIcon = editType === "edit" ? "ph-bold ph-pencil-simple" : "ph-bold ph-git-fork"; + + return ( + + +
+
+ agent logo +
+ +
+

{displayName}

+

by {accountId}

+ {prompt}, + trigger:

{prompt ? prompt.substring(0, 20) : ""}...

, + }} + /> +
+
+ + + editFunction(item), + iconLeft: editIcon, + variant: "secondary", + fill: "ghost", + size: "small", + }} + /> + ), + }} + /> + + + + + + ), + }} + /> + + + + ), + }} + /> + +
+ ); +}; + +return AgentCard(props); diff --git a/src/AI/Agent/AgentChat.jsx b/src/AI/Agent/AgentChat.jsx new file mode 100644 index 00000000..1db08582 --- /dev/null +++ b/src/AI/Agent/AgentChat.jsx @@ -0,0 +1,398 @@ +const { href } = VM.require("devhub.near/widget/core.lib.url"); +const storedModel = Storage.get("agent-model"); +const storedLocalModel = Storage.get("agent-local-model"); +const storedCredentialType = Storage.get("agent-credential-type"); +const storedCredential = Storage.get("agent-credential"); +if ( + !href || + storedCredential === null || + storedModel === null || + storedLocalModel === null || + storedCredentialType === null +) { + return "Loading config..."; +} + +const { src, embedded } = props; + +const [accountId, agentType, agentName] = src.split("/") ?? [null, null, null]; +const blockHeight = blockHeight ?? "final"; + +const data = Social.getr(`${accountId}/agent/${agentName}`, blockHeight); +const agent = { accountId, name: agentName, ...data }; + +if (!data) return "Loading..."; + +const listLink = href({ + widgetSrc: `${REPL_ACCOUNT}/widget/AI.Nexus`, +}); + +const [settingsOpen, setSettingsOpen] = useState(false); +const [question, setQuestion] = useState(""); +const [loading, setLoading] = useState(false); +const [messages, setMessages] = useState([]); + +const [model, setModel] = useState(storedModel ?? "gpt-3.5-turbo"); +const [localModel, setLocalModel] = useState(storedLocalModel ?? "http://localhost:11434/api/generate"); +const [credentialType, setCredentailType] = useState(storedCredentialType ?? "openai"); +const [credential, setCredential] = useState(storedCredential ?? ""); + +useEffect(() => { + Storage.set("agent-model", model); +}, [model]); +useEffect(() => { + Storage.set("agent-local-model", localModel); +}, [localModel]); +useEffect(() => { + Storage.set("agent-credential-type", credentialType); +}, [credentialType]); +useEffect(() => { + Storage.set("agent-credential", credential); +}, [credential]); + +const toggleSettings = () => { + setSettingsOpen(!settingsOpen); +}; + +const routeApi = async (question) => { + switch (model) { + case "local": + return localAI(question); + default: + return openAI(question); + } +}; +const localAI = async (question) => { + return asyncFetch(localModel, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + responseType: "json", + body: JSON.stringify([{ role: "system", content: data.prompt }, question]), + }); +}; +const openAI = async (question) => { + return asyncFetch(`https://api.openai.com/v1/chat/completions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${credential}`, + }, + responseType: "json", + body: JSON.stringify({ + model, + messages: [ + { role: "system", content: data.prompt }, + { + role: "user", + content: question.content, + }, + ], + // max_tokens: 2048, + // temperature: 0.7, + // top_p: 1, + // n: 1, + // stop: ["\n"], + }), + }).then((response) => { + const answer = response.body.choices[0].message.content; + return answer; + }); +}; + +useEffect(() => { + if (messages.length === 0 || messages[messages.length - 1].role !== "user") { + return; + } + setLoading(true); + routeApi(...messages.slice(-1)) + .then((answer) => { + setMessages([...messages, { role: "system", content: answer }]); + }) + .finally(() => { + setLoading(false); + }); +}, [messages]); + +const submitQuestion = () => { + setMessages([...messages, { role: "user", content: question }]); + setQuestion(""); +}; +const requiresCredentials = (model) => { + return model === "gpt-4" || model === "gpt-3.5-turbo"; +}; + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 48px; + padding: 48px; +`; + +const Overview = styled.div` + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 1em; +`; + +const Header = styled.h1` + font-size: 24px; + line-height: 39px; + color: #11181c; + margin-bottom: 20px; + font-weight: 600; +`; +const Text = styled.p` + margin: 0; + font-size: 14px; + line-height: 20px; + color: ${(p) => (p.bold ? "#11181C" : "#687076")}; + font-weight: ${(p) => (p.bold ? "600" : "400")}; + font-size: ${(p) => (p.small ? "12px" : "14px")}; + + i { + margin-right: 4px; + } +`; +const Prompt = styled.p` + font-family: monospace; + font-size: 14px; + overflow-y: auto; + height: 100px; +`; +const Label = styled.span` + font-weight: 600; +`; +const Settings = styled.div` + margin-bottom: 1em; + z-index: 1000; +`; +const Controls = styled.div` + margin-bottom: 1em; +`; +const CardControl = styled.div` + cursor: pointer; + color: var(--violet8); + margin-bottom: 1em; +`; +const AllSettings = styled.div``; +const InputWrapper = styled.div` + padding-bottom: 1em; +`; +const Question = styled.input` + border-top-left-radius: 2rem; + border-bottom-left-radius: 2rem; +`; +const UserMessage = styled.div``; +const AgentMessage = styled.div` + background-color: #f9f9f9; +`; + +const renderSettings = () => { + return ( + + + Settings + + {settingsOpen && ( + + + + + {model === "local" && ( + + setLocalModel(e.target.value), + value: localModel, + }} + /> + + )} + +
+
+ +
+
+ setCredential(e.target.value), + value: credential, + type: "password", + }} + /> +
+
+
+
+ )} +
+ ); +}; + +return ( + +
+ {!embedded && ( +
+ +
+ + Agent List +
+ + +
+
+ +
+
+ + {data.prompt} + +
+
+
+
+ )} + + {renderSettings()} + {requiresCredentials(model) && credential === "" && ( +
+ To use an OpenAI model enter your OpenAI API Key in Settings or change + to another provider. +
+ )} +
+ setQuestion(e.target.value)} + onKeyPress={(e) => { + if (e.key === "Enter") { + submitQuestion(); + } + }} + placeholder="What's your question?" + autoFocus + /> + +
+
+
+ {messages.map(({ role, content }, i) => { + return ( +
+ {role === "user" && ( + + + + + )} + {role !== "user" && ( + + + + )} +
+ ); + })} + {loading && ( +
+
+
+
+ )} +
+
+
+); diff --git a/src/Entities/AgentFramework/AgentCreate.jsx b/src/AI/Agent/AgentCreate.jsx similarity index 94% rename from src/Entities/AgentFramework/AgentCreate.jsx rename to src/AI/Agent/AgentCreate.jsx index f2397be4..a8e74d9f 100644 --- a/src/Entities/AgentFramework/AgentCreate.jsx +++ b/src/AI/Agent/AgentCreate.jsx @@ -5,11 +5,10 @@ if (!typeMatch) { } const { data, onSubmit, onCancel } = props; - const onSubmitDefault = (formValues) => { const { name, ...rest } = formValues; const agent = { [name]: rest }; - Social.set({ agent: agent }); + Social.set({ agent: agent }, { force: true }); }; const onSubmitFunction = onSubmit ?? onSubmitDefault; @@ -22,7 +21,6 @@ const AgentInputsPartialSchema = { placeholder: "Choose a unique identifier for your agent. Example: travel-agent.", required: true, }, - label: "Name", order: 1, }, @@ -43,6 +41,7 @@ const AgentInputsPartialSchema = { placeholder: "The prompt for the agent.", required: true, }, + multiline: true, label: "Prompt", order: 3, }, @@ -124,19 +123,11 @@ const AgentInputsPartialSchema = { const agentInputsValidator = (formValues) => typeMatch(formValues) && Object.values(formValues).every((value) => typeof value === "string" && value.length > 0); -const AgentInputsDefaults = { - handle: "", - name: "", - tag: "", - description: "", -}; - return ( ); diff --git a/src/AI/Agent/AgentDetails.jsx b/src/AI/Agent/AgentDetails.jsx new file mode 100644 index 00000000..b38b9c6e --- /dev/null +++ b/src/AI/Agent/AgentDetails.jsx @@ -0,0 +1,118 @@ +const { href } = VM.require("devhub.near/widget/core.lib.url"); +if (!href) { + return <>; +} +let { src, tab, highlightComment } = props; +const [accountId, agentType, agentName] = src.split("/") ?? [null, null, null]; + +let agent = Social.get(`${accountId}/agent/${agentName}/**`); +const exists = !existsData || Object.keys(existsData).length > 0; + +if (!exists) { + return ( +
+ Error + Could not find: {src} +
+ ); +} + +agent = { accountId, name: agentName, ...agent }; +const { prompt } = agent; +const editType = accountId === context.accountId ? "edit" : "fork"; +const editLabel = editType === "edit" ? "Edit" : "Fork"; +const editIcon = editType === "edit" ? "ph-bold ph-pencil-simple" : "ph-bold ph-git-fork"; +const listLink = href({ + widgetSrc: `${REPL_ACCOUNT}/widget/AI.Nexus`, +}); + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 32px; + padding-bottom: 48px; +`; + +const ContentWrapper = styled.div` + display: grid; + grid-template-columns: minmax(0, 1fr) 260px; + gap: 32px; + + @media (max-width: 1200px) { + grid-template-columns: minmax(0, 1fr); + gap: 24px; + } +`; + +const Header = styled.h1` + font-size: 24px; + line-height: 39px; + color: #11181c; + margin: 0; + font-weight: 600; +`; + +const Text = styled.p` + margin: 0; + font-size: 14px; + line-height: 20px; + color: ${(p) => (p.bold ? "#11181C" : "#687076")}; + font-weight: ${(p) => (p.bold ? "600" : "400")}; + font-size: ${(p) => (p.small ? "12px" : "14px")}; + + i { + margin-right: 4px; + } +`; + +return ( + + +
+ + Agent List +
+ + + + {prompt}, + icon: "ph ph-code", + }, + { + name: editLabel, + value: "edit", + content: , + icon: editIcon, + }, + { + name: "Chat", + value: "chat", + content: , + icon: "ph ph-code", + }, + ], + }} + /> + + + +
+); diff --git a/src/Entities/AgentFramework/AgentHeader.jsx b/src/AI/Agent/AgentHeader.jsx similarity index 95% rename from src/Entities/AgentFramework/AgentHeader.jsx rename to src/AI/Agent/AgentHeader.jsx index b2993662..e2fd3adc 100644 --- a/src/Entities/AgentFramework/AgentHeader.jsx +++ b/src/AI/Agent/AgentHeader.jsx @@ -1,4 +1,14 @@ -const text = props.text; +const { text, color, alpha } = props; + +const colorToVec3 = (hexStr, alpha) => { + if (/^#([0-9A-F]{3}){1,2}$/i.test(hexStr)) { + const rbg = [hexStr.slice(1, 3), hexStr.slice(3, 5), hexStr.slice(5, 7)].map( + (x) => Math.round((parseInt(x, 16) / 255) * 1000) / 1000, + ); + return rbg.join(",") + (alpha ? "," + alpha : ",0.05"); + } + return "0.067,0.094,0.11,0.05"; +}; let src = `
@@ -60,7 +70,7 @@ html, body { varying vec3 vColor; void main() { - gl_FragColor = vec4(0.201,0.885,1.000,0.03); //;vec4( color * vColor, 1.0 ); // for changing colors + gl_FragColor = vec4(COLOR_PROPERTY); //;vec4( color * vColor, 1.0 ); // for changing colors gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord ); } @@ -409,10 +419,11 @@ class CreateParticles { return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)); } } -`; // Adapted from https://codepen.io/sanprieto/details/XWNjBdb under MIT LICENSE +`; src = src.replace("TEXT_PROPERTY", text); +src = src.replace("COLOR_PROPERTY", colorToVec3(color, alpha)); return (
diff --git a/src/AI/Agent/AgentSummary.jsx b/src/AI/Agent/AgentSummary.jsx new file mode 100644 index 00000000..60d8aecb --- /dev/null +++ b/src/AI/Agent/AgentSummary.jsx @@ -0,0 +1,265 @@ +if (!props.agent) return ""; +const { href } = VM.require("devhub.near/widget/core.lib.url"); +if (!href) { + return <>; +} + +const { agent, showActions } = props; +const { accountId, name, displayName, prompt, logoUrl, tags } = agent; + +const chatLink = href({ + widgetSrc: `${REPL_ACCOUNT}/widget/AI.Agent.AgentChat`, + params: { src: `${accountId}/agent/${name}` }, +}); +const agentChatUrl = `https://${REPL_NEAR_URL}/${REPL_ACCOUNT}/widget/AI.Agent.AgentChat?src=${accountId}/agent/${name}`; + +const size = props.size || "small"; + +const sizes = { + small: { + gap: "16px", + thumbnail: "100px", + title: "16px", + }, + large: { + gap: "16px", + thumbnail: "200px", + title: "32px", + }, +}; + +const Wrapper = styled.div``; + +const Header = styled.div` + display: flex; + align-items: center; + gap: ${(p) => sizes[p.size].gap}; + margin-bottom: 32px; + + > * { + min-width: 0; + } + + @media (max-width: 770px) { + gap: 16px; + } +`; + +const TagsWrapper = styled.div` + margin-bottom: 16px; +`; + +const Actions = styled.div` + display: flex; + gap: 12px; + flex-wrap: wrap; + margin-bottom: 16px; +`; + +const Title = styled.h1` + font-size: ${(p) => sizes[p.size].title}; + line-height: 1.2em; + color: #11181c; + margin: 0 0 8px; + font-weight: 600; + + @media (max-width: 770px) { + font-size: 16px; + margin: 0; + } +`; + +const Thumbnail = styled.div` + width: ${(p) => sizes[p.size].thumbnail}; + height: ${(p) => sizes[p.size].thumbnail}; + flex-shrink: 0; + border: 1px solid #eceef0; + border-radius: 12px; + overflow: hidden; + box-shadow: + 0px 1px 3px rgba(16, 24, 40, 0.1), + 0px 1px 2px rgba(16, 24, 40, 0.06); + + img { + object-fit: cover; + width: 100%; + height: 100%; + } + + @media (max-width: 770px) { + width: 58px; + height: 58px; + } +`; + +const sharedButtonStyles = ` + display: inline-flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + height: 32px; + border-radius: 50px; + font-weight: 600; + font-size: 12px; + line-height: 15px; + text-align: center; + cursor: pointer; + + &:hover, + &:focus { + text-decoration: none; + outline: none; + } + + i { + color: #7E868C; + } + + .bi-16 { + font-size: 16px; + } +`; + +const Button = styled.button` + ${sharedButtonStyles} + color: ${(p) => (p.primary ? "#09342E" : "#11181C")} !important; + background: ${(p) => (p.primary ? "#59E692" : "#FBFCFD")}; + border: ${(p) => "none"}; + + &:hover, + &:focus { + background: ${(p) => (p.primary ? "rgb(112 242 164)" : "#ECEDEE")}; + } +`; + +const Text = styled.p` + margin: 0; + font-size: 14px; + line-height: 20px; + color: ${(p) => (p.bold ? "#11181C" : "#687076")}; + font-weight: ${(p) => (p.bold ? "600" : "400")}; + font-size: ${(p) => (p.small ? "12px" : "14px")}; + overflow: ${(p) => (p.ellipsis ? "hidden" : "visible")}; + text-overflow: ${(p) => (p.ellipsis ? "ellipsis" : "unset")}; + white-space: ${(p) => (p.ellipsis ? "nowrap" : "")}; + + i { + margin-right: 4px; + } +`; + +return ( + +
+ + + + +
+ {displayName} + {name} + by {accountId} +
+
+ + {tags && tags.length > 0 && ( + + + + )} + + {showActions && ( + + {false && accountId === context.accountId && ( + delete(agent.name), + iconLeft: "ph-bold ph-trash", + variant: "destructive", + fill: "ghost", + size: "small", + }} + /> + ), + }} + /> + )} + + + ( + + ), + }} + />{" "} + + + + ), + }} + /> + + )} +
+); diff --git a/src/Entities/AgentFramework/AgentPage.jsx b/src/AI/Nexus.jsx similarity index 80% rename from src/Entities/AgentFramework/AgentPage.jsx rename to src/AI/Nexus.jsx index d7b9fe4b..5ad5922c 100644 --- a/src/Entities/AgentFramework/AgentPage.jsx +++ b/src/AI/Nexus.jsx @@ -61,23 +61,30 @@ const convertSnakeToPascal = (item) => { }); return item; }; -const renderItem = (item) => { +const renderItem = (item, editFunction) => { return ( ); }; -const createWidget = "${REPL_ACCOUNT}/widget/Entities.AgentFramework.AgentCreate"; -const description = "Intent is all you need"; +const createWidget = "${REPL_ACCOUNT}/widget/AI.Agent.AgentCreate"; +const description = "NEAR AI Nexus"; + +const Header = styled.h1` + font-size: 24px; + color: #11181c; + margin: 0; + font-weight: 600; +`; return (
- - + Dependencies ({dependencySources.length}) {dependencySources.length === 0 ? ( - This component has no dependencies. + This {type} has no dependencies. ) : ( {dependencySources diff --git a/src/DIG/InputSelect.jsx b/src/DIG/InputSelect.jsx index 7ac93be8..e12b0ba3 100644 --- a/src/DIG/InputSelect.jsx +++ b/src/DIG/InputSelect.jsx @@ -33,6 +33,7 @@ const Content = styled("Select.Content")` max-height: var(--radix-select-content-available-height); scroll-behavior: smooth; overflow: auto; + z-index: 1000; `; const Viewport = styled("Select.Viewport")``; diff --git a/src/Entities/AgentFramework/AgentCard.jsx b/src/Entities/AgentFramework/AgentCard.jsx deleted file mode 100644 index 2be95282..00000000 --- a/src/Entities/AgentFramework/AgentCard.jsx +++ /dev/null @@ -1,98 +0,0 @@ -const { href } = VM.require("devhub.near/widget/core.lib.url"); - -if (!href) { - return <>; -} - -const Card = styled.div` - cursor: pointer; - background-color: white; - border-radius: 0.5rem; - padding: 1.5rem; - gap: 1rem; - height: 100%; - min-height: 12rem; - - transition: all 300ms; - box-shadow: - 0 1px 3px 0 rgb(0 0 0 / 0.1), - 0 1px 2px -1px rgb(0 0 0 / 0.1); - - &:hover { - box-shadow: - 0 4px 6px -1px rgb(0 0 0 / 0.1), - 0 2px 4px -2px rgb(0 0 0 / 0.1); - } - - img.logo { - height: 6rem; - width: 6rem; - border-radius: 50%; - - object-fit: cover; - } - - h3, - p { - margin: 0; - } - - h3 { - font-size: 1.25rem; - font-weight: 600; - } - - p { - font-size: 1rem; - font-weight: 400; - } -`; -const CardBody = styled.div` - display: flex; - align-items: center; -`; -const Break = styled.div` - flex-basis: 100%; - height: 0; -`; -const Actions = styled.div` - padding-top: 16px; - display: flex; - align-items: center; - gap: 12px; -`; -const AgentCard = ({ item }) => { - const { accountId, name, displayName, prompt, logoUrl } = item; - const imageUrl = - logoUrl ?? "https://ipfs.near.social/ipfs/bafkreibysr2mkwhb4j36h2t7mqwhynqdy4vzjfygfkfg65kuspd2bawauu"; - const link = href({ - widgetSrc: `${REPL_ACCOUNT}/widget/Entities.AgentFramework.AgentChat`, - params: { src: `${accountId}/agent/${name}` }, - }); - - return ( - - -
-
- agent logo -
- -
-

{displayName}

-

by {accountId}

- {prompt}, - trigger:

{prompt ? prompt.substring(0, 20) : ""}...

, - }} - /> -
-
- -
- ); -}; - -return AgentCard(props); diff --git a/src/Entities/AgentFramework/AgentChat.jsx b/src/Entities/AgentFramework/AgentChat.jsx deleted file mode 100644 index 916bca79..00000000 --- a/src/Entities/AgentFramework/AgentChat.jsx +++ /dev/null @@ -1,107 +0,0 @@ -const [accountId, agentType, agentName] = props.src.split("/") ?? [null, null, null]; -const blockHeight = props.blockHeight ?? "final"; - -const data = Social.getr(`${accountId}/agent/${agentName}`, blockHeight); - -if (!data) return "Loading..."; - -const [question, setQuestion] = useState(""); -const [prompt, setPrompt] = useState(""); -const [loading, setLoading] = useState(false); -const [response, setResponse] = useState(""); -const [messages, setMessages] = useState([]); - -useEffect(() => { - if (messages.length === 0 || messages[messages.length - 1].role !== "user") { - return; - } - console.log(messages); - setLoading(true); - asyncFetch(`https://ai.near.social/api`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - responseType: "json", - body: JSON.stringify([{ role: "system", content: data.prompt }, ...messages.slice(-1)]), - }) - .then(({ body }) => { - setMessages([...messages, { role: "system", content: body.response }]); - }) - .finally(() => { - setLoading(false); - }); -}, [messages]); - -const submitQuestion = () => { - setMessages([...messages, { role: "user", content: question }]); - setQuestion(""); -}; - -const Wrapper = styled.div` - display: flex; - flex-direction: column; - gap: 48px; -`; - -return ( - -
-
Name: {data.displayName}
-
- Prompt:
{data.prompt}
-
- -
-
- setQuestion(e.target.value)} - onKeyPress={(e) => { - if (e.key === "Enter") { - submitQuestion(); - } - }} - placeholder="What's your question?" - autoFocus - /> - -
-
-
- {messages.map(({ role, content }, i) => { - return ( -
- {role === "user" && ( - - )} - -
- ); - })} - {loading && ( -
-
-
-
- )} -
-
-
-); diff --git a/src/QueryApi/DataPlatformIndexerStatuses.jsx b/src/Entities/QueryApi/DataPlatformIndexerStatuses.jsx similarity index 90% rename from src/QueryApi/DataPlatformIndexerStatuses.jsx rename to src/Entities/QueryApi/DataPlatformIndexerStatuses.jsx index 9254875e..0f02c361 100644 --- a/src/QueryApi/DataPlatformIndexerStatuses.jsx +++ b/src/Entities/QueryApi/DataPlatformIndexerStatuses.jsx @@ -1,6 +1,7 @@ const GRAPHQL_ENDPOINT = props.GRAPHQL_ENDPOINT || "https://near-queryapi.api.pagoda.co"; const indexerAccount = props.indexerAccount || "dataplatform.near"; +const indexerAccountLink = indexerAccount.replace(".", "_"); const indexerFilter = props.indexerFilter || null; const fullFilter = indexerFilter ? indexerAccount + "/" + indexerFilter : indexerAccount; @@ -88,7 +89,12 @@ return ( ))} -
{errors}
+ + Explore Data +
); diff --git a/src/Entities/Template/EntityList.jsx b/src/Entities/Template/EntityList.jsx index 9e03cd0d..a6e394ad 100644 --- a/src/Entities/Template/EntityList.jsx +++ b/src/Entities/Template/EntityList.jsx @@ -13,13 +13,19 @@ const [sort, setSort] = useState(""); const [items, setItems] = useState([]); const [totalItems, setTotalItems] = useState(0); const [showCreateModal, setShowCreateModal] = useState(false); +const [activeItem, setActiveItem] = useState(null); const closeModal = () => { + setActiveItem(null); setShowCreateModal(false); }; const toggleModal = () => { setShowCreateModal(!showCreateModal); }; +const editFunction = (item) => { + setActiveItem(item); + setShowCreateModal(true); +}; const onLoad = (newItems, totalItems) => { setItems([...items, ...newItems]); setTotalItems(totalItems); @@ -111,9 +117,9 @@ return (
-

+

{totalItems} {entityType + (totalItems > 1 ? "s" : "")} -

+ {description && {description}}
{context.accountId && ( @@ -133,7 +139,7 @@ return ( src="${REPL_ACCOUNT}/widget/DIG.Dialog" props={{ type: "dialog", - description: , + description: , onOpenChange: closeModal, open: showCreateModal, contentStyles: dialogStyles, @@ -161,7 +167,7 @@ return ( > {items.map((item) => ( - {renderItem(item)} + {renderItem(item, editFunction)} ))}