feat: add Paragraph component and types for typography
Browse filesfeat: implement useAIResponseStream hook for handling streaming API responses
feat: create useAIChatStreamHandler for managing chat interactions with streaming responses
feat: add useChatActions hook for chat message management
feat: implement useSessionLoader for loading and managing session data
feat: add audio utility functions for decoding base64 audio
feat: create constructEndpointUrl utility for endpoint URL construction
feat: implement modelProvider utility for mapping provider icons
feat: add utility functions for common operations in utils.ts
feat: establish Zustand store for state management in the playground
feat: define playground types for structured data handling
style: configure Tailwind CSS for styling
chore: set up TypeScript configuration for the project
ci: add GitHub Actions workflow for validating builds
- .gitignore +9 -3
- .vscode/settings.json +7 -0
- CONTRIBUTING.md +20 -0
- LICENSE +21 -201
- README.md +66 -1
- components.json +21 -0
- eslint.config.mjs +16 -0
- next.config.ts +7 -0
- package-lock.json +0 -0
- package.json +55 -0
- pnpm-lock.yaml +0 -0
- postcss.config.mjs +8 -0
- prettier.config.cjs +8 -0
- src/api/playground.ts +89 -0
- src/api/routes.ts +23 -0
- src/app/favicon.ico +0 -0
- src/app/globals.css +31 -0
- src/app/layout.tsx +37 -0
- src/app/page.tsx +15 -0
- src/components/playground/ChatArea/ChatArea.tsx +16 -0
- src/components/playground/ChatArea/ChatInput/ChatInput.tsx +68 -0
- src/components/playground/ChatArea/ChatInput/index.ts +3 -0
- src/components/playground/ChatArea/MessageArea.tsx +27 -0
- src/components/playground/ChatArea/Messages/AgentThinkingLoader.tsx +9 -0
- src/components/playground/ChatArea/Messages/ChatBlankState.tsx +198 -0
- src/components/playground/ChatArea/Messages/MessageItem.tsx +98 -0
- src/components/playground/ChatArea/Messages/Messages.tsx +179 -0
- src/components/playground/ChatArea/Messages/Multimedia/Audios/Audios.tsx +63 -0
- src/components/playground/ChatArea/Messages/Multimedia/Audios/index.ts +3 -0
- src/components/playground/ChatArea/Messages/Multimedia/Images/Images.tsx +41 -0
- src/components/playground/ChatArea/Messages/Multimedia/Images/index.ts +3 -0
- src/components/playground/ChatArea/Messages/Multimedia/Videos/Videos.tsx +79 -0
- src/components/playground/ChatArea/Messages/Multimedia/Videos/index.ts +3 -0
- src/components/playground/ChatArea/Messages/index.ts +3 -0
- src/components/playground/ChatArea/ScrollToBottom.tsx +39 -0
- src/components/playground/ChatArea/index.ts +3 -0
- src/components/playground/Sidebar/AgentSelector.tsx +89 -0
- src/components/playground/Sidebar/NewChatButton.tsx +25 -0
- src/components/playground/Sidebar/Sessions/DeleteSessionModal.tsx +57 -0
- src/components/playground/Sidebar/Sessions/SessionBlankState.tsx +136 -0
- src/components/playground/Sidebar/Sessions/SessionItem.tsx +104 -0
- src/components/playground/Sidebar/Sessions/Sessions.tsx +180 -0
- src/components/playground/Sidebar/Sessions/index.ts +3 -0
- src/components/playground/Sidebar/Sidebar.tsx +298 -0
- src/components/playground/Sidebar/index.ts +3 -0
- src/components/ui/button.tsx +57 -0
- src/components/ui/dialog.tsx +122 -0
- src/components/ui/icon/Icon.tsx +35 -0
- src/components/ui/icon/constants.tsx +79 -0
- src/components/ui/icon/custom-icons.tsx +983 -0
@@ -3,7 +3,12 @@
|
|
3 |
# dependencies
|
4 |
/node_modules
|
5 |
/.pnp
|
6 |
-
.pnp
|
|
|
|
|
|
|
|
|
|
|
7 |
|
8 |
# testing
|
9 |
/coverage
|
@@ -23,9 +28,10 @@
|
|
23 |
npm-debug.log*
|
24 |
yarn-debug.log*
|
25 |
yarn-error.log*
|
|
|
26 |
|
27 |
-
#
|
28 |
-
.env
|
29 |
.env
|
30 |
|
31 |
# vercel
|
|
|
3 |
# dependencies
|
4 |
/node_modules
|
5 |
/.pnp
|
6 |
+
.pnp.*
|
7 |
+
.yarn/*
|
8 |
+
!.yarn/patches
|
9 |
+
!.yarn/plugins
|
10 |
+
!.yarn/releases
|
11 |
+
!.yarn/versions
|
12 |
|
13 |
# testing
|
14 |
/coverage
|
|
|
28 |
npm-debug.log*
|
29 |
yarn-debug.log*
|
30 |
yarn-error.log*
|
31 |
+
.pnpm-debug.log*
|
32 |
|
33 |
+
# env files (can opt-in for committing if needed)
|
34 |
+
.env.local
|
35 |
.env
|
36 |
|
37 |
# vercel
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
3 |
+
"editor.formatOnSave": true,
|
4 |
+
"editor.codeActionsOnSave": {
|
5 |
+
"source.fixAll.eslint": "explicit"
|
6 |
+
}
|
7 |
+
}
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Contributing to Agent UI
|
2 |
+
|
3 |
+
Contributions are welcome! Please feel free to submit a Pull Request or raise an issue.
|
4 |
+
|
5 |
+
## How to Contribute
|
6 |
+
|
7 |
+
1. For bugs and feature requests, please raise a ticket first
|
8 |
+
2. Fork the repository
|
9 |
+
3. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
10 |
+
4. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
11 |
+
5. Push to the branch (`git push origin feature/amazing-feature`)
|
12 |
+
6. Open a Pull Request
|
13 |
+
|
14 |
+
## Code of Conduct
|
15 |
+
|
16 |
+
Please be respectful and considerate of others when contributing to this project.
|
17 |
+
|
18 |
+
## Questions?
|
19 |
+
|
20 |
+
If you have any questions about contributing, please feel free to reach out to the maintainers.
|
@@ -1,201 +1,21 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
"You" (or "Your") shall mean an individual or Legal Entity
|
24 |
-
exercising permissions granted by this License.
|
25 |
-
|
26 |
-
"Source" form shall mean the preferred form for making modifications,
|
27 |
-
including but not limited to software source code, documentation
|
28 |
-
source, and configuration files.
|
29 |
-
|
30 |
-
"Object" form shall mean any form resulting from mechanical
|
31 |
-
transformation or translation of a Source form, including but
|
32 |
-
not limited to compiled object code, generated documentation,
|
33 |
-
and conversions to other media types.
|
34 |
-
|
35 |
-
"Work" shall mean the work of authorship, whether in Source or
|
36 |
-
Object form, made available under the License, as indicated by a
|
37 |
-
copyright notice that is included in or attached to the work
|
38 |
-
(an example is provided in the Appendix below).
|
39 |
-
|
40 |
-
"Derivative Works" shall mean any work, whether in Source or Object
|
41 |
-
form, that is based on (or derived from) the Work and for which the
|
42 |
-
editorial revisions, annotations, elaborations, or other modifications
|
43 |
-
represent, as a whole, an original work of authorship. For the purposes
|
44 |
-
of this License, Derivative Works shall not include works that remain
|
45 |
-
separable from, or merely link (or bind by name) to the interfaces of,
|
46 |
-
the Work and Derivative Works thereof.
|
47 |
-
|
48 |
-
"Contribution" shall mean any work of authorship, including
|
49 |
-
the original version of the Work and any modifications or additions
|
50 |
-
to that Work or Derivative Works thereof, that is intentionally
|
51 |
-
submitted to Licensor for inclusion in the Work by the copyright owner
|
52 |
-
or by an individual or Legal Entity authorized to submit on behalf of
|
53 |
-
the copyright owner. For the purposes of this definition, "submitted"
|
54 |
-
means any form of electronic, verbal, or written communication sent
|
55 |
-
to the Licensor or its representatives, including but not limited to
|
56 |
-
communication on electronic mailing lists, source code control systems,
|
57 |
-
and issue tracking systems that are managed by, or on behalf of, the
|
58 |
-
Licensor for the purpose of discussing and improving the Work, but
|
59 |
-
excluding communication that is conspicuously marked or otherwise
|
60 |
-
designated in writing by the copyright owner as "Not a Contribution."
|
61 |
-
|
62 |
-
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63 |
-
on behalf of whom a Contribution has been received by Licensor and
|
64 |
-
subsequently incorporated within the Work.
|
65 |
-
|
66 |
-
2. Grant of Copyright License. Subject to the terms and conditions of
|
67 |
-
this License, each Contributor hereby grants to You a perpetual,
|
68 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69 |
-
copyright license to reproduce, prepare Derivative Works of,
|
70 |
-
publicly display, publicly perform, sublicense, and distribute the
|
71 |
-
Work and such Derivative Works in Source or Object form.
|
72 |
-
|
73 |
-
3. Grant of Patent License. Subject to the terms and conditions of
|
74 |
-
this License, each Contributor hereby grants to You a perpetual,
|
75 |
-
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76 |
-
(except as stated in this section) patent license to make, have made,
|
77 |
-
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78 |
-
where such license applies only to those patent claims licensable
|
79 |
-
by such Contributor that are necessarily infringed by their
|
80 |
-
Contribution(s) alone or by combination of their Contribution(s)
|
81 |
-
with the Work to which such Contribution(s) was submitted. If You
|
82 |
-
institute patent litigation against any entity (including a
|
83 |
-
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84 |
-
or a Contribution incorporated within the Work constitutes direct
|
85 |
-
or contributory patent infringement, then any patent licenses
|
86 |
-
granted to You under this License for that Work shall terminate
|
87 |
-
as of the date such litigation is filed.
|
88 |
-
|
89 |
-
4. Redistribution. You may reproduce and distribute copies of the
|
90 |
-
Work or Derivative Works thereof in any medium, with or without
|
91 |
-
modifications, and in Source or Object form, provided that You
|
92 |
-
meet the following conditions:
|
93 |
-
|
94 |
-
(a) You must give any other recipients of the Work or
|
95 |
-
Derivative Works a copy of this License; and
|
96 |
-
|
97 |
-
(b) You must cause any modified files to carry prominent notices
|
98 |
-
stating that You changed the files; and
|
99 |
-
|
100 |
-
(c) You must retain, in the Source form of any Derivative Works
|
101 |
-
that You distribute, all copyright, patent, trademark, and
|
102 |
-
attribution notices from the Source form of the Work,
|
103 |
-
excluding those notices that do not pertain to any part of
|
104 |
-
the Derivative Works; and
|
105 |
-
|
106 |
-
(d) If the Work includes a "NOTICE" text file as part of its
|
107 |
-
distribution, then any Derivative Works that You distribute must
|
108 |
-
include a readable copy of the attribution notices contained
|
109 |
-
within such NOTICE file, excluding those notices that do not
|
110 |
-
pertain to any part of the Derivative Works, in at least one
|
111 |
-
of the following places: within a NOTICE text file distributed
|
112 |
-
as part of the Derivative Works; within the Source form or
|
113 |
-
documentation, if provided along with the Derivative Works; or,
|
114 |
-
within a display generated by the Derivative Works, if and
|
115 |
-
wherever such third-party notices normally appear. The contents
|
116 |
-
of the NOTICE file are for informational purposes only and
|
117 |
-
do not modify the License. You may add Your own attribution
|
118 |
-
notices within Derivative Works that You distribute, alongside
|
119 |
-
or as an addendum to the NOTICE text from the Work, provided
|
120 |
-
that such additional attribution notices cannot be construed
|
121 |
-
as modifying the License.
|
122 |
-
|
123 |
-
You may add Your own copyright statement to Your modifications and
|
124 |
-
may provide additional or different license terms and conditions
|
125 |
-
for use, reproduction, or distribution of Your modifications, or
|
126 |
-
for any such Derivative Works as a whole, provided Your use,
|
127 |
-
reproduction, and distribution of the Work otherwise complies with
|
128 |
-
the conditions stated in this License.
|
129 |
-
|
130 |
-
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131 |
-
any Contribution intentionally submitted for inclusion in the Work
|
132 |
-
by You to the Licensor shall be under the terms and conditions of
|
133 |
-
this License, without any additional terms or conditions.
|
134 |
-
Notwithstanding the above, nothing herein shall supersede or modify
|
135 |
-
the terms of any separate license agreement you may have executed
|
136 |
-
with Licensor regarding such Contributions.
|
137 |
-
|
138 |
-
6. Trademarks. This License does not grant permission to use the trade
|
139 |
-
names, trademarks, service marks, or product names of the Licensor,
|
140 |
-
except as required for reasonable and customary use in describing the
|
141 |
-
origin of the Work and reproducing the content of the NOTICE file.
|
142 |
-
|
143 |
-
7. Disclaimer of Warranty. Unless required by applicable law or
|
144 |
-
agreed to in writing, Licensor provides the Work (and each
|
145 |
-
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147 |
-
implied, including, without limitation, any warranties or conditions
|
148 |
-
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149 |
-
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150 |
-
appropriateness of using or redistributing the Work and assume any
|
151 |
-
risks associated with Your exercise of permissions under this License.
|
152 |
-
|
153 |
-
8. Limitation of Liability. In no event and under no legal theory,
|
154 |
-
whether in tort (including negligence), contract, or otherwise,
|
155 |
-
unless required by applicable law (such as deliberate and grossly
|
156 |
-
negligent acts) or agreed to in writing, shall any Contributor be
|
157 |
-
liable to You for damages, including any direct, indirect, special,
|
158 |
-
incidental, or consequential damages of any character arising as a
|
159 |
-
result of this License or out of the use or inability to use the
|
160 |
-
Work (including but not limited to damages for loss of goodwill,
|
161 |
-
work stoppage, computer failure or malfunction, or any and all
|
162 |
-
other commercial damages or losses), even if such Contributor
|
163 |
-
has been advised of the possibility of such damages.
|
164 |
-
|
165 |
-
9. Accepting Warranty or Additional Liability. While redistributing
|
166 |
-
the Work or Derivative Works thereof, You may choose to offer,
|
167 |
-
and charge a fee for, acceptance of support, warranty, indemnity,
|
168 |
-
or other liability obligations and/or rights consistent with this
|
169 |
-
License. However, in accepting such obligations, You may act only
|
170 |
-
on Your own behalf and on Your sole responsibility, not on behalf
|
171 |
-
of any other Contributor, and only if You agree to indemnify,
|
172 |
-
defend, and hold each Contributor harmless for any liability
|
173 |
-
incurred by, or claims asserted against, such Contributor by reason
|
174 |
-
of your accepting any such warranty or additional liability.
|
175 |
-
|
176 |
-
END OF TERMS AND CONDITIONS
|
177 |
-
|
178 |
-
APPENDIX: How to apply the Apache License to your work.
|
179 |
-
|
180 |
-
To apply the Apache License to your work, attach the following
|
181 |
-
boilerplate notice, with the fields enclosed by brackets "[]"
|
182 |
-
replaced with your own identifying information. (Don't include
|
183 |
-
the brackets!) The text should be enclosed in the appropriate
|
184 |
-
comment syntax for the file format. We also recommend that a
|
185 |
-
file or class name and description of purpose be included on the
|
186 |
-
same "printed page" as the copyright notice for easier
|
187 |
-
identification within third-party archives.
|
188 |
-
|
189 |
-
Copyright [yyyy] [name of copyright owner]
|
190 |
-
|
191 |
-
Licensed under the Apache License, Version 2.0 (the "License");
|
192 |
-
you may not use this file except in compliance with the License.
|
193 |
-
You may obtain a copy of the License at
|
194 |
-
|
195 |
-
http://www.apache.org/licenses/LICENSE-2.0
|
196 |
-
|
197 |
-
Unless required by applicable law or agreed to in writing, software
|
198 |
-
distributed under the License is distributed on an "AS IS" BASIS,
|
199 |
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200 |
-
See the License for the specific language governing permissions and
|
201 |
-
limitations under the License.
|
|
|
1 |
+
MIT License
|
2 |
+
|
3 |
+
Copyright (c) 2025 Agno
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1 +1,66 @@
|
|
1 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Agent UI
|
2 |
+
|
3 |
+
A modern chat interface for AI agents built with Next.js, Tailwind CSS, and TypeScript. This template provides a ready-to-use UI for interacting with Agno agents.
|
4 |
+
|
5 |
+
<img src="https://github.com/user-attachments/assets/7765fae5-a813-46cb-993b-904af9bc1672" alt="agent-ui" style="border-radius: 10px; width: 100%; max-width: 800px;" />
|
6 |
+
|
7 |
+
## Features
|
8 |
+
|
9 |
+
- 💬 **Modern Chat Interface**: Clean design with real-time streaming support
|
10 |
+
- 🧩 **Tool Calls Support**: Visualizes agent tool calls and their results
|
11 |
+
- 🧠 **Reasoning Steps**: Displays agent reasoning process (when available)
|
12 |
+
- 📚 **References Support**: Show sources used by the agent
|
13 |
+
- 🖼️ **Multi-modality Support**: Handles various content types including images, video, and audio
|
14 |
+
- 🎨 **Customizable UI**: Built with Tailwind CSS for easy styling
|
15 |
+
- 🧰 **Built with Modern Stack**: Next.js, TypeScript, shadcn/ui, Framer Motion, and more
|
16 |
+
|
17 |
+
## Getting Started
|
18 |
+
|
19 |
+
### Prerequisites
|
20 |
+
|
21 |
+
Before setting up Agent UI, you may want to have an Agno Playground running. If you haven't set up the Agno Playground yet, follow the [official guide](https://agno.link/agent-ui#connect-to-local-agents) to run the Playground locally.
|
22 |
+
|
23 |
+
### Installation
|
24 |
+
|
25 |
+
### Automatic Installation (Recommended)
|
26 |
+
|
27 |
+
```bash
|
28 |
+
npx create-agent-ui@latest
|
29 |
+
```
|
30 |
+
|
31 |
+
### Manual Installation
|
32 |
+
|
33 |
+
1. Clone the repository:
|
34 |
+
|
35 |
+
```bash
|
36 |
+
git clone https://github.com/agno-agi/agent-ui.git
|
37 |
+
cd agent-ui
|
38 |
+
```
|
39 |
+
|
40 |
+
2. Install dependencies:
|
41 |
+
|
42 |
+
```bash
|
43 |
+
pnpm install
|
44 |
+
```
|
45 |
+
|
46 |
+
3. Start the development server:
|
47 |
+
|
48 |
+
```bash
|
49 |
+
pnpm dev
|
50 |
+
```
|
51 |
+
|
52 |
+
4. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
53 |
+
|
54 |
+
## Connecting to an Agent Backend
|
55 |
+
|
56 |
+
By default Agent UI connects to `http://localhost:7777`. You can easily change this by hovering over the endpoint URL and clicking the edit option.
|
57 |
+
|
58 |
+
The default endpoint works with the standard Agno Playground setup described in the [official documentation](https://agno.link/agent-ui#connect-to-local-agents).
|
59 |
+
|
60 |
+
## Contributing
|
61 |
+
|
62 |
+
Contributions are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution guidelines.
|
63 |
+
|
64 |
+
## License
|
65 |
+
|
66 |
+
This project is licensed under the [MIT License](./LICENSE).
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"$schema": "https://ui.shadcn.com/schema.json",
|
3 |
+
"style": "new-york",
|
4 |
+
"rsc": true,
|
5 |
+
"tsx": true,
|
6 |
+
"tailwind": {
|
7 |
+
"config": "tailwind.config.ts",
|
8 |
+
"css": "src/app/globals.css",
|
9 |
+
"baseColor": "neutral",
|
10 |
+
"cssVariables": true,
|
11 |
+
"prefix": ""
|
12 |
+
},
|
13 |
+
"aliases": {
|
14 |
+
"components": "@/components",
|
15 |
+
"utils": "@/lib/utils",
|
16 |
+
"ui": "@/components/ui",
|
17 |
+
"lib": "@/lib",
|
18 |
+
"hooks": "@/hooks"
|
19 |
+
},
|
20 |
+
"iconLibrary": "lucide"
|
21 |
+
}
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { dirname } from 'path'
|
2 |
+
import { fileURLToPath } from 'url'
|
3 |
+
import { FlatCompat } from '@eslint/eslintrc'
|
4 |
+
|
5 |
+
const __filename = fileURLToPath(import.meta.url)
|
6 |
+
const __dirname = dirname(__filename)
|
7 |
+
|
8 |
+
const compat = new FlatCompat({
|
9 |
+
baseDirectory: __dirname
|
10 |
+
})
|
11 |
+
|
12 |
+
const eslintConfig = [
|
13 |
+
...compat.extends('next/core-web-vitals', 'next/typescript')
|
14 |
+
]
|
15 |
+
|
16 |
+
export default eslintConfig
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { NextConfig } from 'next'
|
2 |
+
|
3 |
+
const nextConfig: NextConfig = {
|
4 |
+
devIndicators: false
|
5 |
+
}
|
6 |
+
|
7 |
+
export default nextConfig
|
The diff for this file is too large to render.
See raw diff
|
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "agent-ui",
|
3 |
+
"version": "0.1.0",
|
4 |
+
"private": true,
|
5 |
+
"scripts": {
|
6 |
+
"dev": "next dev -p 3000",
|
7 |
+
"build": "next build",
|
8 |
+
"start": "next start",
|
9 |
+
"lint": "next lint",
|
10 |
+
"lint:fix": "next lint --fix",
|
11 |
+
"format": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
|
12 |
+
"format:fix": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
|
13 |
+
"typecheck": "tsc --noEmit",
|
14 |
+
"validate": "pnpm run lint && pnpm run format && pnpm run typecheck"
|
15 |
+
},
|
16 |
+
"dependencies": {
|
17 |
+
"@radix-ui/react-dialog": "^1.1.5",
|
18 |
+
"@radix-ui/react-icons": "^1.3.2",
|
19 |
+
"@radix-ui/react-select": "^2.1.5",
|
20 |
+
"@radix-ui/react-slot": "^1.1.1",
|
21 |
+
"@radix-ui/react-tooltip": "^1.1.7",
|
22 |
+
"class-variance-authority": "^0.7.1",
|
23 |
+
"clsx": "^2.1.1",
|
24 |
+
"dayjs": "^1.11.13",
|
25 |
+
"framer-motion": "^12.4.1",
|
26 |
+
"lucide-react": "^0.474.0",
|
27 |
+
"next": "15.2.3",
|
28 |
+
"next-themes": "^0.4.4",
|
29 |
+
"nuqs": "^2.3.2",
|
30 |
+
"prettier-plugin-tailwindcss": "^0.6.11",
|
31 |
+
"react": "^19.0.0",
|
32 |
+
"react-dom": "^19.0.0",
|
33 |
+
"react-markdown": "^9.0.3",
|
34 |
+
"rehype-raw": "^7.0.0",
|
35 |
+
"rehype-sanitize": "^6.0.0",
|
36 |
+
"remark-gfm": "^4.0.0",
|
37 |
+
"sonner": "^1.7.4",
|
38 |
+
"tailwind-merge": "^3.0.1",
|
39 |
+
"tailwindcss-animate": "^1.0.7",
|
40 |
+
"use-stick-to-bottom": "^1.0.46",
|
41 |
+
"zustand": "^5.0.3"
|
42 |
+
},
|
43 |
+
"devDependencies": {
|
44 |
+
"@eslint/eslintrc": "^3",
|
45 |
+
"@types/node": "^20",
|
46 |
+
"@types/react": "^19",
|
47 |
+
"@types/react-dom": "^19",
|
48 |
+
"eslint": "^9",
|
49 |
+
"eslint-config-next": "15.2.3",
|
50 |
+
"postcss": "^8",
|
51 |
+
"prettier": "3.4.2",
|
52 |
+
"tailwindcss": "^3.4.1",
|
53 |
+
"typescript": "^5"
|
54 |
+
}
|
55 |
+
}
|
The diff for this file is too large to render.
See raw diff
|
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/** @type {import('postcss-load-config').Config} */
|
2 |
+
const config = {
|
3 |
+
plugins: {
|
4 |
+
tailwindcss: {}
|
5 |
+
}
|
6 |
+
}
|
7 |
+
|
8 |
+
export default config
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/** @type {import('prettier').Config} */
|
2 |
+
module.exports = {
|
3 |
+
singleQuote: true,
|
4 |
+
semi: false,
|
5 |
+
trailingComma: 'none',
|
6 |
+
plugins: ['prettier-plugin-tailwindcss'],
|
7 |
+
filepath: './src/**/*.{js,ts,jsx,tsx}'
|
8 |
+
}
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { toast } from 'sonner'
|
2 |
+
|
3 |
+
import { APIRoutes } from './routes'
|
4 |
+
|
5 |
+
import { Agent, ComboboxAgent, SessionEntry } from '@/types/playground'
|
6 |
+
|
7 |
+
export const getPlaygroundAgentsAPI = async (
|
8 |
+
endpoint: string
|
9 |
+
): Promise<ComboboxAgent[]> => {
|
10 |
+
const url = APIRoutes.GetPlaygroundAgents(endpoint)
|
11 |
+
try {
|
12 |
+
const response = await fetch(url, { method: 'GET' })
|
13 |
+
if (!response.ok) {
|
14 |
+
toast.error(`Failed to fetch playground agents: ${response.statusText}`)
|
15 |
+
return []
|
16 |
+
}
|
17 |
+
const data = await response.json()
|
18 |
+
// Transform the API response into the expected shape.
|
19 |
+
const agents: ComboboxAgent[] = data.map((item: Agent) => ({
|
20 |
+
value: item.agent_id || '',
|
21 |
+
label: item.name || '',
|
22 |
+
model: item.model || '',
|
23 |
+
storage: item.storage || false
|
24 |
+
}))
|
25 |
+
return agents
|
26 |
+
} catch {
|
27 |
+
toast.error('Error fetching playground agents')
|
28 |
+
return []
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
export const getPlaygroundStatusAPI = async (base: string): Promise<number> => {
|
33 |
+
const response = await fetch(APIRoutes.PlaygroundStatus(base), {
|
34 |
+
method: 'GET'
|
35 |
+
})
|
36 |
+
return response.status
|
37 |
+
}
|
38 |
+
|
39 |
+
export const getAllPlaygroundSessionsAPI = async (
|
40 |
+
base: string,
|
41 |
+
agentId: string
|
42 |
+
): Promise<SessionEntry[]> => {
|
43 |
+
try {
|
44 |
+
const response = await fetch(
|
45 |
+
APIRoutes.GetPlaygroundSessions(base, agentId),
|
46 |
+
{
|
47 |
+
method: 'GET'
|
48 |
+
}
|
49 |
+
)
|
50 |
+
if (!response.ok) {
|
51 |
+
if (response.status === 404) {
|
52 |
+
// Return empty array when storage is not enabled
|
53 |
+
return []
|
54 |
+
}
|
55 |
+
throw new Error(`Failed to fetch sessions: ${response.statusText}`)
|
56 |
+
}
|
57 |
+
return response.json()
|
58 |
+
} catch {
|
59 |
+
return []
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
export const getPlaygroundSessionAPI = async (
|
64 |
+
base: string,
|
65 |
+
agentId: string,
|
66 |
+
sessionId: string
|
67 |
+
) => {
|
68 |
+
const response = await fetch(
|
69 |
+
APIRoutes.GetPlaygroundSession(base, agentId, sessionId),
|
70 |
+
{
|
71 |
+
method: 'GET'
|
72 |
+
}
|
73 |
+
)
|
74 |
+
return response.json()
|
75 |
+
}
|
76 |
+
|
77 |
+
export const deletePlaygroundSessionAPI = async (
|
78 |
+
base: string,
|
79 |
+
agentId: string,
|
80 |
+
sessionId: string
|
81 |
+
) => {
|
82 |
+
const response = await fetch(
|
83 |
+
APIRoutes.DeletePlaygroundSession(base, agentId, sessionId),
|
84 |
+
{
|
85 |
+
method: 'DELETE'
|
86 |
+
}
|
87 |
+
)
|
88 |
+
return response
|
89 |
+
}
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
export const APIRoutes = {
|
2 |
+
GetPlaygroundAgents: (PlaygroundApiUrl: string) =>
|
3 |
+
`${PlaygroundApiUrl}/v1/playground/agents`,
|
4 |
+
AgentRun: (PlaygroundApiUrl: string) =>
|
5 |
+
`${PlaygroundApiUrl}/v1/playground/agents/{agent_id}/runs`,
|
6 |
+
PlaygroundStatus: (PlaygroundApiUrl: string) =>
|
7 |
+
`${PlaygroundApiUrl}/v1/playground/status`,
|
8 |
+
GetPlaygroundSessions: (PlaygroundApiUrl: string, agentId: string) =>
|
9 |
+
`${PlaygroundApiUrl}/v1/playground/agents/${agentId}/sessions`,
|
10 |
+
GetPlaygroundSession: (
|
11 |
+
PlaygroundApiUrl: string,
|
12 |
+
agentId: string,
|
13 |
+
sessionId: string
|
14 |
+
) =>
|
15 |
+
`${PlaygroundApiUrl}/v1/playground/agents/${agentId}/sessions/${sessionId}`,
|
16 |
+
|
17 |
+
DeletePlaygroundSession: (
|
18 |
+
PlaygroundApiUrl: string,
|
19 |
+
agentId: string,
|
20 |
+
sessionId: string
|
21 |
+
) =>
|
22 |
+
`${PlaygroundApiUrl}/v1/playground/agents/${agentId}/sessions/${sessionId}`
|
23 |
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@tailwind base;
|
2 |
+
@tailwind components;
|
3 |
+
@tailwind utilities;
|
4 |
+
|
5 |
+
@layer base {
|
6 |
+
:root {
|
7 |
+
--color-border-default: 255, 255, 255, 0.2;
|
8 |
+
--scrollbar-width: 0.1rem;
|
9 |
+
}
|
10 |
+
|
11 |
+
body {
|
12 |
+
@apply bg-background/80 text-secondary;
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
::-webkit-scrollbar {
|
17 |
+
width: var(--scrollbar-width);
|
18 |
+
}
|
19 |
+
|
20 |
+
::-webkit-scrollbar-thumb {
|
21 |
+
--tw-border-opacity: 1;
|
22 |
+
@apply bg-border;
|
23 |
+
border-color: rgba(255, 255, 255, var(--tw-border-opacity));
|
24 |
+
border-radius: 9999px;
|
25 |
+
border-width: 1px;
|
26 |
+
}
|
27 |
+
|
28 |
+
::-webkit-scrollbar-track {
|
29 |
+
background-color: transparent;
|
30 |
+
border-radius: 9999px;
|
31 |
+
}
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { Metadata } from 'next'
|
2 |
+
import { DM_Mono, Geist } from 'next/font/google'
|
3 |
+
import { NuqsAdapter } from 'nuqs/adapters/next/app'
|
4 |
+
import { Toaster } from '@/components/ui/sonner'
|
5 |
+
import './globals.css'
|
6 |
+
const geistSans = Geist({
|
7 |
+
variable: '--font-geist-sans',
|
8 |
+
weight: '400',
|
9 |
+
subsets: ['latin']
|
10 |
+
})
|
11 |
+
|
12 |
+
const dmMono = DM_Mono({
|
13 |
+
subsets: ['latin'],
|
14 |
+
variable: '--font-dm-mono',
|
15 |
+
weight: '400'
|
16 |
+
})
|
17 |
+
|
18 |
+
export const metadata: Metadata = {
|
19 |
+
title: 'Agent UI',
|
20 |
+
description:
|
21 |
+
'A modern chat interface for AI agents built with Next.js, Tailwind CSS, and TypeScript. This template provides a ready-to-use UI for interacting with Agno agents.'
|
22 |
+
}
|
23 |
+
|
24 |
+
export default function RootLayout({
|
25 |
+
children
|
26 |
+
}: Readonly<{
|
27 |
+
children: React.ReactNode
|
28 |
+
}>) {
|
29 |
+
return (
|
30 |
+
<html lang="en">
|
31 |
+
<body className={`${geistSans.variable} ${dmMono.variable} antialiased`}>
|
32 |
+
<NuqsAdapter>{children}</NuqsAdapter>
|
33 |
+
<Toaster />
|
34 |
+
</body>
|
35 |
+
</html>
|
36 |
+
)
|
37 |
+
}
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
import Sidebar from '@/components/playground/Sidebar/Sidebar'
|
3 |
+
import { ChatArea } from '@/components/playground/ChatArea'
|
4 |
+
import { Suspense } from 'react'
|
5 |
+
|
6 |
+
export default function Home() {
|
7 |
+
return (
|
8 |
+
<Suspense fallback={<div>Loading...</div>}>
|
9 |
+
<div className="flex h-screen bg-background/80">
|
10 |
+
<Sidebar />
|
11 |
+
<ChatArea />
|
12 |
+
</div>
|
13 |
+
</Suspense>
|
14 |
+
)
|
15 |
+
}
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import ChatInput from './ChatInput'
|
4 |
+
import MessageArea from './MessageArea'
|
5 |
+
const ChatArea = () => {
|
6 |
+
return (
|
7 |
+
<main className="relative m-1.5 flex flex-grow flex-col rounded-xl bg-background">
|
8 |
+
<MessageArea />
|
9 |
+
<div className="sticky bottom-0 ml-9 px-4 pb-2">
|
10 |
+
<ChatInput />
|
11 |
+
</div>
|
12 |
+
</main>
|
13 |
+
)
|
14 |
+
}
|
15 |
+
|
16 |
+
export default ChatArea
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
import { useState } from 'react'
|
3 |
+
import { toast } from 'sonner'
|
4 |
+
import { TextArea } from '@/components/ui/textarea'
|
5 |
+
import { Button } from '@/components/ui/button'
|
6 |
+
import { usePlaygroundStore } from '@/store'
|
7 |
+
import useAIChatStreamHandler from '@/hooks/useAIStreamHandler'
|
8 |
+
import { useQueryState } from 'nuqs'
|
9 |
+
import Icon from '@/components/ui/icon'
|
10 |
+
|
11 |
+
const ChatInput = () => {
|
12 |
+
const { chatInputRef } = usePlaygroundStore()
|
13 |
+
|
14 |
+
const { handleStreamResponse } = useAIChatStreamHandler()
|
15 |
+
const [selectedAgent] = useQueryState('agent')
|
16 |
+
const [inputMessage, setInputMessage] = useState('')
|
17 |
+
const isStreaming = usePlaygroundStore((state) => state.isStreaming)
|
18 |
+
const handleSubmit = async () => {
|
19 |
+
if (!inputMessage.trim()) return
|
20 |
+
|
21 |
+
const currentMessage = inputMessage
|
22 |
+
setInputMessage('')
|
23 |
+
|
24 |
+
try {
|
25 |
+
await handleStreamResponse(currentMessage)
|
26 |
+
} catch (error) {
|
27 |
+
toast.error(
|
28 |
+
`Error in handleSubmit: ${
|
29 |
+
error instanceof Error ? error.message : String(error)
|
30 |
+
}`
|
31 |
+
)
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
return (
|
36 |
+
<div className="relative mx-auto mb-1 flex w-full max-w-2xl items-end justify-center gap-x-2 font-geist">
|
37 |
+
<TextArea
|
38 |
+
placeholder={'Ask anything'}
|
39 |
+
value={inputMessage}
|
40 |
+
onChange={(e) => setInputMessage(e.target.value)}
|
41 |
+
onKeyDown={(e) => {
|
42 |
+
if (
|
43 |
+
e.key === 'Enter' &&
|
44 |
+
!e.nativeEvent.isComposing &&
|
45 |
+
!e.shiftKey &&
|
46 |
+
!isStreaming
|
47 |
+
) {
|
48 |
+
e.preventDefault()
|
49 |
+
handleSubmit()
|
50 |
+
}
|
51 |
+
}}
|
52 |
+
className="w-full border border-accent bg-primaryAccent px-4 text-sm text-primary focus:border-accent"
|
53 |
+
disabled={!selectedAgent}
|
54 |
+
ref={chatInputRef}
|
55 |
+
/>
|
56 |
+
<Button
|
57 |
+
onClick={handleSubmit}
|
58 |
+
disabled={!selectedAgent || !inputMessage.trim() || isStreaming}
|
59 |
+
size="icon"
|
60 |
+
className="rounded-xl bg-primary p-5 text-primaryAccent"
|
61 |
+
>
|
62 |
+
<Icon type="send" color="primaryAccent" />
|
63 |
+
</Button>
|
64 |
+
</div>
|
65 |
+
)
|
66 |
+
}
|
67 |
+
|
68 |
+
export default ChatInput
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import ChatInput from './ChatInput'
|
2 |
+
|
3 |
+
export default ChatInput
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { usePlaygroundStore } from '@/store'
|
4 |
+
import Messages from './Messages'
|
5 |
+
import ScrollToBottom from '@/components/playground/ChatArea/ScrollToBottom'
|
6 |
+
import { StickToBottom } from 'use-stick-to-bottom'
|
7 |
+
|
8 |
+
const MessageArea = () => {
|
9 |
+
const { messages } = usePlaygroundStore()
|
10 |
+
|
11 |
+
return (
|
12 |
+
<StickToBottom
|
13 |
+
className="relative mb-4 flex max-h-[calc(100vh-64px)] min-h-0 flex-grow flex-col"
|
14 |
+
resize="smooth"
|
15 |
+
initial="smooth"
|
16 |
+
>
|
17 |
+
<StickToBottom.Content className="flex min-h-full flex-col justify-center">
|
18 |
+
<div className="mx-auto w-full max-w-2xl space-y-9 px-4 pb-4">
|
19 |
+
<Messages messages={messages} />
|
20 |
+
</div>
|
21 |
+
</StickToBottom.Content>
|
22 |
+
<ScrollToBottom />
|
23 |
+
</StickToBottom>
|
24 |
+
)
|
25 |
+
}
|
26 |
+
|
27 |
+
export default MessageArea
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const AgentThinkingLoader = () => (
|
2 |
+
<div className="flex items-center justify-center gap-1">
|
3 |
+
<div className="size-2 animate-bounce rounded-full bg-primary/20 [animation-delay:-0.3s] [animation-duration:0.70s]" />
|
4 |
+
<div className="size-2 animate-bounce rounded-full bg-primary/20 [animation-delay:-0.10s] [animation-duration:0.70s]" />
|
5 |
+
<div className="size-2 animate-bounce rounded-full bg-primary/20 [animation-duration:0.70s]" />
|
6 |
+
</div>
|
7 |
+
)
|
8 |
+
|
9 |
+
export default AgentThinkingLoader
|
@@ -0,0 +1,198 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import Link from 'next/link'
|
4 |
+
import { motion, Variants } from 'framer-motion'
|
5 |
+
import Icon from '@/components/ui/icon'
|
6 |
+
import { IconType } from '@/components/ui/icon/types'
|
7 |
+
import React, { useState } from 'react'
|
8 |
+
|
9 |
+
const EXTERNAL_LINKS = {
|
10 |
+
documentation: 'https://agno.link/agent-ui',
|
11 |
+
playground: 'https://app.agno.com/playground/agents',
|
12 |
+
agno: 'https://agno.com'
|
13 |
+
}
|
14 |
+
|
15 |
+
const TECH_ICONS = [
|
16 |
+
{
|
17 |
+
type: 'nextjs' as IconType,
|
18 |
+
position: 'left-0',
|
19 |
+
link: 'https://nextjs.org',
|
20 |
+
name: 'Next.js',
|
21 |
+
zIndex: 10
|
22 |
+
},
|
23 |
+
{
|
24 |
+
type: 'shadcn' as IconType,
|
25 |
+
position: 'left-[15px]',
|
26 |
+
link: 'https://ui.shadcn.com',
|
27 |
+
name: 'shadcn/ui',
|
28 |
+
zIndex: 20
|
29 |
+
},
|
30 |
+
{
|
31 |
+
type: 'tailwind' as IconType,
|
32 |
+
position: 'left-[30px]',
|
33 |
+
link: 'https://tailwindcss.com',
|
34 |
+
name: 'Tailwind CSS',
|
35 |
+
zIndex: 30
|
36 |
+
}
|
37 |
+
]
|
38 |
+
|
39 |
+
interface ActionButtonProps {
|
40 |
+
href: string
|
41 |
+
variant?: 'primary'
|
42 |
+
text: string
|
43 |
+
}
|
44 |
+
|
45 |
+
const ActionButton = ({ href, variant, text }: ActionButtonProps) => {
|
46 |
+
const baseStyles =
|
47 |
+
'px-4 py-2 text-sm transition-colors font-dmmono tracking-tight'
|
48 |
+
const variantStyles = {
|
49 |
+
primary: 'border border-border hover:bg-neutral-800 rounded-xl'
|
50 |
+
}
|
51 |
+
|
52 |
+
return (
|
53 |
+
<Link
|
54 |
+
href={href}
|
55 |
+
target="_blank"
|
56 |
+
className={`${baseStyles} ${variant ? variantStyles[variant] : ''}`}
|
57 |
+
>
|
58 |
+
{text}
|
59 |
+
</Link>
|
60 |
+
)
|
61 |
+
}
|
62 |
+
|
63 |
+
const ChatBlankState = () => {
|
64 |
+
const [hoveredIcon, setHoveredIcon] = useState<string | null>(null)
|
65 |
+
|
66 |
+
// Animation variants for the icon
|
67 |
+
const iconVariants: Variants = {
|
68 |
+
initial: { y: 0 },
|
69 |
+
hover: {
|
70 |
+
y: -8,
|
71 |
+
transition: {
|
72 |
+
type: 'spring',
|
73 |
+
stiffness: 150,
|
74 |
+
damping: 10,
|
75 |
+
mass: 0.5
|
76 |
+
}
|
77 |
+
},
|
78 |
+
exit: {
|
79 |
+
y: 0,
|
80 |
+
transition: {
|
81 |
+
type: 'spring',
|
82 |
+
stiffness: 200,
|
83 |
+
damping: 15,
|
84 |
+
mass: 0.6
|
85 |
+
}
|
86 |
+
}
|
87 |
+
}
|
88 |
+
|
89 |
+
// Animation variants for the tooltip
|
90 |
+
const tooltipVariants: Variants = {
|
91 |
+
hidden: {
|
92 |
+
opacity: 0,
|
93 |
+
transition: {
|
94 |
+
duration: 0.15,
|
95 |
+
ease: 'easeInOut'
|
96 |
+
}
|
97 |
+
},
|
98 |
+
visible: {
|
99 |
+
opacity: 1,
|
100 |
+
transition: {
|
101 |
+
duration: 0.15,
|
102 |
+
ease: 'easeInOut'
|
103 |
+
}
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
return (
|
108 |
+
<section
|
109 |
+
className="flex flex-col items-center text-center font-geist"
|
110 |
+
aria-label="Welcome message"
|
111 |
+
>
|
112 |
+
<div className="flex max-w-3xl flex-col gap-y-8">
|
113 |
+
<motion.h1
|
114 |
+
initial={{ opacity: 0, y: 10 }}
|
115 |
+
animate={{ opacity: 1, y: 0 }}
|
116 |
+
transition={{ duration: 0.5, delay: 0.3 }}
|
117 |
+
className="text-3xl font-[600] tracking-tight"
|
118 |
+
>
|
119 |
+
<div className="flex items-center justify-center gap-x-2 whitespace-nowrap font-medium">
|
120 |
+
<span className="flex items-center font-[600]">
|
121 |
+
This is an open-source
|
122 |
+
</span>
|
123 |
+
<span className="inline-flex translate-y-[10px] scale-125 items-center transition-transform duration-200 hover:rotate-6">
|
124 |
+
<Link
|
125 |
+
href={EXTERNAL_LINKS.agno}
|
126 |
+
target="_blank"
|
127 |
+
rel="noopener"
|
128 |
+
className="cursor-pointer"
|
129 |
+
>
|
130 |
+
<Icon type="agno-tag" size="default" />
|
131 |
+
</Link>
|
132 |
+
</span>
|
133 |
+
<span className="flex items-center font-[600]">
|
134 |
+
Agent UI, built with
|
135 |
+
</span>
|
136 |
+
<span className="inline-flex translate-y-[5px] scale-125 items-center">
|
137 |
+
<div className="relative ml-2 h-[40px] w-[90px]">
|
138 |
+
{TECH_ICONS.map((icon) => (
|
139 |
+
<motion.div
|
140 |
+
key={icon.type}
|
141 |
+
className={`absolute ${icon.position} top-0`}
|
142 |
+
style={{ zIndex: icon.zIndex }}
|
143 |
+
variants={iconVariants}
|
144 |
+
initial="initial"
|
145 |
+
whileHover="hover"
|
146 |
+
animate={hoveredIcon === icon.type ? 'hover' : 'exit'}
|
147 |
+
onHoverStart={() => setHoveredIcon(icon.type)}
|
148 |
+
onHoverEnd={() => setHoveredIcon(null)}
|
149 |
+
>
|
150 |
+
<Link
|
151 |
+
href={icon.link}
|
152 |
+
target="_blank"
|
153 |
+
rel="noopener"
|
154 |
+
className="relative block cursor-pointer"
|
155 |
+
>
|
156 |
+
<div>
|
157 |
+
<Icon type={icon.type} size="default" />
|
158 |
+
</div>
|
159 |
+
<motion.div
|
160 |
+
className="pointer-events-none absolute bottom-full left-1/2 mb-1 -translate-x-1/2 transform whitespace-nowrap rounded bg-neutral-800 px-2 py-1 text-xs text-primary"
|
161 |
+
variants={tooltipVariants}
|
162 |
+
initial="hidden"
|
163 |
+
animate={
|
164 |
+
hoveredIcon === icon.type ? 'visible' : 'hidden'
|
165 |
+
}
|
166 |
+
>
|
167 |
+
{icon.name}
|
168 |
+
</motion.div>
|
169 |
+
</Link>
|
170 |
+
</motion.div>
|
171 |
+
))}
|
172 |
+
</div>
|
173 |
+
</span>
|
174 |
+
</div>
|
175 |
+
<p>For the full experience, visit the Agent Playground.</p>
|
176 |
+
</motion.h1>
|
177 |
+
<motion.div
|
178 |
+
initial={{ opacity: 0, y: 10 }}
|
179 |
+
animate={{ opacity: 1, y: 0 }}
|
180 |
+
transition={{ duration: 0.5, delay: 0.5 }}
|
181 |
+
className="flex justify-center gap-4"
|
182 |
+
>
|
183 |
+
<ActionButton
|
184 |
+
href={EXTERNAL_LINKS.documentation}
|
185 |
+
variant="primary"
|
186 |
+
text="GO TO DOCS"
|
187 |
+
/>
|
188 |
+
<ActionButton
|
189 |
+
href={EXTERNAL_LINKS.playground}
|
190 |
+
text="VISIT AGENT PLAYGROUND"
|
191 |
+
/>
|
192 |
+
</motion.div>
|
193 |
+
</div>
|
194 |
+
</section>
|
195 |
+
)
|
196 |
+
}
|
197 |
+
|
198 |
+
export default ChatBlankState
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import Icon from '@/components/ui/icon'
|
2 |
+
import MarkdownRenderer from '@/components/ui/typography/MarkdownRenderer'
|
3 |
+
import { usePlaygroundStore } from '@/store'
|
4 |
+
import type { PlaygroundChatMessage } from '@/types/playground'
|
5 |
+
import Videos from './Multimedia/Videos'
|
6 |
+
import Images from './Multimedia/Images'
|
7 |
+
import Audios from './Multimedia/Audios'
|
8 |
+
import { memo } from 'react'
|
9 |
+
import AgentThinkingLoader from './AgentThinkingLoader'
|
10 |
+
|
11 |
+
interface MessageProps {
|
12 |
+
message: PlaygroundChatMessage
|
13 |
+
}
|
14 |
+
|
15 |
+
const AgentMessage = ({ message }: MessageProps) => {
|
16 |
+
const { streamingErrorMessage } = usePlaygroundStore()
|
17 |
+
let messageContent
|
18 |
+
if (message.streamingError) {
|
19 |
+
messageContent = (
|
20 |
+
<p className="text-destructive">
|
21 |
+
Oops! Something went wrong while streaming.{' '}
|
22 |
+
{streamingErrorMessage ? (
|
23 |
+
<>{streamingErrorMessage}</>
|
24 |
+
) : (
|
25 |
+
'Please try refreshing the page or try again later.'
|
26 |
+
)}
|
27 |
+
</p>
|
28 |
+
)
|
29 |
+
} else if (message.content) {
|
30 |
+
messageContent = (
|
31 |
+
<div className="flex w-full flex-col gap-4">
|
32 |
+
<MarkdownRenderer>{message.content}</MarkdownRenderer>
|
33 |
+
{message.videos && message.videos.length > 0 && (
|
34 |
+
<Videos videos={message.videos} />
|
35 |
+
)}
|
36 |
+
{message.images && message.images.length > 0 && (
|
37 |
+
<Images images={message.images} />
|
38 |
+
)}
|
39 |
+
{message.audio && message.audio.length > 0 && (
|
40 |
+
<Audios audio={message.audio} />
|
41 |
+
)}
|
42 |
+
</div>
|
43 |
+
)
|
44 |
+
} else if (message.response_audio) {
|
45 |
+
if (!message.response_audio.transcript) {
|
46 |
+
messageContent = (
|
47 |
+
<div className="mt-2 flex items-start">
|
48 |
+
<AgentThinkingLoader />
|
49 |
+
</div>
|
50 |
+
)
|
51 |
+
} else {
|
52 |
+
messageContent = (
|
53 |
+
<div className="flex w-full flex-col gap-4">
|
54 |
+
<MarkdownRenderer>
|
55 |
+
{message.response_audio.transcript}
|
56 |
+
</MarkdownRenderer>
|
57 |
+
{message.response_audio.content && message.response_audio && (
|
58 |
+
<Audios audio={[message.response_audio]} />
|
59 |
+
)}
|
60 |
+
</div>
|
61 |
+
)
|
62 |
+
}
|
63 |
+
} else {
|
64 |
+
messageContent = (
|
65 |
+
<div className="mt-2">
|
66 |
+
<AgentThinkingLoader />
|
67 |
+
</div>
|
68 |
+
)
|
69 |
+
}
|
70 |
+
|
71 |
+
return (
|
72 |
+
<div className="flex flex-row items-start gap-4 font-geist">
|
73 |
+
<div className="flex-shrink-0">
|
74 |
+
<Icon type="agent" size="sm" />
|
75 |
+
</div>
|
76 |
+
{messageContent}
|
77 |
+
</div>
|
78 |
+
)
|
79 |
+
}
|
80 |
+
|
81 |
+
const UserMessage = memo(({ message }: MessageProps) => {
|
82 |
+
return (
|
83 |
+
<div className="flex items-start pt-4 text-start max-md:break-words">
|
84 |
+
<div className="flex flex-row gap-x-3">
|
85 |
+
<p className="flex items-center gap-x-2 text-sm font-medium text-muted">
|
86 |
+
<Icon type="user" size="sm" />
|
87 |
+
</p>
|
88 |
+
<div className="text-md rounded-lg py-1 font-geist text-secondary">
|
89 |
+
{message.content}
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
</div>
|
93 |
+
)
|
94 |
+
})
|
95 |
+
|
96 |
+
AgentMessage.displayName = 'AgentMessage'
|
97 |
+
UserMessage.displayName = 'UserMessage'
|
98 |
+
export { AgentMessage, UserMessage }
|
@@ -0,0 +1,179 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import type { PlaygroundChatMessage } from '@/types/playground'
|
2 |
+
|
3 |
+
import { AgentMessage, UserMessage } from './MessageItem'
|
4 |
+
import Tooltip from '@/components/ui/tooltip'
|
5 |
+
import { memo } from 'react'
|
6 |
+
import {
|
7 |
+
ToolCallProps,
|
8 |
+
ReasoningStepProps,
|
9 |
+
ReasoningProps,
|
10 |
+
ReferenceData,
|
11 |
+
Reference
|
12 |
+
} from '@/types/playground'
|
13 |
+
import React, { type FC } from 'react'
|
14 |
+
import ChatBlankState from './ChatBlankState'
|
15 |
+
import Icon from '@/components/ui/icon'
|
16 |
+
|
17 |
+
interface MessageListProps {
|
18 |
+
messages: PlaygroundChatMessage[]
|
19 |
+
}
|
20 |
+
|
21 |
+
interface MessageWrapperProps {
|
22 |
+
message: PlaygroundChatMessage
|
23 |
+
isLastMessage: boolean
|
24 |
+
}
|
25 |
+
|
26 |
+
interface ReferenceProps {
|
27 |
+
references: ReferenceData[]
|
28 |
+
}
|
29 |
+
|
30 |
+
interface ReferenceItemProps {
|
31 |
+
reference: Reference
|
32 |
+
}
|
33 |
+
|
34 |
+
const ReferenceItem: FC<ReferenceItemProps> = ({ reference }) => (
|
35 |
+
<div className="relative flex h-[63px] w-[190px] cursor-default flex-col justify-between overflow-hidden rounded-md bg-background-secondary p-3 transition-colors hover:bg-background-secondary/80">
|
36 |
+
<p className="text-sm font-medium text-primary">{reference.name}</p>
|
37 |
+
<p className="truncate text-xs text-primary/40">{reference.content}</p>
|
38 |
+
</div>
|
39 |
+
)
|
40 |
+
|
41 |
+
const References: FC<ReferenceProps> = ({ references }) => (
|
42 |
+
<div className="flex flex-col gap-4">
|
43 |
+
{references.map((referenceData, index) => (
|
44 |
+
<div
|
45 |
+
key={`${referenceData.query}-${index}`}
|
46 |
+
className="flex flex-col gap-3"
|
47 |
+
>
|
48 |
+
<div className="flex flex-wrap gap-3">
|
49 |
+
{referenceData.references.map((reference, refIndex) => (
|
50 |
+
<ReferenceItem
|
51 |
+
key={`${reference.name}-${reference.meta_data.chunk}-${refIndex}`}
|
52 |
+
reference={reference}
|
53 |
+
/>
|
54 |
+
))}
|
55 |
+
</div>
|
56 |
+
</div>
|
57 |
+
))}
|
58 |
+
</div>
|
59 |
+
)
|
60 |
+
|
61 |
+
const AgentMessageWrapper = ({ message }: MessageWrapperProps) => {
|
62 |
+
return (
|
63 |
+
<div className="flex flex-col gap-y-9">
|
64 |
+
{message.extra_data?.reasoning_steps &&
|
65 |
+
message.extra_data.reasoning_steps.length > 0 && (
|
66 |
+
<div className="flex items-start gap-4">
|
67 |
+
<Tooltip
|
68 |
+
delayDuration={0}
|
69 |
+
content={<p className="text-accent">Reasoning</p>}
|
70 |
+
side="top"
|
71 |
+
>
|
72 |
+
<Icon type="reasoning" size="sm" />
|
73 |
+
</Tooltip>
|
74 |
+
<div className="flex flex-col gap-3">
|
75 |
+
<p className="text-xs uppercase">Reasoning</p>
|
76 |
+
<Reasonings reasoning={message.extra_data.reasoning_steps} />
|
77 |
+
</div>
|
78 |
+
</div>
|
79 |
+
)}
|
80 |
+
{message.extra_data?.references &&
|
81 |
+
message.extra_data.references.length > 0 && (
|
82 |
+
<div className="flex items-start gap-4">
|
83 |
+
<Tooltip
|
84 |
+
delayDuration={0}
|
85 |
+
content={<p className="text-accent">References</p>}
|
86 |
+
side="top"
|
87 |
+
>
|
88 |
+
<Icon type="references" size="sm" />
|
89 |
+
</Tooltip>
|
90 |
+
<div className="flex flex-col gap-3">
|
91 |
+
<References references={message.extra_data.references} />
|
92 |
+
</div>
|
93 |
+
</div>
|
94 |
+
)}
|
95 |
+
{message.tool_calls && message.tool_calls.length > 0 && (
|
96 |
+
<div className="flex items-center gap-3">
|
97 |
+
<Tooltip
|
98 |
+
delayDuration={0}
|
99 |
+
content={<p className="text-accent">Tool Calls</p>}
|
100 |
+
side="top"
|
101 |
+
>
|
102 |
+
<Icon
|
103 |
+
type="hammer"
|
104 |
+
className="rounded-lg bg-background-secondary p-1"
|
105 |
+
size="sm"
|
106 |
+
color="secondary"
|
107 |
+
/>
|
108 |
+
</Tooltip>
|
109 |
+
|
110 |
+
<div className="flex flex-wrap gap-2">
|
111 |
+
{message.tool_calls.map((toolCall, index) => (
|
112 |
+
<ToolComponent
|
113 |
+
key={
|
114 |
+
toolCall.tool_call_id ||
|
115 |
+
`${toolCall.tool_name}-${toolCall.created_at}-${index}`
|
116 |
+
}
|
117 |
+
tools={toolCall}
|
118 |
+
/>
|
119 |
+
))}
|
120 |
+
</div>
|
121 |
+
</div>
|
122 |
+
)}
|
123 |
+
<AgentMessage message={message} />
|
124 |
+
</div>
|
125 |
+
)
|
126 |
+
}
|
127 |
+
const Reasoning: FC<ReasoningStepProps> = ({ index, stepTitle }) => (
|
128 |
+
<div className="flex items-center gap-2 text-secondary">
|
129 |
+
<div className="flex h-[20px] items-center rounded-md bg-background-secondary p-2">
|
130 |
+
<p className="text-xs">STEP {index + 1}</p>
|
131 |
+
</div>
|
132 |
+
<p className="text-xs">{stepTitle}</p>
|
133 |
+
</div>
|
134 |
+
)
|
135 |
+
const Reasonings: FC<ReasoningProps> = ({ reasoning }) => (
|
136 |
+
<div className="flex flex-col items-start justify-center gap-2">
|
137 |
+
{reasoning.map((title, index) => (
|
138 |
+
<Reasoning
|
139 |
+
key={`${title.title}-${title.action}-${index}`}
|
140 |
+
stepTitle={title.title}
|
141 |
+
index={index}
|
142 |
+
/>
|
143 |
+
))}
|
144 |
+
</div>
|
145 |
+
)
|
146 |
+
|
147 |
+
const ToolComponent = memo(({ tools }: ToolCallProps) => (
|
148 |
+
<div className="cursor-default rounded-full bg-accent px-2 py-1.5 text-xs">
|
149 |
+
<p className="font-dmmono uppercase text-primary/80">{tools.tool_name}</p>
|
150 |
+
</div>
|
151 |
+
))
|
152 |
+
ToolComponent.displayName = 'ToolComponent'
|
153 |
+
const Messages = ({ messages }: MessageListProps) => {
|
154 |
+
if (messages.length === 0) {
|
155 |
+
return <ChatBlankState />
|
156 |
+
}
|
157 |
+
|
158 |
+
return (
|
159 |
+
<>
|
160 |
+
{messages.map((message, index) => {
|
161 |
+
const key = `${message.role}-${message.created_at}-${index}`
|
162 |
+
const isLastMessage = index === messages.length - 1
|
163 |
+
|
164 |
+
if (message.role === 'agent') {
|
165 |
+
return (
|
166 |
+
<AgentMessageWrapper
|
167 |
+
key={key}
|
168 |
+
message={message}
|
169 |
+
isLastMessage={isLastMessage}
|
170 |
+
/>
|
171 |
+
)
|
172 |
+
}
|
173 |
+
return <UserMessage key={key} message={message} />
|
174 |
+
})}
|
175 |
+
</>
|
176 |
+
)
|
177 |
+
}
|
178 |
+
|
179 |
+
export default Messages
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { memo, useMemo } from 'react'
|
4 |
+
|
5 |
+
import { type AudioData } from '@/types/playground'
|
6 |
+
import { decodeBase64Audio } from '@/lib/audio'
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Renders a single audio item with controls
|
10 |
+
* @param audio - AudioData object containing url or base64 audio data
|
11 |
+
*/
|
12 |
+
const AudioItem = memo(({ audio }: { audio: AudioData }) => {
|
13 |
+
const audioUrl = useMemo(() => {
|
14 |
+
if (audio?.url) {
|
15 |
+
return audio.url
|
16 |
+
}
|
17 |
+
if (audio.base64_audio) {
|
18 |
+
return decodeBase64Audio(
|
19 |
+
audio.base64_audio,
|
20 |
+
audio.mime_type || 'audio/wav'
|
21 |
+
)
|
22 |
+
}
|
23 |
+
if (audio.content) {
|
24 |
+
return decodeBase64Audio(
|
25 |
+
audio.content,
|
26 |
+
'audio/pcm16',
|
27 |
+
audio.sample_rate,
|
28 |
+
audio.channels
|
29 |
+
)
|
30 |
+
}
|
31 |
+
return null
|
32 |
+
}, [audio])
|
33 |
+
|
34 |
+
if (!audioUrl) return null
|
35 |
+
|
36 |
+
return (
|
37 |
+
<audio
|
38 |
+
src={audioUrl}
|
39 |
+
controls
|
40 |
+
className="w-full rounded-lg"
|
41 |
+
preload="metadata"
|
42 |
+
/>
|
43 |
+
)
|
44 |
+
})
|
45 |
+
|
46 |
+
AudioItem.displayName = 'AudioItem'
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Renders a list of audio elements
|
50 |
+
* @param audio - Array of AudioData objects
|
51 |
+
*/
|
52 |
+
const Audios = memo(({ audio }: { audio: AudioData[] }) => (
|
53 |
+
<div className="flex flex-col gap-4">
|
54 |
+
{audio.map((audio_item, index) => (
|
55 |
+
// TODO :: find a better way to handle the key
|
56 |
+
<AudioItem key={audio_item.id ?? `audio-${index}`} audio={audio_item} />
|
57 |
+
))}
|
58 |
+
</div>
|
59 |
+
))
|
60 |
+
|
61 |
+
Audios.displayName = 'Audios'
|
62 |
+
|
63 |
+
export default Audios
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import Audios from './Audios'
|
2 |
+
|
3 |
+
export default Audios
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { memo } from 'react'
|
2 |
+
|
3 |
+
import { type ImageData } from '@/types/playground'
|
4 |
+
import { cn } from '@/lib/utils'
|
5 |
+
|
6 |
+
const Images = ({ images }: { images: ImageData[] }) => (
|
7 |
+
<div
|
8 |
+
className={cn(
|
9 |
+
'grid max-w-xl gap-4',
|
10 |
+
images.length > 1 ? 'grid-cols-2' : 'grid-cols-1'
|
11 |
+
)}
|
12 |
+
>
|
13 |
+
{images.map((image) => (
|
14 |
+
<div key={image.url} className="group relative">
|
15 |
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
16 |
+
<img
|
17 |
+
src={image.url}
|
18 |
+
alt={image.revised_prompt || 'AI generated image'}
|
19 |
+
className="w-full rounded-lg"
|
20 |
+
onError={(e) => {
|
21 |
+
const parent = e.currentTarget.parentElement
|
22 |
+
if (parent) {
|
23 |
+
parent.innerHTML = `
|
24 |
+
<div class="flex h-40 flex-col items-center justify-center gap-2 rounded-md bg-secondary/50 text-muted" >
|
25 |
+
<p class="text-primary">Image unavailable</p>
|
26 |
+
<a href="${image.url}" target="_blank" class="max-w-md truncate underline text-primary text-xs w-full text-center p-2">
|
27 |
+
${image.url}
|
28 |
+
</a>
|
29 |
+
</div>
|
30 |
+
`
|
31 |
+
}
|
32 |
+
}}
|
33 |
+
/>
|
34 |
+
</div>
|
35 |
+
))}
|
36 |
+
</div>
|
37 |
+
)
|
38 |
+
|
39 |
+
export default memo(Images)
|
40 |
+
|
41 |
+
Images.displayName = 'Images'
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import Images from './Images'
|
2 |
+
|
3 |
+
export default Images
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { memo } from 'react'
|
4 |
+
|
5 |
+
import { toast } from 'sonner'
|
6 |
+
|
7 |
+
import { type VideoData } from '@/types/playground'
|
8 |
+
import Icon from '@/components/ui/icon'
|
9 |
+
|
10 |
+
const VideoItem = memo(({ video }: { video: VideoData }) => {
|
11 |
+
const videoUrl = video.url
|
12 |
+
|
13 |
+
const handleDownload = async () => {
|
14 |
+
try {
|
15 |
+
toast.loading('Downloading video...')
|
16 |
+
const response = await fetch(videoUrl)
|
17 |
+
if (!response.ok) throw new Error('Network response was not ok')
|
18 |
+
|
19 |
+
const blob = await response.blob()
|
20 |
+
const fileExtension = videoUrl.split('.').pop() ?? 'mp4'
|
21 |
+
const fileName = `video-${Date.now()}.${fileExtension}`
|
22 |
+
|
23 |
+
const url = window.URL.createObjectURL(blob)
|
24 |
+
const a = document.createElement('a')
|
25 |
+
a.href = url
|
26 |
+
a.download = fileName
|
27 |
+
|
28 |
+
document.body.appendChild(a)
|
29 |
+
a.click()
|
30 |
+
|
31 |
+
window.URL.revokeObjectURL(url)
|
32 |
+
document.body.removeChild(a)
|
33 |
+
toast.dismiss()
|
34 |
+
toast.success('Video downloaded successfully')
|
35 |
+
} catch {
|
36 |
+
toast.dismiss()
|
37 |
+
toast.error('Failed to download video')
|
38 |
+
}
|
39 |
+
}
|
40 |
+
|
41 |
+
return (
|
42 |
+
<div>
|
43 |
+
<div className="group relative w-full max-w-xl">
|
44 |
+
{}
|
45 |
+
<video
|
46 |
+
src={videoUrl}
|
47 |
+
autoPlay
|
48 |
+
muted
|
49 |
+
loop
|
50 |
+
controls
|
51 |
+
className="w-full rounded-lg"
|
52 |
+
style={{ aspectRatio: '16 / 9' }}
|
53 |
+
/>
|
54 |
+
<button
|
55 |
+
type="button"
|
56 |
+
onClick={handleDownload}
|
57 |
+
className="absolute right-2 top-2 flex items-center justify-center rounded-sm bg-secondary/80 p-1.5 opacity-0 transition-opacity duration-200 hover:bg-secondary group-hover:opacity-100"
|
58 |
+
aria-label="Download GIF"
|
59 |
+
>
|
60 |
+
<Icon type="download" size="xs" />
|
61 |
+
</button>
|
62 |
+
</div>
|
63 |
+
</div>
|
64 |
+
)
|
65 |
+
})
|
66 |
+
|
67 |
+
VideoItem.displayName = 'VideoItem'
|
68 |
+
|
69 |
+
const Videos = memo(({ videos }: { videos: VideoData[] }) => (
|
70 |
+
<div className="flex flex-col gap-4">
|
71 |
+
{videos.map((video) => (
|
72 |
+
<VideoItem key={video.id} video={video} />
|
73 |
+
))}
|
74 |
+
</div>
|
75 |
+
))
|
76 |
+
|
77 |
+
Videos.displayName = 'Videos'
|
78 |
+
|
79 |
+
export default Videos
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import Videos from './Videos'
|
2 |
+
|
3 |
+
export default Videos
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import Messages from './Messages'
|
2 |
+
|
3 |
+
export default Messages
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import type React from 'react'
|
4 |
+
|
5 |
+
import { motion, AnimatePresence } from 'framer-motion'
|
6 |
+
import { useStickToBottomContext } from 'use-stick-to-bottom'
|
7 |
+
|
8 |
+
import { Button } from '@/components/ui/button'
|
9 |
+
import Icon from '@/components/ui/icon'
|
10 |
+
|
11 |
+
const ScrollToBottom: React.FC = () => {
|
12 |
+
const { isAtBottom, scrollToBottom } = useStickToBottomContext()
|
13 |
+
|
14 |
+
return (
|
15 |
+
<AnimatePresence>
|
16 |
+
{!isAtBottom && (
|
17 |
+
<motion.div
|
18 |
+
initial={{ opacity: 0, y: 20 }}
|
19 |
+
animate={{ opacity: 1, y: 0 }}
|
20 |
+
exit={{ opacity: 0, y: 20 }}
|
21 |
+
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
22 |
+
className="absolute bottom-4 left-1/2 -translate-x-1/2"
|
23 |
+
>
|
24 |
+
<Button
|
25 |
+
onClick={() => scrollToBottom()}
|
26 |
+
type="button"
|
27 |
+
size="icon"
|
28 |
+
variant="secondary"
|
29 |
+
className="border border-border bg-background text-primary shadow-md transition-shadow duration-300 hover:bg-background-secondary"
|
30 |
+
>
|
31 |
+
<Icon type="arrow-down" size="xs" />
|
32 |
+
</Button>
|
33 |
+
</motion.div>
|
34 |
+
)}
|
35 |
+
</AnimatePresence>
|
36 |
+
)
|
37 |
+
}
|
38 |
+
|
39 |
+
export default ScrollToBottom
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import ChatArea from './ChatArea'
|
2 |
+
|
3 |
+
export { ChatArea }
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import * as React from 'react'
|
4 |
+
import {
|
5 |
+
Select,
|
6 |
+
SelectTrigger,
|
7 |
+
SelectValue,
|
8 |
+
SelectContent,
|
9 |
+
SelectItem
|
10 |
+
} from '@/components/ui/select'
|
11 |
+
import { usePlaygroundStore } from '@/store'
|
12 |
+
import { useQueryState } from 'nuqs'
|
13 |
+
import Icon from '@/components/ui/icon'
|
14 |
+
import { useEffect } from 'react'
|
15 |
+
import useChatActions from '@/hooks/useChatActions'
|
16 |
+
|
17 |
+
export function AgentSelector() {
|
18 |
+
const { agents, setMessages, setSelectedModel, setHasStorage } =
|
19 |
+
usePlaygroundStore()
|
20 |
+
const { focusChatInput } = useChatActions()
|
21 |
+
const [agentId, setAgentId] = useQueryState('agent', {
|
22 |
+
parse: (value) => value || undefined,
|
23 |
+
history: 'push'
|
24 |
+
})
|
25 |
+
const [, setSessionId] = useQueryState('session')
|
26 |
+
|
27 |
+
// Set the model when the component mounts if an agent is already selected
|
28 |
+
useEffect(() => {
|
29 |
+
if (agentId && agents.length > 0) {
|
30 |
+
const agent = agents.find((agent) => agent.value === agentId)
|
31 |
+
if (agent) {
|
32 |
+
setSelectedModel(agent.model.provider || '')
|
33 |
+
setHasStorage(!!agent.storage)
|
34 |
+
if (agent.model.provider) {
|
35 |
+
focusChatInput()
|
36 |
+
}
|
37 |
+
} else {
|
38 |
+
setAgentId(agents[0].value)
|
39 |
+
}
|
40 |
+
}
|
41 |
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
42 |
+
}, [agentId, agents, setSelectedModel])
|
43 |
+
|
44 |
+
const handleOnValueChange = (value: string) => {
|
45 |
+
const newAgent = value === agentId ? '' : value
|
46 |
+
const selectedAgent = agents.find((agent) => agent.value === newAgent)
|
47 |
+
setSelectedModel(selectedAgent?.model.provider || '')
|
48 |
+
setHasStorage(!!selectedAgent?.storage)
|
49 |
+
setAgentId(newAgent)
|
50 |
+
setMessages([])
|
51 |
+
setSessionId(null)
|
52 |
+
if (selectedAgent?.model.provider) {
|
53 |
+
focusChatInput()
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
return (
|
58 |
+
<Select
|
59 |
+
value={agentId || ''}
|
60 |
+
onValueChange={(value) => handleOnValueChange(value)}
|
61 |
+
>
|
62 |
+
<SelectTrigger className="h-9 w-full rounded-xl border border-primary/15 bg-primaryAccent text-xs font-medium uppercase">
|
63 |
+
<SelectValue placeholder="Select Agent" />
|
64 |
+
</SelectTrigger>
|
65 |
+
<SelectContent className="border-none bg-primaryAccent font-dmmono shadow-lg">
|
66 |
+
{agents.map((agent, index) => (
|
67 |
+
<SelectItem
|
68 |
+
className="cursor-pointer"
|
69 |
+
key={`${agent.value}-${index}`}
|
70 |
+
value={agent.value}
|
71 |
+
>
|
72 |
+
<div className="flex items-center gap-3 text-xs font-medium uppercase">
|
73 |
+
<Icon type={'agent'} size="xs" />
|
74 |
+
{agent.label}
|
75 |
+
</div>
|
76 |
+
</SelectItem>
|
77 |
+
))}
|
78 |
+
{agents.length === 0 && (
|
79 |
+
<SelectItem
|
80 |
+
value="no-agents"
|
81 |
+
className="cursor-not-allowed select-none text-center"
|
82 |
+
>
|
83 |
+
No agents found
|
84 |
+
</SelectItem>
|
85 |
+
)}
|
86 |
+
</SelectContent>
|
87 |
+
</Select>
|
88 |
+
)
|
89 |
+
}
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { Button } from '@/components/ui/button'
|
4 |
+
import Icon from '@/components/ui/icon'
|
5 |
+
import useChatActions from '@/hooks/useChatActions'
|
6 |
+
import { usePlaygroundStore } from '@/store'
|
7 |
+
|
8 |
+
function NewChatButton() {
|
9 |
+
const { clearChat } = useChatActions()
|
10 |
+
const { messages } = usePlaygroundStore()
|
11 |
+
return (
|
12 |
+
<Button
|
13 |
+
className="z-10 cursor-pointer rounded bg-brand px-4 py-2 font-bold text-primary hover:bg-brand/80 disabled:cursor-not-allowed disabled:opacity-50"
|
14 |
+
onClick={clearChat}
|
15 |
+
disabled={messages.length === 0}
|
16 |
+
>
|
17 |
+
<div className="flex items-center gap-2">
|
18 |
+
<p>New Chat</p>{' '}
|
19 |
+
<Icon type="plus-icon" size="xs" className="text-background" />
|
20 |
+
</div>
|
21 |
+
</Button>
|
22 |
+
)
|
23 |
+
}
|
24 |
+
|
25 |
+
export default NewChatButton
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { type FC } from 'react'
|
2 |
+
|
3 |
+
import { Button } from '@/components/ui/button'
|
4 |
+
import {
|
5 |
+
Dialog,
|
6 |
+
DialogContent,
|
7 |
+
DialogDescription,
|
8 |
+
DialogFooter,
|
9 |
+
DialogHeader,
|
10 |
+
DialogTitle
|
11 |
+
} from '@/components/ui/dialog'
|
12 |
+
|
13 |
+
interface DeleteSessionModalProps {
|
14 |
+
isOpen: boolean
|
15 |
+
onClose: () => void
|
16 |
+
onDelete: () => Promise<void>
|
17 |
+
isDeleting: boolean
|
18 |
+
}
|
19 |
+
|
20 |
+
const DeleteSessionModal: FC<DeleteSessionModalProps> = ({
|
21 |
+
isOpen,
|
22 |
+
onClose,
|
23 |
+
onDelete,
|
24 |
+
isDeleting
|
25 |
+
}) => (
|
26 |
+
<Dialog open={isOpen} onOpenChange={onClose}>
|
27 |
+
<DialogContent className="font-geist">
|
28 |
+
<DialogHeader>
|
29 |
+
<DialogTitle>Confirm deletion</DialogTitle>
|
30 |
+
<DialogDescription>
|
31 |
+
This will permanently delete the session. This action cannot be
|
32 |
+
undone.
|
33 |
+
</DialogDescription>
|
34 |
+
</DialogHeader>
|
35 |
+
<DialogFooter>
|
36 |
+
<Button
|
37 |
+
variant="outline"
|
38 |
+
className="rounded-xl border-border font-geist"
|
39 |
+
onClick={onClose}
|
40 |
+
disabled={isDeleting}
|
41 |
+
>
|
42 |
+
CANCEL
|
43 |
+
</Button>
|
44 |
+
<Button
|
45 |
+
variant="destructive"
|
46 |
+
onClick={onDelete}
|
47 |
+
disabled={isDeleting}
|
48 |
+
className="rounded-xl font-geist"
|
49 |
+
>
|
50 |
+
DELETE
|
51 |
+
</Button>
|
52 |
+
</DialogFooter>
|
53 |
+
</DialogContent>
|
54 |
+
</Dialog>
|
55 |
+
)
|
56 |
+
|
57 |
+
export default DeleteSessionModal
|
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react'
|
2 |
+
import { usePlaygroundStore } from '@/store'
|
3 |
+
import { useQueryState } from 'nuqs'
|
4 |
+
import Link from 'next/link'
|
5 |
+
|
6 |
+
const HistoryBlankStateIcon = () => (
|
7 |
+
<svg
|
8 |
+
width="90"
|
9 |
+
height="89"
|
10 |
+
viewBox="0 0 90 89"
|
11 |
+
fill="none"
|
12 |
+
xmlns="http://www.w3.org/2000/svg"
|
13 |
+
>
|
14 |
+
<path
|
15 |
+
d="M60.0192 18.2484L75.7339 21.2565C80.9549 22.2558 84.3771 27.2984 83.3777 32.5194L80.3697 48.2341C79.3703 53.455 74.3277 56.8773 69.1067 55.8779L53.3921 52.8698C48.1711 51.8704 44.7489 46.8278 45.7482 41.6069L48.7563 25.8922C49.7557 20.6712 54.7983 17.249 60.0192 18.2484Z"
|
16 |
+
stroke="white"
|
17 |
+
strokeOpacity="0.15"
|
18 |
+
strokeWidth="0.75"
|
19 |
+
/>
|
20 |
+
<path
|
21 |
+
d="M52.6787 34.7885C53.9351 28.225 60.2744 23.9228 66.8378 25.1792V25.1792C73.4013 26.4355 77.7036 32.7748 76.4472 39.3383V39.3383C75.1908 45.9017 68.8516 50.204 62.2881 48.9476V48.9476C55.7246 47.6913 51.4224 41.352 52.6787 34.7885V34.7885Z"
|
22 |
+
fill="#FF4017"
|
23 |
+
/>
|
24 |
+
<g clipPath="url(#clip1_9008_17675)">
|
25 |
+
<path
|
26 |
+
fillRule="evenodd"
|
27 |
+
clipRule="evenodd"
|
28 |
+
d="M59.8503 32.7422C59.5795 32.6962 59.3962 32.4446 59.4409 32.1802C59.6051 31.2079 60.0017 30.4826 60.7415 30.1543C61.4471 29.8413 62.3116 29.9643 63.221 30.2791C63.4804 30.3689 63.6182 30.6467 63.5286 30.8995C63.4391 31.1524 63.1562 31.2846 62.8968 31.1948C62.0492 30.9014 61.5019 30.8876 61.1589 31.0398C60.8501 31.1768 60.5613 31.519 60.4215 32.3469C60.3768 32.6112 60.1211 32.7882 59.8503 32.7422Z"
|
29 |
+
fill="white"
|
30 |
+
/>
|
31 |
+
<path
|
32 |
+
fillRule="evenodd"
|
33 |
+
clipRule="evenodd"
|
34 |
+
d="M70.6365 34.8074C70.9052 34.8646 71.1684 34.6985 71.2246 34.4363C71.431 33.4721 71.3304 32.6517 70.7641 32.0734C70.224 31.5218 69.3752 31.3169 68.4138 31.2736C68.1395 31.2612 67.909 31.4685 67.8988 31.7365C67.8886 32.0046 68.1026 32.2319 68.3769 32.2443C69.2729 32.2847 69.7866 32.474 70.0492 32.7421C70.2855 32.9835 70.4276 33.4081 70.2518 34.2291C70.1956 34.4912 70.3679 34.7502 70.6365 34.8074Z"
|
35 |
+
fill="white"
|
36 |
+
/>
|
37 |
+
<path
|
38 |
+
d="M63.6581 36.939C63.5614 37.4443 63.0733 37.7755 62.5681 37.6787C62.0628 37.582 61.7316 37.094 61.8283 36.5887C61.925 36.0834 62.413 35.7522 62.9183 35.849C63.4236 35.9457 63.7548 36.4337 63.6581 36.939Z"
|
39 |
+
fill="white"
|
40 |
+
/>
|
41 |
+
<path
|
42 |
+
d="M67.318 37.6392C67.2213 38.1444 66.7332 38.4756 66.228 38.3789C65.7227 38.2822 65.3915 37.7942 65.4882 37.2889C65.5849 36.7836 66.0729 36.4524 66.5782 36.5492C67.0835 36.6459 67.4147 37.1339 67.318 37.6392Z"
|
43 |
+
fill="white"
|
44 |
+
/>
|
45 |
+
<path
|
46 |
+
fillRule="evenodd"
|
47 |
+
clipRule="evenodd"
|
48 |
+
d="M69.4411 41.0527C69.7119 41.0986 69.8945 41.3539 69.8489 41.6229C69.6814 42.6122 69.2823 43.351 68.5409 43.6873C67.8339 44.0079 66.9693 43.8856 66.0603 43.5684C65.801 43.478 65.6641 43.1959 65.7545 42.9385C65.8449 42.6811 66.1284 42.5457 66.3877 42.6362C67.2348 42.9318 67.7825 42.944 68.1262 42.7881C68.4356 42.6478 68.7257 42.2989 68.8683 41.4566C68.9138 41.1876 69.1703 41.0068 69.4411 41.0527Z"
|
49 |
+
fill="white"
|
50 |
+
/>
|
51 |
+
<path
|
52 |
+
fillRule="evenodd"
|
53 |
+
clipRule="evenodd"
|
54 |
+
d="M58.6548 38.9885C58.3862 38.9312 58.1223 39.101 58.0652 39.3678C57.8555 40.349 57.9536 41.183 58.5184 41.7692C59.057 42.3283 59.9057 42.534 60.8675 42.5749C61.1419 42.5866 61.3733 42.3751 61.3844 42.1025C61.3954 41.8298 61.182 41.5994 60.9076 41.5877C60.0112 41.5495 59.4977 41.3586 59.2359 41.0868C59.0002 40.8422 58.8594 40.4108 59.038 39.5754C59.095 39.3086 58.9234 39.0458 58.6548 38.9885Z"
|
55 |
+
fill="white"
|
56 |
+
/>
|
57 |
+
</g>
|
58 |
+
<path
|
59 |
+
d="M4.32008 49.0567C3.54981 43.797 7.18916 38.9088 12.4488 38.1386L28.2799 35.8201C33.5396 35.0498 38.4278 38.6892 39.198 43.9488L41.5165 59.7799C42.2868 65.0396 38.6474 69.9278 33.3878 70.698L17.5567 73.0165C12.297 73.7868 7.40882 70.1474 6.63855 64.8878L4.32008 49.0567Z"
|
60 |
+
stroke="white"
|
61 |
+
strokeOpacity="0.15"
|
62 |
+
strokeWidth="0.75"
|
63 |
+
/>
|
64 |
+
<path
|
65 |
+
d="M11.0451 56.1568C10.085 49.5994 14.6225 43.5051 21.18 42.545C27.7375 41.5848 33.8318 46.1224 34.7919 52.6799C35.7521 59.2374 31.2145 65.3316 24.657 66.2918C18.0995 67.2519 12.0053 62.7143 11.0451 56.1568Z"
|
66 |
+
fill="white"
|
67 |
+
/>
|
68 |
+
<g clipPath="url(#clip0_7378_12246)">
|
69 |
+
<path
|
70 |
+
d="M29.1447 55.5281C29.1959 55.878 29.1061 56.2339 28.8949 56.5175C28.6837 56.8011 28.3685 56.9893 28.0186 57.0405L20.103 58.1995L17.8508 61.2244L16.3055 50.6702C16.2542 50.3203 16.3441 49.9644 16.5553 49.6808C16.7665 49.3971 17.0817 49.209 17.4316 49.1578L26.6664 47.8056C27.0163 47.7544 27.3722 47.8443 27.6559 48.0554C27.9395 48.2666 28.1276 48.5818 28.1789 48.9317L29.1447 55.5281Z"
|
71 |
+
stroke="black"
|
72 |
+
strokeLinecap="round"
|
73 |
+
strokeLinejoin="round"
|
74 |
+
/>
|
75 |
+
</g>
|
76 |
+
<defs>
|
77 |
+
<clipPath id="clip0_7378_12246">
|
78 |
+
<rect
|
79 |
+
width="16"
|
80 |
+
height="16"
|
81 |
+
fill="white"
|
82 |
+
transform="translate(13.8438 47.6617) rotate(-8.33)"
|
83 |
+
/>
|
84 |
+
</clipPath>
|
85 |
+
</defs>
|
86 |
+
</svg>
|
87 |
+
)
|
88 |
+
|
89 |
+
const SessionBlankState = () => {
|
90 |
+
const { selectedEndpoint, isEndpointActive, hasStorage } =
|
91 |
+
usePlaygroundStore()
|
92 |
+
const [agentId] = useQueryState('agent')
|
93 |
+
|
94 |
+
const errorMessage = (() => {
|
95 |
+
switch (true) {
|
96 |
+
case !isEndpointActive:
|
97 |
+
return 'Endpoint is not connected. Please connect the endpoint to see the history.'
|
98 |
+
case !selectedEndpoint:
|
99 |
+
return 'Select an endpoint to see the history.'
|
100 |
+
case !agentId:
|
101 |
+
return 'Select an agent to see the history.'
|
102 |
+
case !hasStorage:
|
103 |
+
return (
|
104 |
+
<>
|
105 |
+
Connect{' '}
|
106 |
+
<Link
|
107 |
+
className="underline"
|
108 |
+
href={'https://docs.agno.com/storage'}
|
109 |
+
target="_blank"
|
110 |
+
>
|
111 |
+
storage
|
112 |
+
</Link>{' '}
|
113 |
+
to your agent to see sessions.{' '}
|
114 |
+
</>
|
115 |
+
)
|
116 |
+
default:
|
117 |
+
return 'No session records yet. Start a conversation to create one.'
|
118 |
+
}
|
119 |
+
})()
|
120 |
+
|
121 |
+
return (
|
122 |
+
<div className="mt-1 flex items-center justify-center rounded-lg bg-background-secondary/50 pb-6 pt-4">
|
123 |
+
<div className="flex flex-col items-center gap-1">
|
124 |
+
<HistoryBlankStateIcon />
|
125 |
+
<div className="flex flex-col items-center gap-2">
|
126 |
+
<h3 className="text-sm font-medium text-primary">No Session found</h3>
|
127 |
+
<p className="max-w-[210px] text-center text-sm text-muted">
|
128 |
+
{errorMessage}
|
129 |
+
</p>
|
130 |
+
</div>
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
)
|
134 |
+
}
|
135 |
+
|
136 |
+
export default SessionBlankState
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { useQueryState } from 'nuqs'
|
2 |
+
import { SessionEntry } from '@/types/playground'
|
3 |
+
import { Button } from '../../../ui/button'
|
4 |
+
import useSessionLoader from '@/hooks/useSessionLoader'
|
5 |
+
import { deletePlaygroundSessionAPI } from '@/api/playground'
|
6 |
+
import { usePlaygroundStore } from '@/store'
|
7 |
+
import { toast } from 'sonner'
|
8 |
+
import Icon from '@/components/ui/icon'
|
9 |
+
import { useState } from 'react'
|
10 |
+
import DeleteSessionModal from './DeleteSessionModal'
|
11 |
+
import useChatActions from '@/hooks/useChatActions'
|
12 |
+
import { truncateText, cn } from '@/lib/utils'
|
13 |
+
|
14 |
+
type SessionItemProps = SessionEntry & {
|
15 |
+
isSelected: boolean
|
16 |
+
onSessionClick: () => void
|
17 |
+
}
|
18 |
+
const SessionItem = ({
|
19 |
+
title,
|
20 |
+
session_id,
|
21 |
+
isSelected,
|
22 |
+
onSessionClick
|
23 |
+
}: SessionItemProps) => {
|
24 |
+
const [agentId] = useQueryState('agent')
|
25 |
+
const { getSession } = useSessionLoader()
|
26 |
+
const [, setSessionId] = useQueryState('session')
|
27 |
+
const { selectedEndpoint, sessionsData, setSessionsData } =
|
28 |
+
usePlaygroundStore()
|
29 |
+
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false)
|
30 |
+
const { clearChat } = useChatActions()
|
31 |
+
|
32 |
+
const handleGetSession = async () => {
|
33 |
+
if (agentId) {
|
34 |
+
onSessionClick()
|
35 |
+
await getSession(session_id, agentId)
|
36 |
+
setSessionId(session_id)
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
const handleDeleteSession = async () => {
|
41 |
+
if (agentId) {
|
42 |
+
try {
|
43 |
+
const response = await deletePlaygroundSessionAPI(
|
44 |
+
selectedEndpoint,
|
45 |
+
agentId,
|
46 |
+
session_id
|
47 |
+
)
|
48 |
+
if (response.status === 200 && sessionsData) {
|
49 |
+
setSessionsData(
|
50 |
+
sessionsData.filter((session) => session.session_id !== session_id)
|
51 |
+
)
|
52 |
+
clearChat()
|
53 |
+
toast.success('Session deleted')
|
54 |
+
} else {
|
55 |
+
toast.error('Failed to delete session')
|
56 |
+
}
|
57 |
+
} catch {
|
58 |
+
toast.error('Failed to delete session')
|
59 |
+
} finally {
|
60 |
+
setIsDeleteModalOpen(false)
|
61 |
+
}
|
62 |
+
}
|
63 |
+
}
|
64 |
+
return (
|
65 |
+
<>
|
66 |
+
<div
|
67 |
+
className={cn(
|
68 |
+
'group flex h-11 w-full cursor-pointer items-center justify-between rounded-lg px-3 py-2 transition-colors duration-200',
|
69 |
+
isSelected
|
70 |
+
? 'cursor-default bg-primary/10'
|
71 |
+
: 'bg-background-secondary hover:bg-background-secondary/80'
|
72 |
+
)}
|
73 |
+
onClick={handleGetSession}
|
74 |
+
>
|
75 |
+
<div className="flex flex-col gap-1">
|
76 |
+
<h4
|
77 |
+
className={cn('text-sm font-medium', isSelected && 'text-primary')}
|
78 |
+
>
|
79 |
+
{truncateText(title, 20)}
|
80 |
+
</h4>
|
81 |
+
</div>
|
82 |
+
<Button
|
83 |
+
variant="ghost"
|
84 |
+
size="icon"
|
85 |
+
className="transform opacity-0 transition-all duration-200 ease-in-out group-hover:opacity-100"
|
86 |
+
onClick={(e) => {
|
87 |
+
e.stopPropagation()
|
88 |
+
setIsDeleteModalOpen(true)
|
89 |
+
}}
|
90 |
+
>
|
91 |
+
<Icon type="trash" size="xs" />
|
92 |
+
</Button>
|
93 |
+
</div>
|
94 |
+
<DeleteSessionModal
|
95 |
+
isOpen={isDeleteModalOpen}
|
96 |
+
onClose={() => setIsDeleteModalOpen(false)}
|
97 |
+
onDelete={handleDeleteSession}
|
98 |
+
isDeleting={false}
|
99 |
+
/>
|
100 |
+
</>
|
101 |
+
)
|
102 |
+
}
|
103 |
+
|
104 |
+
export default SessionItem
|
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import { useEffect, useMemo, useState, useRef, useCallback } from 'react'
|
4 |
+
import dayjs from 'dayjs'
|
5 |
+
import utc from 'dayjs/plugin/utc'
|
6 |
+
|
7 |
+
import { usePlaygroundStore } from '@/store'
|
8 |
+
import { useQueryState } from 'nuqs'
|
9 |
+
import SessionItem from './SessionItem'
|
10 |
+
import SessionBlankState from './SessionBlankState'
|
11 |
+
import useSessionLoader from '@/hooks/useSessionLoader'
|
12 |
+
|
13 |
+
import { cn } from '@/lib/utils'
|
14 |
+
import { FC } from 'react'
|
15 |
+
import { Skeleton } from '@/components/ui/skeleton'
|
16 |
+
|
17 |
+
interface SkeletonListProps {
|
18 |
+
skeletonCount: number
|
19 |
+
}
|
20 |
+
|
21 |
+
const SkeletonList: FC<SkeletonListProps> = ({ skeletonCount }) => {
|
22 |
+
const skeletons = useMemo(
|
23 |
+
() => Array.from({ length: skeletonCount }, (_, i) => i),
|
24 |
+
[skeletonCount]
|
25 |
+
)
|
26 |
+
|
27 |
+
return skeletons.map((skeleton, index) => (
|
28 |
+
<Skeleton
|
29 |
+
key={skeleton}
|
30 |
+
className={cn(
|
31 |
+
'mb-1 h-11 rounded-lg px-3 py-2',
|
32 |
+
index > 0 && 'bg-background-secondary'
|
33 |
+
)}
|
34 |
+
/>
|
35 |
+
))
|
36 |
+
}
|
37 |
+
|
38 |
+
dayjs.extend(utc)
|
39 |
+
|
40 |
+
const formatDate = (
|
41 |
+
timestamp: number,
|
42 |
+
format: 'natural' | 'full' = 'full'
|
43 |
+
): string => {
|
44 |
+
const date = dayjs.unix(timestamp).utc()
|
45 |
+
return format === 'natural'
|
46 |
+
? date.format('HH:mm')
|
47 |
+
: date.format('YYYY-MM-DD HH:mm:ss')
|
48 |
+
}
|
49 |
+
|
50 |
+
const Sessions = () => {
|
51 |
+
const [agentId] = useQueryState('agent', {
|
52 |
+
parse: (value) => value || undefined,
|
53 |
+
history: 'push'
|
54 |
+
})
|
55 |
+
const [sessionId] = useQueryState('session')
|
56 |
+
const {
|
57 |
+
selectedEndpoint,
|
58 |
+
isEndpointActive,
|
59 |
+
isEndpointLoading,
|
60 |
+
sessionsData,
|
61 |
+
hydrated,
|
62 |
+
hasStorage,
|
63 |
+
setSessionsData
|
64 |
+
} = usePlaygroundStore()
|
65 |
+
const [isScrolling, setIsScrolling] = useState(false)
|
66 |
+
const [selectedSessionId, setSelectedSessionId] = useState<string | null>(
|
67 |
+
null
|
68 |
+
)
|
69 |
+
const { getSession, getSessions } = useSessionLoader()
|
70 |
+
const scrollTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)
|
71 |
+
const { isSessionsLoading } = usePlaygroundStore()
|
72 |
+
|
73 |
+
const handleScroll = () => {
|
74 |
+
setIsScrolling(true)
|
75 |
+
|
76 |
+
if (scrollTimeoutRef.current) {
|
77 |
+
clearTimeout(scrollTimeoutRef.current)
|
78 |
+
}
|
79 |
+
|
80 |
+
scrollTimeoutRef.current = setTimeout(() => {
|
81 |
+
setIsScrolling(false)
|
82 |
+
}, 1500)
|
83 |
+
}
|
84 |
+
|
85 |
+
// Cleanup the scroll timeout when component unmounts
|
86 |
+
useEffect(() => {
|
87 |
+
return () => {
|
88 |
+
if (scrollTimeoutRef.current) {
|
89 |
+
clearTimeout(scrollTimeoutRef.current)
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}, [])
|
93 |
+
|
94 |
+
// Load a session on render if a session id exists in url
|
95 |
+
useEffect(() => {
|
96 |
+
if (sessionId && agentId && selectedEndpoint && hydrated) {
|
97 |
+
getSession(sessionId, agentId)
|
98 |
+
}
|
99 |
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
100 |
+
}, [hydrated])
|
101 |
+
|
102 |
+
useEffect(() => {
|
103 |
+
if (!selectedEndpoint || !agentId || !hasStorage) {
|
104 |
+
setSessionsData(() => null)
|
105 |
+
return
|
106 |
+
}
|
107 |
+
if (!isEndpointLoading) {
|
108 |
+
setSessionsData(() => null)
|
109 |
+
getSessions(agentId)
|
110 |
+
}
|
111 |
+
}, [
|
112 |
+
selectedEndpoint,
|
113 |
+
agentId,
|
114 |
+
getSessions,
|
115 |
+
isEndpointLoading,
|
116 |
+
hasStorage,
|
117 |
+
setSessionsData
|
118 |
+
])
|
119 |
+
|
120 |
+
useEffect(() => {
|
121 |
+
if (sessionId) {
|
122 |
+
setSelectedSessionId(sessionId)
|
123 |
+
}
|
124 |
+
}, [sessionId])
|
125 |
+
|
126 |
+
const formattedSessionsData = useMemo(() => {
|
127 |
+
if (!sessionsData || !Array.isArray(sessionsData)) return []
|
128 |
+
|
129 |
+
return sessionsData.map((entry) => ({
|
130 |
+
...entry,
|
131 |
+
created_at: entry.created_at,
|
132 |
+
formatted_time: formatDate(entry.created_at, 'natural')
|
133 |
+
}))
|
134 |
+
}, [sessionsData])
|
135 |
+
|
136 |
+
const handleSessionClick = useCallback(
|
137 |
+
(id: string) => () => setSelectedSessionId(id),
|
138 |
+
[]
|
139 |
+
)
|
140 |
+
|
141 |
+
if (isSessionsLoading || isEndpointLoading)
|
142 |
+
return (
|
143 |
+
<div className="w-full">
|
144 |
+
<div className="mb-2 text-xs font-medium uppercase">Sessions</div>
|
145 |
+
<div className="mt-4 h-[calc(100vh-325px)] w-full overflow-y-auto">
|
146 |
+
<SkeletonList skeletonCount={5} />
|
147 |
+
</div>
|
148 |
+
</div>
|
149 |
+
)
|
150 |
+
return (
|
151 |
+
<div className="w-full">
|
152 |
+
<div className="mb-2 w-full text-xs font-medium uppercase">Sessions</div>
|
153 |
+
<div
|
154 |
+
className={`h-[calc(100vh-345px)] overflow-y-auto font-geist transition-all duration-300 [&::-webkit-scrollbar]:w-1 [&::-webkit-scrollbar]:transition-opacity [&::-webkit-scrollbar]:duration-300 ${isScrolling ? '[&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-background [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar]:opacity-0' : '[&::-webkit-scrollbar]:opacity-100'}`}
|
155 |
+
onScroll={handleScroll}
|
156 |
+
onMouseOver={() => setIsScrolling(true)}
|
157 |
+
onMouseLeave={handleScroll}
|
158 |
+
>
|
159 |
+
{!isEndpointActive ||
|
160 |
+
!hasStorage ||
|
161 |
+
(!isSessionsLoading && (!sessionsData || sessionsData.length === 0)) ? (
|
162 |
+
<SessionBlankState />
|
163 |
+
) : (
|
164 |
+
<div className="flex flex-col gap-y-1 pr-1">
|
165 |
+
{formattedSessionsData.map((entry, index) => (
|
166 |
+
<SessionItem
|
167 |
+
key={`${entry.session_id}-${index}`}
|
168 |
+
{...entry}
|
169 |
+
isSelected={selectedSessionId === entry.session_id}
|
170 |
+
onSessionClick={handleSessionClick(entry.session_id)}
|
171 |
+
/>
|
172 |
+
))}
|
173 |
+
</div>
|
174 |
+
)}
|
175 |
+
</div>
|
176 |
+
</div>
|
177 |
+
)
|
178 |
+
}
|
179 |
+
|
180 |
+
export default Sessions
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import Sessions from './Sessions'
|
2 |
+
|
3 |
+
export default Sessions
|
@@ -0,0 +1,298 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
import { Button } from '@/components/ui/button'
|
3 |
+
import { AgentSelector } from '@/components/playground/Sidebar/AgentSelector'
|
4 |
+
import useChatActions from '@/hooks/useChatActions'
|
5 |
+
import { usePlaygroundStore } from '@/store'
|
6 |
+
import { motion, AnimatePresence } from 'framer-motion'
|
7 |
+
import { useState, useEffect } from 'react'
|
8 |
+
import Icon from '@/components/ui/icon'
|
9 |
+
import { getProviderIcon } from '@/lib/modelProvider'
|
10 |
+
import Sessions from './Sessions'
|
11 |
+
import { isValidUrl } from '@/lib/utils'
|
12 |
+
import { toast } from 'sonner'
|
13 |
+
import { useQueryState } from 'nuqs'
|
14 |
+
import { truncateText } from '@/lib/utils'
|
15 |
+
import { Skeleton } from '@/components/ui/skeleton'
|
16 |
+
const ENDPOINT_PLACEHOLDER = 'NO ENDPOINT ADDED'
|
17 |
+
const SidebarHeader = () => (
|
18 |
+
<div className="flex items-center gap-2">
|
19 |
+
<Icon type="agno" size="xs" />
|
20 |
+
<span className="text-xs font-medium uppercase text-white">Agent UI</span>
|
21 |
+
</div>
|
22 |
+
)
|
23 |
+
|
24 |
+
const NewChatButton = ({
|
25 |
+
disabled,
|
26 |
+
onClick
|
27 |
+
}: {
|
28 |
+
disabled: boolean
|
29 |
+
onClick: () => void
|
30 |
+
}) => (
|
31 |
+
<Button
|
32 |
+
onClick={onClick}
|
33 |
+
disabled={disabled}
|
34 |
+
size="lg"
|
35 |
+
className="h-9 w-full rounded-xl bg-primary text-xs font-medium text-background hover:bg-primary/80"
|
36 |
+
>
|
37 |
+
<Icon type="plus-icon" size="xs" className="text-background" />
|
38 |
+
<span className="uppercase">New Chat</span>
|
39 |
+
</Button>
|
40 |
+
)
|
41 |
+
|
42 |
+
const ModelDisplay = ({ model }: { model: string }) => (
|
43 |
+
<div className="flex h-9 w-full items-center gap-3 rounded-xl border border-primary/15 bg-accent p-3 text-xs font-medium uppercase text-muted">
|
44 |
+
{(() => {
|
45 |
+
const icon = getProviderIcon(model)
|
46 |
+
return icon ? <Icon type={icon} className="shrink-0" size="xs" /> : null
|
47 |
+
})()}
|
48 |
+
{model}
|
49 |
+
</div>
|
50 |
+
)
|
51 |
+
|
52 |
+
const Endpoint = () => {
|
53 |
+
const {
|
54 |
+
selectedEndpoint,
|
55 |
+
isEndpointActive,
|
56 |
+
setSelectedEndpoint,
|
57 |
+
setAgents,
|
58 |
+
setSessionsData,
|
59 |
+
setMessages
|
60 |
+
} = usePlaygroundStore()
|
61 |
+
const { initializePlayground } = useChatActions()
|
62 |
+
const [isEditing, setIsEditing] = useState(false)
|
63 |
+
const [endpointValue, setEndpointValue] = useState('')
|
64 |
+
const [isMounted, setIsMounted] = useState(false)
|
65 |
+
const [isHovering, setIsHovering] = useState(false)
|
66 |
+
const [isRotating, setIsRotating] = useState(false)
|
67 |
+
const [, setAgentId] = useQueryState('agent')
|
68 |
+
const [, setSessionId] = useQueryState('session')
|
69 |
+
|
70 |
+
useEffect(() => {
|
71 |
+
setEndpointValue(selectedEndpoint)
|
72 |
+
setIsMounted(true)
|
73 |
+
}, [selectedEndpoint])
|
74 |
+
|
75 |
+
const getStatusColor = (isActive: boolean) =>
|
76 |
+
isActive ? 'bg-positive' : 'bg-destructive'
|
77 |
+
|
78 |
+
const handleSave = async () => {
|
79 |
+
if (!isValidUrl(endpointValue)) {
|
80 |
+
toast.error('Please enter a valid URL')
|
81 |
+
return
|
82 |
+
}
|
83 |
+
const cleanEndpoint = endpointValue.replace(/\/$/, '').trim()
|
84 |
+
setSelectedEndpoint(cleanEndpoint)
|
85 |
+
setAgentId(null)
|
86 |
+
setSessionId(null)
|
87 |
+
setIsEditing(false)
|
88 |
+
setIsHovering(false)
|
89 |
+
setAgents([])
|
90 |
+
setSessionsData([])
|
91 |
+
setMessages([])
|
92 |
+
}
|
93 |
+
|
94 |
+
const handleCancel = () => {
|
95 |
+
setEndpointValue(selectedEndpoint)
|
96 |
+
setIsEditing(false)
|
97 |
+
setIsHovering(false)
|
98 |
+
}
|
99 |
+
|
100 |
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
101 |
+
if (e.key === 'Enter') {
|
102 |
+
handleSave()
|
103 |
+
} else if (e.key === 'Escape') {
|
104 |
+
handleCancel()
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
const handleRefresh = async () => {
|
109 |
+
setIsRotating(true)
|
110 |
+
await initializePlayground()
|
111 |
+
setTimeout(() => setIsRotating(false), 500)
|
112 |
+
}
|
113 |
+
|
114 |
+
return (
|
115 |
+
<div className="flex flex-col items-start gap-2">
|
116 |
+
<div className="text-xs font-medium uppercase text-primary">Endpoint</div>
|
117 |
+
{isEditing ? (
|
118 |
+
<div className="flex w-full items-center gap-1">
|
119 |
+
<input
|
120 |
+
type="text"
|
121 |
+
value={endpointValue}
|
122 |
+
onChange={(e) => setEndpointValue(e.target.value)}
|
123 |
+
onKeyDown={handleKeyDown}
|
124 |
+
className="flex h-9 w-full items-center text-ellipsis rounded-xl border border-primary/15 bg-accent p-3 text-xs font-medium text-muted"
|
125 |
+
autoFocus
|
126 |
+
/>
|
127 |
+
<Button
|
128 |
+
variant="ghost"
|
129 |
+
size="icon"
|
130 |
+
onClick={handleSave}
|
131 |
+
className="hover:cursor-pointer hover:bg-transparent"
|
132 |
+
>
|
133 |
+
<Icon type="save" size="xs" />
|
134 |
+
</Button>
|
135 |
+
</div>
|
136 |
+
) : (
|
137 |
+
<div className="flex w-full items-center gap-1">
|
138 |
+
<motion.div
|
139 |
+
className="relative flex h-9 w-full cursor-pointer items-center justify-between rounded-xl border border-primary/15 bg-accent p-3 uppercase"
|
140 |
+
onMouseEnter={() => setIsHovering(true)}
|
141 |
+
onMouseLeave={() => setIsHovering(false)}
|
142 |
+
onClick={() => setIsEditing(true)}
|
143 |
+
transition={{ type: 'spring', stiffness: 400, damping: 10 }}
|
144 |
+
>
|
145 |
+
<AnimatePresence mode="wait">
|
146 |
+
{isHovering ? (
|
147 |
+
<motion.div
|
148 |
+
key="endpoint-display-hover"
|
149 |
+
className="absolute inset-0 flex items-center justify-center"
|
150 |
+
initial={{ opacity: 0 }}
|
151 |
+
animate={{ opacity: 1 }}
|
152 |
+
exit={{ opacity: 0 }}
|
153 |
+
transition={{ duration: 0.2 }}
|
154 |
+
>
|
155 |
+
<p className="flex items-center gap-2 whitespace-nowrap text-xs font-medium text-primary">
|
156 |
+
<Icon type="edit" size="xxs" /> EDIT ENDPOINT
|
157 |
+
</p>
|
158 |
+
</motion.div>
|
159 |
+
) : (
|
160 |
+
<motion.div
|
161 |
+
key="endpoint-display"
|
162 |
+
className="absolute inset-0 flex items-center justify-between px-3"
|
163 |
+
initial={{ opacity: 0 }}
|
164 |
+
animate={{ opacity: 1 }}
|
165 |
+
exit={{ opacity: 0 }}
|
166 |
+
transition={{ duration: 0.2 }}
|
167 |
+
>
|
168 |
+
<p className="text-xs font-medium text-muted">
|
169 |
+
{isMounted
|
170 |
+
? truncateText(selectedEndpoint, 21) ||
|
171 |
+
ENDPOINT_PLACEHOLDER
|
172 |
+
: 'http://localhost:7777'}
|
173 |
+
</p>
|
174 |
+
<div
|
175 |
+
className={`size-2 shrink-0 rounded-full ${getStatusColor(isEndpointActive)}`}
|
176 |
+
/>
|
177 |
+
</motion.div>
|
178 |
+
)}
|
179 |
+
</AnimatePresence>
|
180 |
+
</motion.div>
|
181 |
+
<Button
|
182 |
+
variant="ghost"
|
183 |
+
size="icon"
|
184 |
+
onClick={handleRefresh}
|
185 |
+
className="hover:cursor-pointer hover:bg-transparent"
|
186 |
+
>
|
187 |
+
<motion.div
|
188 |
+
key={isRotating ? 'rotating' : 'idle'}
|
189 |
+
animate={{ rotate: isRotating ? 360 : 0 }}
|
190 |
+
transition={{ duration: 0.5, ease: 'easeInOut' }}
|
191 |
+
>
|
192 |
+
<Icon type="refresh" size="xs" />
|
193 |
+
</motion.div>
|
194 |
+
</Button>
|
195 |
+
</div>
|
196 |
+
)}
|
197 |
+
</div>
|
198 |
+
)
|
199 |
+
}
|
200 |
+
|
201 |
+
const Sidebar = () => {
|
202 |
+
const [isCollapsed, setIsCollapsed] = useState(false)
|
203 |
+
const { clearChat, focusChatInput, initializePlayground } = useChatActions()
|
204 |
+
const {
|
205 |
+
messages,
|
206 |
+
selectedEndpoint,
|
207 |
+
isEndpointActive,
|
208 |
+
selectedModel,
|
209 |
+
hydrated,
|
210 |
+
isEndpointLoading
|
211 |
+
} = usePlaygroundStore()
|
212 |
+
const [isMounted, setIsMounted] = useState(false)
|
213 |
+
const [agentId] = useQueryState('agent')
|
214 |
+
useEffect(() => {
|
215 |
+
setIsMounted(true)
|
216 |
+
if (hydrated) initializePlayground()
|
217 |
+
}, [selectedEndpoint, initializePlayground, hydrated])
|
218 |
+
const handleNewChat = () => {
|
219 |
+
clearChat()
|
220 |
+
focusChatInput()
|
221 |
+
}
|
222 |
+
return (
|
223 |
+
<motion.aside
|
224 |
+
className="relative flex h-screen shrink-0 grow-0 flex-col overflow-hidden px-2 py-3 font-dmmono"
|
225 |
+
initial={{ width: '16rem' }}
|
226 |
+
animate={{ width: isCollapsed ? '2.5rem' : '16rem' }}
|
227 |
+
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
|
228 |
+
>
|
229 |
+
<motion.button
|
230 |
+
onClick={() => setIsCollapsed(!isCollapsed)}
|
231 |
+
className="absolute right-2 top-2 z-10 p-1"
|
232 |
+
aria-label={isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
|
233 |
+
type="button"
|
234 |
+
whileTap={{ scale: 0.95 }}
|
235 |
+
>
|
236 |
+
<Icon
|
237 |
+
type="sheet"
|
238 |
+
size="xs"
|
239 |
+
className={`transform ${isCollapsed ? 'rotate-180' : 'rotate-0'}`}
|
240 |
+
/>
|
241 |
+
</motion.button>
|
242 |
+
<motion.div
|
243 |
+
className="w-60 space-y-5"
|
244 |
+
initial={{ opacity: 0, x: -20 }}
|
245 |
+
animate={{ opacity: isCollapsed ? 0 : 1, x: isCollapsed ? -20 : 0 }}
|
246 |
+
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
247 |
+
style={{
|
248 |
+
pointerEvents: isCollapsed ? 'none' : 'auto'
|
249 |
+
}}
|
250 |
+
>
|
251 |
+
<SidebarHeader />
|
252 |
+
<NewChatButton
|
253 |
+
disabled={messages.length === 0}
|
254 |
+
onClick={handleNewChat}
|
255 |
+
/>
|
256 |
+
{isMounted && (
|
257 |
+
<>
|
258 |
+
<Endpoint />
|
259 |
+
{isEndpointActive && (
|
260 |
+
<>
|
261 |
+
<motion.div
|
262 |
+
className="flex w-full flex-col items-start gap-2"
|
263 |
+
initial={{ opacity: 0 }}
|
264 |
+
animate={{ opacity: 1 }}
|
265 |
+
transition={{ duration: 0.5, ease: 'easeInOut' }}
|
266 |
+
>
|
267 |
+
<div className="text-xs font-medium uppercase text-primary">
|
268 |
+
Agent
|
269 |
+
</div>
|
270 |
+
{isEndpointLoading ? (
|
271 |
+
<div className="flex w-full flex-col gap-2">
|
272 |
+
{Array.from({ length: 2 }).map((_, index) => (
|
273 |
+
<Skeleton
|
274 |
+
key={index}
|
275 |
+
className="h-9 w-full rounded-xl"
|
276 |
+
/>
|
277 |
+
))}
|
278 |
+
</div>
|
279 |
+
) : (
|
280 |
+
<>
|
281 |
+
<AgentSelector />
|
282 |
+
{selectedModel && agentId && (
|
283 |
+
<ModelDisplay model={selectedModel} />
|
284 |
+
)}
|
285 |
+
</>
|
286 |
+
)}
|
287 |
+
</motion.div>
|
288 |
+
<Sessions />
|
289 |
+
</>
|
290 |
+
)}
|
291 |
+
</>
|
292 |
+
)}
|
293 |
+
</motion.div>
|
294 |
+
</motion.aside>
|
295 |
+
)
|
296 |
+
}
|
297 |
+
|
298 |
+
export default Sidebar
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
import Sidebar from './Sidebar'
|
2 |
+
|
3 |
+
export default Sidebar
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import * as React from 'react'
|
2 |
+
import { Slot } from '@radix-ui/react-slot'
|
3 |
+
import { cva, type VariantProps } from 'class-variance-authority'
|
4 |
+
|
5 |
+
import { cn } from '@/lib/utils'
|
6 |
+
|
7 |
+
const buttonVariants = cva(
|
8 |
+
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
|
9 |
+
{
|
10 |
+
variants: {
|
11 |
+
variant: {
|
12 |
+
default:
|
13 |
+
'bg-primary text-primary-foreground shadow hover:bg-primary/90',
|
14 |
+
destructive:
|
15 |
+
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
|
16 |
+
outline:
|
17 |
+
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
|
18 |
+
secondary:
|
19 |
+
'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
|
20 |
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
21 |
+
link: 'text-primary underline-offset-4 hover:underline'
|
22 |
+
},
|
23 |
+
size: {
|
24 |
+
default: 'h-9 px-4 py-2',
|
25 |
+
sm: 'h-8 rounded-md px-3 text-xs',
|
26 |
+
lg: 'h-10 rounded-md px-8',
|
27 |
+
icon: 'h-9 w-9'
|
28 |
+
}
|
29 |
+
},
|
30 |
+
defaultVariants: {
|
31 |
+
variant: 'default',
|
32 |
+
size: 'default'
|
33 |
+
}
|
34 |
+
}
|
35 |
+
)
|
36 |
+
|
37 |
+
export interface ButtonProps
|
38 |
+
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
39 |
+
VariantProps<typeof buttonVariants> {
|
40 |
+
asChild?: boolean
|
41 |
+
}
|
42 |
+
|
43 |
+
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
44 |
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
45 |
+
const Comp = asChild ? Slot : 'button'
|
46 |
+
return (
|
47 |
+
<Comp
|
48 |
+
className={cn(buttonVariants({ variant, size, className }))}
|
49 |
+
ref={ref}
|
50 |
+
{...props}
|
51 |
+
/>
|
52 |
+
)
|
53 |
+
}
|
54 |
+
)
|
55 |
+
Button.displayName = 'Button'
|
56 |
+
|
57 |
+
export { Button, buttonVariants }
|
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'use client'
|
2 |
+
|
3 |
+
import * as React from 'react'
|
4 |
+
import * as DialogPrimitive from '@radix-ui/react-dialog'
|
5 |
+
|
6 |
+
import { cn } from '@/lib/utils'
|
7 |
+
import Icon from './icon'
|
8 |
+
|
9 |
+
const Dialog = DialogPrimitive.Root
|
10 |
+
|
11 |
+
const DialogTrigger = DialogPrimitive.Trigger
|
12 |
+
|
13 |
+
const DialogPortal = DialogPrimitive.Portal
|
14 |
+
|
15 |
+
const DialogClose = DialogPrimitive.Close
|
16 |
+
|
17 |
+
const DialogOverlay = React.forwardRef<
|
18 |
+
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
19 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
20 |
+
>(({ className, ...props }, ref) => (
|
21 |
+
<DialogPrimitive.Overlay
|
22 |
+
ref={ref}
|
23 |
+
className={cn(
|
24 |
+
'fixed inset-0 z-50 bg-background/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
25 |
+
className
|
26 |
+
)}
|
27 |
+
{...props}
|
28 |
+
/>
|
29 |
+
))
|
30 |
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
|
31 |
+
|
32 |
+
const DialogContent = React.forwardRef<
|
33 |
+
React.ElementRef<typeof DialogPrimitive.Content>,
|
34 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
35 |
+
>(({ className, children, ...props }, ref) => (
|
36 |
+
<DialogPortal>
|
37 |
+
<DialogOverlay />
|
38 |
+
<DialogPrimitive.Content
|
39 |
+
ref={ref}
|
40 |
+
className={cn(
|
41 |
+
'fixed left-1/2 top-1/2 z-50 grid max-h-[623px] w-full max-w-[440px] -translate-x-1/2 -translate-y-1/2 gap-4 overflow-hidden rounded-[12px] border border-border bg-background/100 p-6 shadow-md duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]',
|
42 |
+
className
|
43 |
+
)}
|
44 |
+
{...props}
|
45 |
+
>
|
46 |
+
<div className="scrollbar-none overflow-auto">{children}</div>
|
47 |
+
<DialogPrimitive.Close className="focus:ring-ring data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent">
|
48 |
+
<Icon type="x" size="xs" />
|
49 |
+
<span className="sr-only">Close</span>
|
50 |
+
</DialogPrimitive.Close>
|
51 |
+
</DialogPrimitive.Content>
|
52 |
+
</DialogPortal>
|
53 |
+
))
|
54 |
+
DialogContent.displayName = DialogPrimitive.Content.displayName
|
55 |
+
|
56 |
+
const DialogHeader = ({
|
57 |
+
className,
|
58 |
+
...props
|
59 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
60 |
+
<div
|
61 |
+
className={cn(
|
62 |
+
'flex flex-col space-y-1.5 text-center sm:text-left',
|
63 |
+
className
|
64 |
+
)}
|
65 |
+
{...props}
|
66 |
+
/>
|
67 |
+
)
|
68 |
+
DialogHeader.displayName = 'DialogHeader'
|
69 |
+
|
70 |
+
const DialogFooter = ({
|
71 |
+
className,
|
72 |
+
...props
|
73 |
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
74 |
+
<div
|
75 |
+
className={cn(
|
76 |
+
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
77 |
+
className
|
78 |
+
)}
|
79 |
+
{...props}
|
80 |
+
/>
|
81 |
+
)
|
82 |
+
DialogFooter.displayName = 'DialogFooter'
|
83 |
+
|
84 |
+
const DialogTitle = React.forwardRef<
|
85 |
+
React.ElementRef<typeof DialogPrimitive.Title>,
|
86 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
87 |
+
>(({ className, ...props }, ref) => (
|
88 |
+
<DialogPrimitive.Title
|
89 |
+
ref={ref}
|
90 |
+
className={cn(
|
91 |
+
'text-lg font-semibold leading-none tracking-tight',
|
92 |
+
className
|
93 |
+
)}
|
94 |
+
{...props}
|
95 |
+
/>
|
96 |
+
))
|
97 |
+
DialogTitle.displayName = DialogPrimitive.Title.displayName
|
98 |
+
|
99 |
+
const DialogDescription = React.forwardRef<
|
100 |
+
React.ElementRef<typeof DialogPrimitive.Description>,
|
101 |
+
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
102 |
+
>(({ className, ...props }, ref) => (
|
103 |
+
<DialogPrimitive.Description
|
104 |
+
ref={ref}
|
105 |
+
className={cn('text-muted-foreground text-sm', className)}
|
106 |
+
{...props}
|
107 |
+
/>
|
108 |
+
))
|
109 |
+
DialogDescription.displayName = DialogPrimitive.Description.displayName
|
110 |
+
|
111 |
+
export {
|
112 |
+
Dialog,
|
113 |
+
DialogPortal,
|
114 |
+
DialogOverlay,
|
115 |
+
DialogTrigger,
|
116 |
+
DialogClose,
|
117 |
+
DialogContent,
|
118 |
+
DialogHeader,
|
119 |
+
DialogFooter,
|
120 |
+
DialogTitle,
|
121 |
+
DialogDescription
|
122 |
+
}
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { type FC } from 'react'
|
2 |
+
|
3 |
+
import { cn } from '@/lib/utils'
|
4 |
+
|
5 |
+
import { ICONS } from './constants'
|
6 |
+
import { type IconProps } from './types'
|
7 |
+
|
8 |
+
const Icon: FC<IconProps> = ({
|
9 |
+
type,
|
10 |
+
size = 'sm',
|
11 |
+
className,
|
12 |
+
color,
|
13 |
+
disabled = false
|
14 |
+
}) => {
|
15 |
+
const IconElement = ICONS[type]
|
16 |
+
|
17 |
+
return (
|
18 |
+
<IconElement
|
19 |
+
className={cn(
|
20 |
+
color && !disabled ? `text-${color}` : 'text-primary',
|
21 |
+
disabled && 'cursor-default text-muted/50',
|
22 |
+
className,
|
23 |
+
size === 'xxs' && 'size-3',
|
24 |
+
size === 'xs' && 'size-4',
|
25 |
+
size === 'sm' && 'size-6',
|
26 |
+
size === 'md' && 'size-[42px]',
|
27 |
+
size === 'lg' && 'size-7',
|
28 |
+
size === 'dot' && 'size-[5.07px]',
|
29 |
+
size === 'default' && ' '
|
30 |
+
)}
|
31 |
+
/>
|
32 |
+
)
|
33 |
+
}
|
34 |
+
|
35 |
+
export default Icon
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import {
|
2 |
+
MistralLogo,
|
3 |
+
OpenAILogo,
|
4 |
+
GeminiLogo,
|
5 |
+
AwsLogo,
|
6 |
+
AzureLogo,
|
7 |
+
AnthropicLogo,
|
8 |
+
GroqLogo,
|
9 |
+
FireworksLogo,
|
10 |
+
DeepseekLogo,
|
11 |
+
CohereLogo,
|
12 |
+
OllamaLogo,
|
13 |
+
XaiLogo,
|
14 |
+
AgnoIcon,
|
15 |
+
UserIcon,
|
16 |
+
AgentIcon,
|
17 |
+
SheetIcon,
|
18 |
+
NextjsTag,
|
19 |
+
ShadcnTag,
|
20 |
+
TailwindTag,
|
21 |
+
AgnoTag,
|
22 |
+
ReasoningIcon,
|
23 |
+
ReferencesIcon
|
24 |
+
} from './custom-icons'
|
25 |
+
import { IconTypeMap } from './types'
|
26 |
+
import {
|
27 |
+
RefreshCw,
|
28 |
+
Edit,
|
29 |
+
Save,
|
30 |
+
X,
|
31 |
+
ArrowDown,
|
32 |
+
SendIcon,
|
33 |
+
Download,
|
34 |
+
HammerIcon,
|
35 |
+
Check,
|
36 |
+
ChevronDown,
|
37 |
+
ChevronUp,
|
38 |
+
Trash
|
39 |
+
} from 'lucide-react'
|
40 |
+
|
41 |
+
import { PlusIcon } from '@radix-ui/react-icons'
|
42 |
+
|
43 |
+
export const ICONS: IconTypeMap = {
|
44 |
+
'open-ai': OpenAILogo,
|
45 |
+
mistral: MistralLogo,
|
46 |
+
gemini: GeminiLogo,
|
47 |
+
aws: AwsLogo,
|
48 |
+
azure: AzureLogo,
|
49 |
+
anthropic: AnthropicLogo,
|
50 |
+
groq: GroqLogo,
|
51 |
+
fireworks: FireworksLogo,
|
52 |
+
deepseek: DeepseekLogo,
|
53 |
+
cohere: CohereLogo,
|
54 |
+
ollama: OllamaLogo,
|
55 |
+
xai: XaiLogo,
|
56 |
+
agno: AgnoIcon,
|
57 |
+
user: UserIcon,
|
58 |
+
agent: AgentIcon,
|
59 |
+
sheet: SheetIcon,
|
60 |
+
nextjs: NextjsTag,
|
61 |
+
shadcn: ShadcnTag,
|
62 |
+
tailwind: TailwindTag,
|
63 |
+
reasoning: ReasoningIcon,
|
64 |
+
'agno-tag': AgnoTag,
|
65 |
+
refresh: RefreshCw,
|
66 |
+
edit: Edit,
|
67 |
+
save: Save,
|
68 |
+
x: X,
|
69 |
+
'arrow-down': ArrowDown,
|
70 |
+
send: SendIcon,
|
71 |
+
download: Download,
|
72 |
+
hammer: HammerIcon,
|
73 |
+
check: Check,
|
74 |
+
'chevron-down': ChevronDown,
|
75 |
+
'chevron-up': ChevronUp,
|
76 |
+
'plus-icon': PlusIcon,
|
77 |
+
references: ReferencesIcon,
|
78 |
+
trash: Trash
|
79 |
+
}
|
@@ -0,0 +1,983 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { type FC } from 'react'
|
2 |
+
|
3 |
+
export const AgnoIcon: FC = ({ ...props }) => {
|
4 |
+
return (
|
5 |
+
<svg
|
6 |
+
width="16"
|
7 |
+
height="16"
|
8 |
+
viewBox="0 0 16 16"
|
9 |
+
fill="none"
|
10 |
+
xmlns="http://www.w3.org/2000/svg"
|
11 |
+
{...props}
|
12 |
+
>
|
13 |
+
<g clipPath="url(#clip0_2815_4632)">
|
14 |
+
<path
|
15 |
+
fillRule="evenodd"
|
16 |
+
clipRule="evenodd"
|
17 |
+
d="M15.7469 1.84196C16.0957 2.52647 16.0957 3.42256 16.0957 5.21473V10.9752C16.0957 12.7674 16.0957 13.6634 15.7469 14.348C15.4401 14.9501 14.9506 15.4396 14.3485 15.7464C13.6639 16.0952 12.7679 16.0952 10.9757 16.0952H5.21522C3.42305 16.0952 2.52696 16.0952 1.84245 15.7464C1.24033 15.4396 0.750789 14.9501 0.443994 14.348C0.0952148 13.6634 0.0952148 12.7674 0.0952148 10.9752V5.21473C0.0952148 3.42256 0.0952148 2.52647 0.443994 1.84196C0.750789 1.23984 1.24033 0.7503 1.84245 0.443506C2.52696 0.0947266 3.42305 0.0947266 5.21521 0.0947266H10.9757C12.7678 0.0947266 13.6639 0.0947266 14.3485 0.443506C14.9506 0.7503 15.4401 1.23984 15.7469 1.84196ZM5.27398 3.77524H9.3046L12.594 12.0905H10.9168L8.32056 5.18973H5.27398V3.77524ZM2.99402 10.676H7.12113V12.0905H2.99402V10.676Z"
|
18 |
+
fill="#FF4017"
|
19 |
+
/>
|
20 |
+
</g>
|
21 |
+
<defs>
|
22 |
+
<clipPath id="clip0_2815_4632">
|
23 |
+
<rect width="16" height="16" fill="white" />
|
24 |
+
</clipPath>
|
25 |
+
</defs>
|
26 |
+
</svg>
|
27 |
+
)
|
28 |
+
}
|
29 |
+
|
30 |
+
export const UserIcon: FC = ({ ...props }) => {
|
31 |
+
return (
|
32 |
+
<svg
|
33 |
+
width="16"
|
34 |
+
height="16"
|
35 |
+
viewBox="0 0 16 16"
|
36 |
+
fill="none"
|
37 |
+
xmlns="http://www.w3.org/2000/svg"
|
38 |
+
{...props}
|
39 |
+
>
|
40 |
+
<rect width="16" height="16" rx="4" fill="#FAFAFA" />
|
41 |
+
<path
|
42 |
+
d="M11.5 12.5V11.5C11.5 10.9696 11.2893 10.4609 10.9142 10.0858C10.5391 9.71071 10.0304 9.5 9.5 9.5H6.5C5.96957 9.5 5.46086 9.71071 5.08579 10.0858C4.71071 10.4609 4.5 10.9696 4.5 11.5V12.5M10 5.5C10 6.60457 9.10457 7.5 8 7.5C6.89543 7.5 6 6.60457 6 5.5C6 4.39543 6.89543 3.5 8 3.5C9.10457 3.5 10 4.39543 10 5.5Z"
|
43 |
+
stroke="#18181B"
|
44 |
+
strokeWidth="0.75"
|
45 |
+
strokeLinecap="round"
|
46 |
+
strokeLinejoin="round"
|
47 |
+
/>
|
48 |
+
</svg>
|
49 |
+
)
|
50 |
+
}
|
51 |
+
|
52 |
+
export const AgentIcon: FC = ({ ...props }) => {
|
53 |
+
return (
|
54 |
+
<svg
|
55 |
+
width="16"
|
56 |
+
height="16"
|
57 |
+
viewBox="0 0 16 16"
|
58 |
+
fill="none"
|
59 |
+
xmlns="http://www.w3.org/2000/svg"
|
60 |
+
{...props}
|
61 |
+
>
|
62 |
+
<rect width="16" height="16" rx="4" fill="#FF4017" />
|
63 |
+
<path
|
64 |
+
fillRule="evenodd"
|
65 |
+
clipRule="evenodd"
|
66 |
+
d="M3.70226 6.05678C3.45553 6.06203 3.25125 5.86627 3.246 5.61953C3.22669 4.71202 3.45412 3.98771 4.05158 3.56286C4.62138 3.15769 5.40509 3.11931 6.26087 3.24653C6.50498 3.28281 6.67346 3.51012 6.63717 3.75423C6.60089 3.99834 6.37358 4.16682 6.12947 4.13053C5.33187 4.01197 4.8465 4.09424 4.5695 4.29121C4.32016 4.46851 4.12308 4.82784 4.13952 5.60052C4.14477 5.84726 3.949 6.05153 3.70226 6.05678Z"
|
67 |
+
fill="white"
|
68 |
+
/>
|
69 |
+
<path
|
70 |
+
fillRule="evenodd"
|
71 |
+
clipRule="evenodd"
|
72 |
+
d="M12.3156 6.05678C12.5623 6.06203 12.7666 5.86627 12.7718 5.61953C12.7911 4.71202 12.5637 3.98771 11.9662 3.56286C11.3964 3.15769 10.6127 3.11931 9.75695 3.24653C9.51284 3.28281 9.34436 3.51012 9.38065 3.75423C9.41694 3.99834 9.64424 4.16682 9.88836 4.13053C10.686 4.01197 11.1713 4.09424 11.4483 4.29121C11.6977 4.46851 11.8947 4.82784 11.8783 5.60052C11.8731 5.84726 12.0688 6.05153 12.3156 6.05678Z"
|
73 |
+
fill="white"
|
74 |
+
/>
|
75 |
+
<path
|
76 |
+
d="M7.25597 7.86712C7.25597 8.28683 6.91573 8.62707 6.49603 8.62707C6.07632 8.62707 5.73608 8.28683 5.73608 7.86712C5.73608 7.44742 6.07632 7.10718 6.49603 7.10718C6.91573 7.10718 7.25597 7.44742 7.25597 7.86712Z"
|
77 |
+
fill="white"
|
78 |
+
/>
|
79 |
+
<path
|
80 |
+
d="M10.409 7.86712C10.409 8.28683 10.0688 8.62707 9.6491 8.62707C9.2294 8.62707 8.88916 8.28683 8.88916 7.86712C8.88916 7.44742 9.2294 7.10718 9.6491 7.10718C10.0688 7.10718 10.409 7.44742 10.409 7.86712Z"
|
81 |
+
fill="white"
|
82 |
+
/>
|
83 |
+
<path
|
84 |
+
fillRule="evenodd"
|
85 |
+
clipRule="evenodd"
|
86 |
+
d="M12.3153 9.97544C12.5621 9.9702 12.7663 10.166 12.7716 10.4127C12.7909 11.3202 12.5635 12.0445 11.966 12.4694C11.3962 12.8745 10.6125 12.9129 9.7567 12.7857C9.51259 12.7494 9.34412 12.5221 9.38041 12.278C9.41669 12.0339 9.644 11.8654 9.88811 11.9017C10.6857 12.0203 11.1711 11.938 11.4481 11.741C11.6974 11.5637 11.8945 11.2044 11.8781 10.4317C11.8728 10.185 12.0686 9.98069 12.3153 9.97544Z"
|
87 |
+
fill="white"
|
88 |
+
/>
|
89 |
+
<path
|
90 |
+
fillRule="evenodd"
|
91 |
+
clipRule="evenodd"
|
92 |
+
d="M3.70251 9.97544C3.45577 9.9702 3.25149 10.166 3.24624 10.4127C3.22693 11.3202 3.45436 12.0445 4.05183 12.4694C4.62162 12.8745 5.40533 12.9129 6.26112 12.7857C6.50523 12.7494 6.6737 12.5221 6.63742 12.278C6.60113 12.0339 6.37382 11.8654 6.12971 11.9017C5.33212 12.0203 4.84675 11.938 4.56974 11.741C4.32041 11.5637 4.12332 11.2044 4.13976 10.4317C4.14501 10.185 3.94924 9.98069 3.70251 9.97544Z"
|
93 |
+
fill="white"
|
94 |
+
/>
|
95 |
+
</svg>
|
96 |
+
)
|
97 |
+
}
|
98 |
+
|
99 |
+
export const MistralLogo: FC = ({ ...props }) => (
|
100 |
+
<svg
|
101 |
+
width="22"
|
102 |
+
height="20"
|
103 |
+
viewBox="0 0 22 20"
|
104 |
+
fill="none"
|
105 |
+
xmlns="http://www.w3.org/2000/svg"
|
106 |
+
{...props}
|
107 |
+
>
|
108 |
+
<path
|
109 |
+
opacity="0.7"
|
110 |
+
d="M19.4156 0.571411H15.6753V4.31167H19.4156V0.571411Z"
|
111 |
+
fill="#FAFAFA"
|
112 |
+
/>
|
113 |
+
<path
|
114 |
+
d="M21.2857 0.571411H17.5454V4.31167H21.2857V0.571411Z"
|
115 |
+
fill="#FAFAFA"
|
116 |
+
/>
|
117 |
+
<path
|
118 |
+
d="M4.45462 0.571411H0.714355V4.31167H4.45462V0.571411Z"
|
119 |
+
fill="#FAFAFA"
|
120 |
+
fillOpacity="0.7"
|
121 |
+
/>
|
122 |
+
<path
|
123 |
+
d="M4.45462 4.31165H0.714355V8.05191H4.45462V4.31165Z"
|
124 |
+
fill="#FAFAFA"
|
125 |
+
fillOpacity="0.7"
|
126 |
+
/>
|
127 |
+
<path
|
128 |
+
d="M4.45462 8.05188H0.714355V11.7921H4.45462V8.05188Z"
|
129 |
+
fill="#FAFAFA"
|
130 |
+
fillOpacity="0.7"
|
131 |
+
/>
|
132 |
+
<path
|
133 |
+
d="M4.45462 11.7922H0.714355V15.5325H4.45462V11.7922Z"
|
134 |
+
fill="#FAFAFA"
|
135 |
+
fillOpacity="0.7"
|
136 |
+
/>
|
137 |
+
<path
|
138 |
+
d="M4.45462 15.5323H0.714355V19.2726H4.45462V15.5323Z"
|
139 |
+
fill="#FAFAFA"
|
140 |
+
fillOpacity="0.7"
|
141 |
+
/>
|
142 |
+
<path
|
143 |
+
d="M6.32473 0.571411H2.58447V4.31167H6.32473V0.571411Z"
|
144 |
+
fill="#FAFAFA"
|
145 |
+
/>
|
146 |
+
<path
|
147 |
+
d="M21.2857 4.31165H17.5454V8.05191H21.2857V4.31165Z"
|
148 |
+
fill="#FAFAFA"
|
149 |
+
/>
|
150 |
+
<path
|
151 |
+
d="M6.32473 4.31165H2.58447V8.05191H6.32473V4.31165Z"
|
152 |
+
fill="#FAFAFA"
|
153 |
+
/>
|
154 |
+
<path
|
155 |
+
opacity="0.7"
|
156 |
+
d="M15.6753 4.31165H11.9351V8.05191H15.6753V4.31165Z"
|
157 |
+
fill="#FAFAFA"
|
158 |
+
/>
|
159 |
+
<path
|
160 |
+
d="M17.5454 4.31165H13.8052V8.05191H17.5454V4.31165Z"
|
161 |
+
fill="#FAFAFA"
|
162 |
+
/>
|
163 |
+
<path d="M10.065 4.31165H6.32471V8.05191H10.065V4.31165Z" fill="#FAFAFA" />
|
164 |
+
<path
|
165 |
+
d="M13.8052 8.05188H10.0649V11.7921H13.8052V8.05188Z"
|
166 |
+
fill="#FAFAFA"
|
167 |
+
/>
|
168 |
+
<path
|
169 |
+
d="M17.5454 8.05188H13.8052V11.7921H17.5454V8.05188Z"
|
170 |
+
fill="#FAFAFA"
|
171 |
+
/>
|
172 |
+
<path d="M10.065 8.05188H6.32471V11.7921H10.065V8.05188Z" fill="#FAFAFA" />
|
173 |
+
<path
|
174 |
+
opacity="0.7"
|
175 |
+
d="M11.9351 11.7922H8.19482V15.5325H11.9351V11.7922Z"
|
176 |
+
fill="#FAFAFA"
|
177 |
+
/>
|
178 |
+
<path
|
179 |
+
d="M13.8052 11.7922H10.0649V15.5325H13.8052V11.7922Z"
|
180 |
+
fill="#FAFAFA"
|
181 |
+
/>
|
182 |
+
<path
|
183 |
+
d="M21.2857 8.05188H17.5454V11.7921H21.2857V8.05188Z"
|
184 |
+
fill="#FAFAFA"
|
185 |
+
/>
|
186 |
+
<path
|
187 |
+
d="M6.32473 8.05188H2.58447V11.7921H6.32473V8.05188Z"
|
188 |
+
fill="#FAFAFA"
|
189 |
+
/>
|
190 |
+
<path
|
191 |
+
opacity="0.7"
|
192 |
+
d="M19.4156 11.7922H15.6753V15.5325H19.4156V11.7922Z"
|
193 |
+
fill="#FAFAFA"
|
194 |
+
/>
|
195 |
+
<path
|
196 |
+
d="M21.2857 11.7922H17.5454V15.5325H21.2857V11.7922Z"
|
197 |
+
fill="#FAFAFA"
|
198 |
+
/>
|
199 |
+
<path
|
200 |
+
opacity="0.7"
|
201 |
+
d="M19.4156 15.5323H15.6753V19.2726H19.4156V15.5323Z"
|
202 |
+
fill="#FAFAFA"
|
203 |
+
/>
|
204 |
+
<path
|
205 |
+
d="M6.32473 11.7922H2.58447V15.5325H6.32473V11.7922Z"
|
206 |
+
fill="#FAFAFA"
|
207 |
+
/>
|
208 |
+
<path
|
209 |
+
d="M21.2857 15.5323H17.5454V19.2726H21.2857V15.5323Z"
|
210 |
+
fill="#FAFAFA"
|
211 |
+
/>
|
212 |
+
<path
|
213 |
+
d="M6.32473 15.5323H2.58447V19.2726H6.32473V15.5323Z"
|
214 |
+
fill="#FAFAFA"
|
215 |
+
/>
|
216 |
+
</svg>
|
217 |
+
)
|
218 |
+
|
219 |
+
export const GeminiLogo: FC = () => (
|
220 |
+
<svg
|
221 |
+
width="20"
|
222 |
+
height="20"
|
223 |
+
viewBox="0 0 20 20"
|
224 |
+
fill="none"
|
225 |
+
xmlns="http://www.w3.org/2000/svg"
|
226 |
+
>
|
227 |
+
<path
|
228 |
+
d="M20 10.02C17.4052 10.1792 14.9583 11.2818 13.12 13.12C11.2818 14.9583 10.1792 17.4052 10.02 20H9.98C9.82103 17.4051 8.71853 14.958 6.88025 13.1197C5.04198 11.2815 2.59485 10.179 0 10.02L0 9.98C2.59485 9.82103 5.04198 8.71853 6.88025 6.88025C8.71853 5.04198 9.82103 2.59485 9.98 0L10.02 0C10.1792 2.59476 11.2818 5.04173 13.12 6.87996C14.9583 8.71818 17.4052 9.82076 20 9.98V10.02Z"
|
229 |
+
fill="#FAFAFA"
|
230 |
+
/>
|
231 |
+
</svg>
|
232 |
+
)
|
233 |
+
|
234 |
+
export const AwsLogo: FC = ({ ...props }) => (
|
235 |
+
<svg
|
236 |
+
width="22"
|
237 |
+
height="14"
|
238 |
+
viewBox="0 0 22 14"
|
239 |
+
fill="none"
|
240 |
+
xmlns="http://www.w3.org/2000/svg"
|
241 |
+
{...props}
|
242 |
+
>
|
243 |
+
<g clipPath="url(#clip0_8005_20521)">
|
244 |
+
<path
|
245 |
+
d="M6.25274 4.80513C6.25274 5.07289 6.28169 5.28999 6.33235 5.4492C6.39024 5.60841 6.46261 5.7821 6.56393 5.97026C6.60011 6.02815 6.61459 6.08605 6.61459 6.1367C6.61459 6.20907 6.57117 6.28144 6.47709 6.35381L6.02117 6.65776C5.95603 6.70118 5.8909 6.72289 5.83301 6.72289C5.76064 6.72289 5.68827 6.6867 5.6159 6.62157C5.51459 6.51302 5.42774 6.39723 5.35538 6.28144C5.28301 6.15841 5.21064 6.02091 5.13103 5.85447C4.56656 6.52026 3.85735 6.85315 3.0034 6.85315C2.39551 6.85315 1.91064 6.67947 1.55603 6.3321C1.20143 5.98473 1.02051 5.52157 1.02051 4.94263C1.02051 4.32749 1.23761 3.82815 1.67906 3.45184C2.12051 3.07552 2.70669 2.88736 3.45209 2.88736C3.69814 2.88736 3.95143 2.90907 4.21919 2.94526C4.48695 2.98144 4.76196 3.03934 5.05143 3.10447V2.57618C5.05143 2.02618 4.93564 1.64263 4.7113 1.41828C4.47972 1.19394 4.08893 1.08539 3.53169 1.08539C3.2784 1.08539 3.01788 1.11434 2.75011 1.17947C2.48235 1.2446 2.22182 1.3242 1.96853 1.42552C1.85274 1.47618 1.7659 1.50513 1.71524 1.5196C1.66459 1.53407 1.6284 1.54131 1.59946 1.54131C1.49814 1.54131 1.44748 1.46894 1.44748 1.31697V0.962362C1.44748 0.846573 1.46196 0.759731 1.49814 0.709073C1.53432 0.658415 1.59946 0.607757 1.70077 0.557099C1.95406 0.426836 2.25801 0.318284 2.61261 0.231441C2.96722 0.137362 3.34353 0.0939415 3.74156 0.0939415C4.60274 0.0939415 5.23235 0.289336 5.63761 0.680126C6.03564 1.07091 6.23827 1.66434 6.23827 2.46039V4.80513H6.25274ZM3.31459 5.90513C3.5534 5.90513 3.79946 5.8617 4.05998 5.77486C4.32051 5.68802 4.55209 5.52881 4.74748 5.3117C4.86327 5.1742 4.95011 5.02223 4.99353 4.84855C5.03696 4.67486 5.0659 4.46499 5.0659 4.21894V3.91499C4.85603 3.86434 4.63169 3.82091 4.40011 3.79197C4.16853 3.76302 3.94419 3.74855 3.71985 3.74855C3.23498 3.74855 2.88038 3.84263 2.64156 4.03802C2.40274 4.23341 2.28696 4.50842 2.28696 4.87026C2.28696 5.21039 2.3738 5.46368 2.55472 5.63736C2.7284 5.81828 2.98169 5.90513 3.31459 5.90513ZM9.12577 6.6867C8.99551 6.6867 8.90867 6.66499 8.85077 6.61434C8.79288 6.57091 8.74222 6.4696 8.6988 6.3321L6.99814 0.73802C6.95472 0.593283 6.93301 0.499205 6.93301 0.448547C6.93301 0.332757 6.9909 0.267626 7.10669 0.267626H7.8159C7.9534 0.267626 8.04748 0.289336 8.09814 0.339994C8.15603 0.383415 8.19946 0.484731 8.24288 0.622231L9.45867 5.41302L10.5876 0.622231C10.6238 0.477494 10.6672 0.383415 10.7251 0.339994C10.783 0.296573 10.8843 0.267626 11.0146 0.267626H11.5935C11.731 0.267626 11.8251 0.289336 11.883 0.339994C11.9409 0.383415 11.9916 0.484731 12.0205 0.622231L13.1639 5.47091L14.4159 0.622231C14.4593 0.477494 14.51 0.383415 14.5606 0.339994C14.6185 0.296573 14.7126 0.267626 14.8429 0.267626H15.5159C15.6317 0.267626 15.6968 0.32552 15.6968 0.448547C15.6968 0.484731 15.6896 0.520915 15.6823 0.564336C15.6751 0.607757 15.6606 0.665652 15.6317 0.745257L13.8876 6.33934C13.8442 6.48407 13.7935 6.57815 13.7356 6.62157C13.6777 6.66499 13.5837 6.69394 13.4606 6.69394H12.8383C12.7008 6.69394 12.6067 6.67223 12.5488 6.62157C12.4909 6.57091 12.4402 6.47684 12.4113 6.3321L11.2896 1.66434L10.1751 6.32486C10.1389 6.4696 10.0955 6.56368 10.0376 6.61434C9.97972 6.66499 9.8784 6.6867 9.74814 6.6867H9.12577ZM18.4251 6.8821C18.0488 6.8821 17.6725 6.83868 17.3106 6.75184C16.9488 6.66499 16.6666 6.57091 16.4784 6.46236C16.3626 6.39723 16.283 6.32486 16.2541 6.25973C16.2251 6.1946 16.2106 6.12223 16.2106 6.0571V5.68802C16.2106 5.53605 16.2685 5.46368 16.3771 5.46368C16.4205 5.46368 16.4639 5.47091 16.5073 5.48539C16.5508 5.49986 16.6159 5.52881 16.6883 5.55776C16.9343 5.66631 17.2021 5.75315 17.4843 5.81105C17.7738 5.86894 18.056 5.89789 18.3455 5.89789C18.8014 5.89789 19.156 5.81828 19.4021 5.65907C19.6481 5.49986 19.7784 5.26828 19.7784 4.97157C19.7784 4.76894 19.7133 4.60249 19.583 4.46499C19.4527 4.32749 19.2067 4.20447 18.8521 4.08868L17.8027 3.76302C17.2745 3.59657 16.8837 3.35052 16.6448 3.02486C16.406 2.70644 16.283 2.35184 16.283 1.97552C16.283 1.67157 16.3481 1.40381 16.4784 1.17223C16.6087 0.940652 16.7823 0.73802 16.9995 0.57881C17.2166 0.412362 17.4626 0.289336 17.7521 0.202494C18.0416 0.115652 18.3455 0.0794678 18.6639 0.0794678C18.8231 0.0794678 18.9896 0.0867046 19.1488 0.108415C19.3152 0.130126 19.4672 0.159073 19.6192 0.18802C19.7639 0.224205 19.9014 0.260389 20.0317 0.30381C20.162 0.347231 20.2633 0.390652 20.3356 0.434073C20.437 0.491968 20.5093 0.549862 20.5527 0.614994C20.5962 0.672889 20.6179 0.752494 20.6179 0.85381V1.19394C20.6179 1.34591 20.56 1.42552 20.4514 1.42552C20.3935 1.42552 20.2995 1.39657 20.1764 1.33868C19.7639 1.15052 19.3008 1.05644 18.787 1.05644C18.3745 1.05644 18.0488 1.12157 17.8245 1.25907C17.6001 1.39657 17.4843 1.60644 17.4843 1.90315C17.4843 2.10578 17.5567 2.27947 17.7014 2.41697C17.8462 2.55447 18.1139 2.69197 18.4975 2.81499L19.5251 3.14065C20.0462 3.3071 20.4225 3.53868 20.6468 3.83539C20.8712 4.1321 20.9797 4.47223 20.9797 4.84855C20.9797 5.15973 20.9146 5.44197 20.7916 5.68802C20.6613 5.93407 20.4876 6.15118 20.2633 6.32486C20.0389 6.50578 19.7712 6.63605 19.46 6.73012C19.1343 6.83144 18.7942 6.8821 18.4251 6.8821Z"
|
246 |
+
fill="#FAFAFA"
|
247 |
+
/>
|
248 |
+
<path
|
249 |
+
fillRule="evenodd"
|
250 |
+
clipRule="evenodd"
|
251 |
+
d="M19.7927 10.3991C17.4117 12.1577 13.9525 13.0912 10.9782 13.0912C6.80976 13.0912 3.05384 11.5498 0.217001 8.98792C-0.00734065 8.78529 0.195291 8.51029 0.463054 8.6695C3.53147 10.4498 7.31634 11.5281 11.2315 11.5281C13.8729 11.5281 16.7749 10.9781 19.4453 9.8491C19.8433 9.66818 20.1834 10.1096 19.7927 10.3991Z"
|
252 |
+
fill="#FAFAFA"
|
253 |
+
/>
|
254 |
+
<path
|
255 |
+
fillRule="evenodd"
|
256 |
+
clipRule="evenodd"
|
257 |
+
d="M20.7838 9.27038C20.4799 8.87959 18.772 9.08222 17.9976 9.1763C17.7661 9.20525 17.7299 9.00262 17.9397 8.85064C19.3003 7.89538 21.5364 8.17038 21.797 8.4888C22.0575 8.81446 21.7246 11.0506 20.4509 12.1217C20.2555 12.2881 20.0674 12.2013 20.1542 11.9842C20.4437 11.2677 21.0878 9.65393 20.7838 9.27038Z"
|
258 |
+
fill="#FAFAFA"
|
259 |
+
/>
|
260 |
+
</g>
|
261 |
+
<defs>
|
262 |
+
<clipPath id="clip0_8005_20521">
|
263 |
+
<rect width="22" height="13.1711" fill="white" />
|
264 |
+
</clipPath>
|
265 |
+
</defs>
|
266 |
+
</svg>
|
267 |
+
)
|
268 |
+
|
269 |
+
export const AnthropicLogo: FC = ({ ...props }) => (
|
270 |
+
<svg
|
271 |
+
width="21"
|
272 |
+
height="15"
|
273 |
+
viewBox="0 0 21 15"
|
274 |
+
fill="none"
|
275 |
+
xmlns="http://www.w3.org/2000/svg"
|
276 |
+
{...props}
|
277 |
+
>
|
278 |
+
<g clipPath="url(#clip0_8005_20528)">
|
279 |
+
<path
|
280 |
+
d="M14.6751 0H11.5612L17.2398 14.3478H20.3537L14.6751 0ZM5.67858 0L0 14.3478H3.17534L4.33662 11.3347H10.2775L11.4388 14.3478H14.6141L8.93553 0H5.67858ZM5.36383 8.67009L7.30705 3.62775L9.25028 8.67009H5.36383Z"
|
281 |
+
fill="#FAFAFA"
|
282 |
+
/>
|
283 |
+
</g>
|
284 |
+
<defs>
|
285 |
+
<clipPath id="clip0_8005_20528">
|
286 |
+
<rect width="20.6249" height="14.3478" fill="white" />
|
287 |
+
</clipPath>
|
288 |
+
</defs>
|
289 |
+
</svg>
|
290 |
+
)
|
291 |
+
|
292 |
+
export const OllamaLogo: FC = ({ ...props }) => (
|
293 |
+
<svg
|
294 |
+
width="16"
|
295 |
+
height="22"
|
296 |
+
viewBox="0 0 16 22"
|
297 |
+
fill="none"
|
298 |
+
xmlns="http://www.w3.org/2000/svg"
|
299 |
+
{...props}
|
300 |
+
>
|
301 |
+
<path
|
302 |
+
d="M10.1044 9.89569C10.6837 10.3223 11.1157 10.8046 11.2561 11.5301C11.3088 12.2593 11.2197 12.6993 10.7819 13.2915C10.2833 13.8614 9.66528 14.2002 8.909 14.2593C8.67758 14.2659 8.44727 14.2686 8.21583 14.2665C8.07221 14.2654 7.92873 14.2665 7.78512 14.2678C6.90745 14.2692 6.21469 14.1208 5.56691 13.5025C5.13374 13.0334 4.90487 12.5888 4.91749 11.9451C4.91818 11.8916 4.91887 11.8381 4.91959 11.783C4.93565 11.3405 5.02996 11.0106 5.29433 10.6494C5.32796 10.6018 5.36158 10.5542 5.39622 10.5052C5.702 10.1169 6.08253 9.86684 6.51379 9.63317C6.56698 9.60356 6.62016 9.57396 6.67496 9.54345C7.73031 9.06067 9.14792 9.29968 10.1044 9.89569ZM5.97181 11.0559C5.73111 11.3772 5.64825 11.6993 5.66615 12.0999C5.74893 12.5188 5.99409 12.8873 6.32749 13.1518C6.8829 13.4828 7.46794 13.5287 8.10163 13.5244C8.20885 13.5265 8.20885 13.5265 8.31824 13.5285C9.02425 13.5281 9.61763 13.365 10.1319 12.8655C10.4247 12.5512 10.4727 12.3291 10.4583 11.907C10.4146 11.4051 10.2916 11.0688 9.89933 10.7362C8.65785 9.78646 7.01637 9.86496 5.97181 11.0559Z"
|
303 |
+
fill="#FAFAFA"
|
304 |
+
/>
|
305 |
+
<path
|
306 |
+
fillRule="evenodd"
|
307 |
+
clipRule="evenodd"
|
308 |
+
d="M5.75158 2.91052C5.53174 2.0987 5.19725 1.27988 4.45008 0.82542C4.05056 0.669299 3.56483 0.665313 3.1941 0.893697C2.63015 1.3091 2.24679 2.08179 2.13263 2.76549L2.11014 2.92613C1.9698 3.69749 1.93035 4.46221 1.98516 5.24411L1.9974 5.39046C2.00502 5.48223 2.01295 5.57397 2.02122 5.66568C2.02479 5.69913 2.02905 5.73135 2.03318 5.76259C2.05519 5.92915 2.07352 6.06782 1.96459 6.2164C1.47913 6.59227 1.04256 7.12358 0.774236 7.67271L0.687434 7.87172C0.580734 8.10782 0.483549 8.34303 0.410356 8.59154C0.179013 9.54096 0.260673 10.6965 0.729776 11.5555C0.811546 11.7038 0.88611 11.8508 0.958425 12.0043C0.958425 12.2854 0.913432 12.3987 0.797524 12.6479C0.510049 13.2599 0.467807 13.9115 0.468974 14.579L0.471488 14.8074C0.471936 15.5967 0.528824 16.3265 0.899146 17.0388C1.03892 17.2886 1.1281 17.5052 1.0484 17.7902C0.557911 18.9435 0.551088 20.0587 0.687434 21.2858H1.97464V21.0148C1.71025 20.139 1.7711 19.1799 2.14639 18.3443L2.16683 18.3023C2.26477 18.1013 2.36207 17.9015 2.44888 17.6952C2.49898 17.4454 2.50268 17.2438 2.36843 17.0177C1.81616 16.4083 1.69579 15.7284 1.68018 14.9261L1.67825 14.71C1.66941 14.0734 1.72655 13.4939 2.03048 12.9245C2.04506 12.9028 2.05964 12.8813 2.07412 12.86C2.25028 12.6002 2.41333 12.3598 2.42347 12.034C2.39679 11.8872 2.38692 11.8329 2.36035 11.7887C2.34476 11.7627 2.32342 11.7402 2.28956 11.7045C1.84561 11.2805 1.59179 10.6432 1.5491 10.0426C1.51683 9.0468 1.7191 8.19467 2.39859 7.42818C3.15842 6.70012 3.8477 6.53584 4.86954 6.52391C4.96598 6.5241 5.06251 6.52249 5.15879 6.51676C5.18883 6.48672 5.20555 6.47 5.22023 6.45165C5.23866 6.42862 5.25388 6.40302 5.2882 6.34528C5.57717 5.85158 5.92486 5.40941 6.39519 5.07712C7.13017 4.62811 7.82723 4.41943 8.68961 4.57854C9.48851 4.83711 10.1926 5.25935 10.6464 5.97478C10.7408 6.17636 10.8301 6.35502 10.9851 6.51676C11.1486 6.56835 11.2843 6.57262 11.4554 6.5712L11.6329 6.56334C12.3759 6.56529 12.9767 6.70263 13.5293 7.23129L13.6273 7.32974C14.1182 7.76083 14.4817 8.37325 14.5757 9.02343C14.6238 9.87283 14.6564 10.7119 14.1137 11.42C13.9911 11.5669 13.8716 11.7115 13.7628 11.8688C13.7004 12.1932 13.7861 12.3474 13.966 12.6141C14.2804 13.0791 14.416 13.5478 14.4926 14.1032C14.5934 14.9993 14.5723 16.0844 13.9927 16.8163C13.8845 16.947 13.7861 17.0777 13.695 17.2209C13.6415 17.4446 13.6647 17.5634 13.7625 17.7698C14.2755 18.751 14.4241 19.7087 14.3047 20.8116L14.1692 21.2858H15.4565C15.6092 20.2164 15.6246 19.1262 15.2532 18.1016L15.1828 17.9169L15.1219 17.7544L15.0651 17.6226C15.0519 17.5586 15.0448 17.5235 15.0501 17.4905C15.0566 17.4505 15.0814 17.4135 15.1362 17.3318C15.1943 17.2431 15.2236 17.1984 15.2492 17.1518C15.2752 17.1045 15.2975 17.0552 15.3424 16.956C15.8611 15.6438 15.9282 14.0744 15.4183 12.7453L15.4061 12.716C15.3337 12.5424 15.2622 12.3706 15.204 12.1914C15.1892 12.1328 15.1811 12.1008 15.1856 12.0707C15.191 12.0347 15.2144 12.0013 15.2659 11.9281C15.8024 11.0772 15.9343 10.071 15.8439 9.08695C15.7088 8.08931 15.2318 7.07554 14.436 6.44902L14.2388 6.31352C14.1611 6.17326 14.122 6.10274 14.1061 6.02733C14.0901 5.95108 14.098 5.86984 14.1137 5.70644C14.1601 5.31445 14.1798 4.93296 14.1818 4.53832L14.1819 4.30649C14.1909 3.47534 14.106 2.75683 13.7903 1.98322C13.5457 1.44714 13.2471 0.983476 12.6788 0.758202C12.3661 0.718969 12.019 0.681597 11.7303 0.825949C11.1198 1.28795 10.7878 1.80066 10.5656 2.52997L10.5109 2.72289C10.4035 3.08351 10.3504 3.43907 10.3177 3.8132L10.3076 3.94235C9.93657 3.75103 9.55797 3.57883 9.16623 3.43424C8.0722 3.07745 7.00024 3.3833 6.00272 3.86057L5.83627 3.94235C5.84947 3.58589 5.82871 3.25921 5.75158 2.91052ZM3.80383 1.90991H4.00708C4.33115 2.30657 4.49953 2.77324 4.61681 3.26487L4.65888 3.41757C4.7506 3.7914 4.76816 4.16041 4.77347 4.54361L4.77709 4.69513C4.77672 4.98914 4.75524 5.15329 4.54906 5.36505C4.47886 5.38562 4.44208 5.3964 4.4046 5.40343C4.36336 5.41118 4.32128 5.41439 4.2329 5.42115L4.23281 5.42116L4.04955 5.43703L3.85888 5.44974L3.66582 5.46562C3.50863 5.47838 3.35145 5.48998 3.1941 5.50055C3.18729 5.20917 3.18243 4.91784 3.17922 4.62641C3.17787 4.52774 3.17604 4.42906 3.17366 4.33041C3.15372 3.48063 3.19343 2.56727 3.80383 1.90991ZM12.2046 1.90991H12.4078C13.1548 2.82926 13.0975 4.17989 13.0175 5.2973L12.9498 5.50055C12.7393 5.48564 12.5291 5.46795 12.3189 5.44974L12.138 5.43703C11.8611 5.41177 11.7625 5.40277 11.6777 5.36372C11.6308 5.34211 11.5881 5.3113 11.5218 5.26343C11.4243 4.99914 11.4264 4.74704 11.4297 4.46739L11.4311 4.28537C11.4507 3.46741 11.6017 2.51281 12.2046 1.90991Z"
|
309 |
+
fill="#FAFAFA"
|
310 |
+
/>
|
311 |
+
<path
|
312 |
+
d="M12.1243 9.46396C12.3546 9.51627 12.5027 9.61403 12.6787 9.76856C12.8518 10.0522 12.8623 10.3252 12.8142 10.6493C12.6748 10.8753 12.5609 10.9763 12.34 11.1235C12.1058 11.1596 11.9417 11.1692 11.7342 11.0444C11.4216 10.7905 11.2914 10.5816 11.2222 10.1835C11.2644 9.91975 11.3519 9.78311 11.5331 9.58993C11.7296 9.44969 11.8881 9.44444 12.1243 9.46396Z"
|
313 |
+
fill="#FAFAFA"
|
314 |
+
/>
|
315 |
+
<path
|
316 |
+
d="M4.4135 9.49766C4.78611 9.7009 4.78611 9.7009 4.88773 9.90415C4.92462 10.3394 4.87446 10.5651 4.61674 10.9204C4.42819 11.0742 4.31585 11.1189 4.07476 11.149C3.76776 11.1106 3.60323 11.0078 3.40999 10.7679C3.30581 10.5267 3.2975 10.3683 3.32953 10.1074C3.58695 9.62933 3.85303 9.39761 4.4135 9.49766Z"
|
317 |
+
fill="#FAFAFA"
|
318 |
+
/>
|
319 |
+
<path
|
320 |
+
d="M7.65258 11.1829C7.83055 11.1899 7.96945 11.2151 8.13952 11.2592C8.16188 11.2368 8.18424 11.2144 8.20727 11.1914C8.40628 11.1787 8.40628 11.1787 8.61376 11.1914C8.74925 11.3269 8.74925 11.3269 8.77042 11.492C8.74925 11.6656 8.74925 11.6656 8.6561 11.7884C8.54601 11.8689 8.54601 11.8689 8.41051 11.8689C8.41209 11.9162 8.41366 11.9636 8.41528 12.0123C8.41711 12.1048 8.41711 12.1048 8.41898 12.1992C8.42055 12.2605 8.42213 12.3218 8.42375 12.3849C8.41051 12.5464 8.41051 12.5464 8.27502 12.6819C8.07177 12.6988 8.07177 12.6988 7.86853 12.6819C7.70573 12.5191 7.71722 12.4721 7.70763 12.25C7.6828 11.9563 7.60997 11.8674 7.3943 11.6656C7.37313 11.4497 7.37313 11.4497 7.3943 11.2592C7.46204 11.1914 7.46204 11.1914 7.65258 11.1829Z"
|
321 |
+
fill="#FAFAFA"
|
322 |
+
/>
|
323 |
+
</svg>
|
324 |
+
)
|
325 |
+
|
326 |
+
export const GroqLogo: FC = ({ ...props }) => (
|
327 |
+
<svg
|
328 |
+
width="15"
|
329 |
+
height="22"
|
330 |
+
viewBox="0 0 15 22"
|
331 |
+
fill="none"
|
332 |
+
xmlns="http://www.w3.org/2000/svg"
|
333 |
+
{...props}
|
334 |
+
>
|
335 |
+
<path
|
336 |
+
d="M7.12321 0.753296C3.27412 0.753296 0.143066 3.91255 0.143066 7.79593C0.143066 11.6793 3.27412 14.839 7.12321 14.839H9.41876V12.1977H7.12321C4.71767 12.1977 2.76072 10.2231 2.76072 7.79593C2.76072 5.36872 4.71767 3.39413 7.12321 3.39413C9.52875 3.39413 11.4959 5.36872 11.4959 7.79593V14.2821C11.4959 16.6934 9.54996 18.6573 7.16603 18.6827C6.02532 18.6732 4.9345 18.2107 4.13004 17.3946L2.27914 19.2622C3.56204 20.5634 5.3002 21.3037 7.11889 21.3235V21.3247C7.1346 21.3247 7.15031 21.3247 7.16563 21.3247H7.21473V21.3235C11.0088 21.2716 14.081 18.1508 14.0986 14.3138L14.101 7.62312C14.0099 3.81981 10.9146 0.753296 7.12321 0.753296Z"
|
337 |
+
fill="#FAFAFA"
|
338 |
+
/>
|
339 |
+
</svg>
|
340 |
+
)
|
341 |
+
export const DeepseekLogo: FC = ({ ...props }) => (
|
342 |
+
<svg
|
343 |
+
width="20"
|
344 |
+
height="15"
|
345 |
+
viewBox="0 0 20 15"
|
346 |
+
fill="none"
|
347 |
+
xmlns="http://www.w3.org/2000/svg"
|
348 |
+
{...props}
|
349 |
+
>
|
350 |
+
<path
|
351 |
+
d="M19.7848 1.26275C19.5756 1.16126 19.486 1.36425 19.3565 1.46575C19.3166 1.4962 19.2768 1.54695 19.2469 1.5774C18.9381 1.91234 18.5795 2.13564 18.1013 2.10519C17.414 2.06459 16.8263 2.28789 16.2983 2.82583C16.1887 2.15594 15.8202 1.7601 15.2623 1.50635C14.9734 1.3744 14.6746 1.24245 14.4654 0.958259C14.326 0.755262 14.2861 0.521816 14.2164 0.29852C14.1666 0.166572 14.1267 0.0244731 13.9673 0.00417344C13.798 -0.0262761 13.7382 0.115822 13.6685 0.23762C13.4095 0.724812 13.3099 1.26275 13.3199 1.80069C13.3398 3.01867 13.8478 3.99306 14.8539 4.68325C14.9734 4.76445 14.9934 4.84565 14.9635 4.95729C14.8938 5.19074 14.8141 5.42419 14.7443 5.66778C14.6945 5.82003 14.6248 5.85048 14.4654 5.78958C13.9175 5.55614 13.4394 5.21104 13.021 4.78475C12.3038 4.08441 11.6563 3.30287 10.8594 2.69388C10.6701 2.55178 10.4809 2.41983 10.2816 2.28789C9.46481 1.4759 10.3912 0.806011 10.6004 0.724812C10.8196 0.643614 10.6801 0.359418 9.95291 0.359418C9.22573 0.359418 8.55832 0.613163 7.7116 0.937958C7.58211 0.988707 7.46257 1.01916 7.32311 1.04961C6.55609 0.897359 5.75917 0.86691 4.92242 0.968408C3.34852 1.15111 2.09339 1.90219 1.17694 3.20137C0.0712291 4.7543 -0.197728 6.52037 0.130997 8.36764C0.469684 10.3063 1.43594 11.9201 2.93014 13.1685C4.47416 14.4677 6.25724 15.1071 8.28936 14.9853C9.52458 14.9143 10.8992 14.7417 12.4532 13.402C12.8417 13.605 13.2601 13.676 13.9375 13.7369C14.4654 13.7877 14.9635 13.7065 15.3619 13.6253C15.9696 13.4933 15.9297 12.9148 15.7106 12.8133C13.9175 11.9607 14.306 12.3058 13.9474 12.0216C14.8639 10.9254 16.2385 9.77847 16.7765 6.06363C16.8163 5.76928 16.7765 5.58658 16.7765 5.34299C16.7765 5.20089 16.8063 5.13999 16.9657 5.12984C17.414 5.07909 17.8523 4.94715 18.2507 4.72385C19.4162 4.07426 19.8844 3.00853 19.994 1.72965C20.0139 1.5368 19.994 1.3338 19.7848 1.2323V1.26275ZM9.64411 12.7524C7.90087 11.3517 7.06412 10.8949 6.70551 10.9152C6.37678 10.9355 6.43655 11.3111 6.50628 11.5648C6.57601 11.8084 6.67562 11.981 6.81508 12.1941C6.90473 12.3362 6.97446 12.5494 6.72543 12.7016C6.16759 13.0569 5.19138 12.5798 5.14157 12.5595C4.00597 11.8795 3.05964 10.9761 2.39223 9.74802C1.74474 8.56049 1.37617 7.29176 1.30644 5.94183C1.28652 5.61703 1.38613 5.49524 1.7049 5.43434C2.12327 5.35314 2.56157 5.33284 2.97995 5.40389C4.75308 5.66778 6.2672 6.47977 7.5323 7.75865C8.25948 8.48944 8.80736 9.36232 9.36519 10.2149C9.96288 11.1182 10.6104 11.981 11.4272 12.6915C11.7161 12.9351 11.9452 13.1279 12.1743 13.27C11.5069 13.3512 10.3912 13.3614 9.62419 12.7524H9.64411ZM10.4809 7.28161C10.4809 7.12936 10.5904 7.01771 10.7399 7.01771C10.8893 7.01771 10.7996 7.01771 10.8295 7.03801C10.8594 7.04816 10.8992 7.06846 10.9192 7.09891C10.969 7.14966 10.9889 7.21056 10.9889 7.28161C10.9889 7.4237 10.8793 7.5455 10.7299 7.5455C10.5805 7.5455 10.4809 7.43385 10.4809 7.28161ZM13.0708 8.63154C12.9015 8.70258 12.7421 8.76348 12.5827 8.76348C12.3337 8.77363 12.0647 8.67213 11.9153 8.55033C11.6862 8.35749 11.5268 8.24584 11.4571 7.90075C11.4272 7.75865 11.4471 7.53535 11.467 7.4034C11.5268 7.12936 11.467 6.94666 11.2678 6.78426C11.1084 6.65232 10.9092 6.61172 10.6901 6.61172C10.4709 6.61172 10.5307 6.58127 10.4809 6.55082C10.3912 6.50007 10.3115 6.38842 10.3912 6.24632C10.4111 6.19558 10.5207 6.08393 10.5506 6.07378C10.8494 5.90123 11.1881 5.95198 11.5069 6.08393C11.7958 6.20572 12.0249 6.42902 12.3436 6.75382C12.6724 7.13951 12.7321 7.24101 12.9114 7.53535C13.0609 7.75865 13.1904 7.99209 13.28 8.25599C13.3398 8.41839 13.2601 8.56048 13.0708 8.64168V8.63154Z"
|
352 |
+
fill="#FAFAFA"
|
353 |
+
/>
|
354 |
+
</svg>
|
355 |
+
)
|
356 |
+
|
357 |
+
export const CohereLogo: FC = ({ ...props }) => (
|
358 |
+
<svg
|
359 |
+
width="18"
|
360 |
+
height="18"
|
361 |
+
viewBox="0 0 18 18"
|
362 |
+
fill="none"
|
363 |
+
xmlns="http://www.w3.org/2000/svg"
|
364 |
+
{...props}
|
365 |
+
>
|
366 |
+
<path
|
367 |
+
fillRule="evenodd"
|
368 |
+
clipRule="evenodd"
|
369 |
+
d="M5.8317 10.7281C6.31172 10.7281 7.27175 10.7041 8.61579 10.1521C10.1758 9.50407 13.2479 8.35203 15.48 7.15199C17.0401 6.31196 17.7121 5.20793 17.7121 3.71988C17.7121 1.67981 16.056 -0.000244141 13.992 -0.000244141H5.35169C2.39959 -0.000244141 -0.000488281 2.39983 -0.000488281 5.35193C-0.000488281 8.30403 2.25559 10.7281 5.8317 10.7281Z"
|
370 |
+
fill="#FAFAFA"
|
371 |
+
/>
|
372 |
+
<path
|
373 |
+
fillRule="evenodd"
|
374 |
+
clipRule="evenodd"
|
375 |
+
d="M7.29541 14.4C7.29541 12.9599 8.15944 11.6399 9.50348 11.0879L12.2156 9.95983C14.9757 8.83179 17.9998 10.8479 17.9998 13.824C17.9998 16.128 16.1277 18.0001 13.8236 18.0001H10.8715C8.90346 18.0001 7.29541 16.392 7.29541 14.4Z"
|
376 |
+
fill="#FAFAFA"
|
377 |
+
/>
|
378 |
+
<path
|
379 |
+
d="M3.09561 11.424C1.39156 11.424 -0.000488281 12.816 -0.000488281 14.5201V14.9281C-0.000488281 16.6081 1.39156 18.0002 3.09561 18.0002C4.79967 18.0002 6.19171 16.6081 6.19171 14.9041V14.4961C6.16771 12.816 4.79967 11.424 3.09561 11.424Z"
|
380 |
+
fill="#FAFAFA"
|
381 |
+
/>
|
382 |
+
</svg>
|
383 |
+
)
|
384 |
+
export const FireworksLogo: FC = ({ ...props }) => (
|
385 |
+
<svg
|
386 |
+
width="22"
|
387 |
+
height="11"
|
388 |
+
viewBox="0 0 22 11"
|
389 |
+
fill="none"
|
390 |
+
xmlns="http://www.w3.org/2000/svg"
|
391 |
+
{...props}
|
392 |
+
>
|
393 |
+
<path
|
394 |
+
fillRule="evenodd"
|
395 |
+
clipRule="evenodd"
|
396 |
+
d="M13.5663 0L10.9988 6.22842L8.42884 0H6.78016L9.597 6.80871C9.83063 7.37681 10.3786 7.74377 10.9892 7.74377C11.5997 7.74377 12.1465 7.37681 12.3813 6.81115L15.215 0H13.5663ZM14.6635 9.48953L19.3602 4.68259L18.7195 3.15261L13.5892 8.41306C13.1605 8.85315 13.0377 9.50172 13.2749 10.0698C13.5109 10.633 14.0565 10.9976 14.6647 10.9976L14.6671 11L22 10.9817L21.3593 9.45173L14.6647 9.48953H14.6635ZM2.63981 4.67893L3.28049 3.14895L8.41077 8.4094C8.8395 8.84828 8.96354 9.49928 8.72509 10.0662C8.48905 10.6306 7.9411 10.9939 7.33534 10.9939L0.00240858 10.9768L0 10.9793L0.640683 9.4493L7.33534 9.48709L2.63981 4.67893Z"
|
397 |
+
fill="#FAFAFA"
|
398 |
+
/>
|
399 |
+
</svg>
|
400 |
+
)
|
401 |
+
|
402 |
+
export const AzureLogo: FC = ({ ...props }) => (
|
403 |
+
<svg
|
404 |
+
width="21"
|
405 |
+
height="17"
|
406 |
+
viewBox="0 0 21 17"
|
407 |
+
fill="none"
|
408 |
+
xmlns="http://www.w3.org/2000/svg"
|
409 |
+
{...props}
|
410 |
+
>
|
411 |
+
<path
|
412 |
+
d="M11.4736 0L5.2828 5.44659L0 15.0667H4.76322L11.4736 0ZM12.2971 1.27434L9.65504 8.82946L14.7209 15.2868L4.89312 17H21L12.2971 1.27434Z"
|
413 |
+
fill="#FAFAFA"
|
414 |
+
/>
|
415 |
+
</svg>
|
416 |
+
)
|
417 |
+
export const XaiLogo: FC = ({ ...props }) => (
|
418 |
+
<svg
|
419 |
+
width="22"
|
420 |
+
height="24"
|
421 |
+
viewBox="0 0 22 24"
|
422 |
+
fill="none"
|
423 |
+
xmlns="http://www.w3.org/2000/svg"
|
424 |
+
{...props}
|
425 |
+
>
|
426 |
+
<path
|
427 |
+
d="M11.334 14.201L18.9751 3.08215H15.2822L9.48779 11.5143L11.334 14.201Z"
|
428 |
+
fill="#FAFAFA"
|
429 |
+
/>
|
430 |
+
<path
|
431 |
+
d="M6.71784 20.9178L8.5643 18.2311L6.71784 15.5444L3.0249 20.9178H6.71784Z"
|
432 |
+
fill="#FAFAFA"
|
433 |
+
/>
|
434 |
+
<path
|
435 |
+
d="M11.3337 20.9179H15.0266L6.71784 8.82727H3.0249L11.3337 20.9179Z"
|
436 |
+
fill="#FAFAFA"
|
437 |
+
/>
|
438 |
+
<path
|
439 |
+
d="M18.9752 4.42566L15.9502 8.82726L16.2527 20.9179H18.6727L18.9752 4.42566Z"
|
440 |
+
fill="#FAFAFA"
|
441 |
+
/>
|
442 |
+
</svg>
|
443 |
+
)
|
444 |
+
export const OpenAILogo: FC = ({ ...props }) => (
|
445 |
+
<svg
|
446 |
+
width="22"
|
447 |
+
height="22"
|
448 |
+
viewBox="0 0 22 22"
|
449 |
+
fill="none"
|
450 |
+
xmlns="http://www.w3.org/2000/svg"
|
451 |
+
{...props}
|
452 |
+
>
|
453 |
+
<path
|
454 |
+
d="M19.928 9.17291C20.1619 8.48057 20.2431 7.74579 20.166 7.01908C20.0889 6.29237 19.8553 5.59098 19.4813 4.96315C18.9236 4.00802 18.0774 3.25435 17.0643 2.81052C16.0459 2.36318 14.9128 2.24653 13.8245 2.47697C13.3319 1.92958 12.7283 1.49331 12.0541 1.19715C11.3779 0.900007 10.6467 0.7488 9.90817 0.753398C8.79741 0.750306 7.71375 1.09622 6.81018 1.74229C5.91252 2.38357 5.24266 3.29435 4.89791 4.34234C4.17432 4.48829 3.48982 4.78574 2.88939 5.21515C2.29172 5.64211 1.79226 6.19195 1.42452 6.82779C0.865606 7.77609 0.626698 8.8791 0.743123 9.97369C0.859548 11.0683 1.32512 12.0964 2.071 12.9059C1.83719 13.598 1.75599 14.3327 1.83296 15.0592C1.90994 15.7858 2.14327 16.487 2.51693 17.1149C3.07465 18.07 3.92086 18.8237 4.9339 19.2675C5.95236 19.7148 7.08545 19.8315 8.17368 19.6011C8.66609 20.1484 9.26938 20.5847 9.94343 20.8809C10.6193 21.1777 11.351 21.329 12.0908 21.3246C13.2022 21.3284 14.2867 20.9828 15.191 20.3365C16.0897 19.6947 16.7602 18.7828 17.1047 17.7335C17.8283 17.5878 18.5128 17.2906 19.1132 16.8614C19.7108 16.4342 20.21 15.8841 20.5774 15.248C21.1355 14.2997 21.3737 13.1969 21.2567 12.1028C21.1398 11.0086 20.6739 9.98111 19.928 9.17217V9.17291ZM12.1334 19.9802C11.0961 19.9802 10.2931 19.6657 9.59154 19.0875C9.62313 19.0706 9.67896 19.0405 9.71496 19.0184L13.8657 16.6528C13.969 16.5946 14.0551 16.5099 14.1149 16.4076C14.1748 16.3052 14.2065 16.1888 14.2066 16.0702V10.2955L15.9616 11.2947C15.9707 11.2994 15.9784 11.3062 15.9843 11.3145C15.9902 11.3228 15.994 11.3324 15.9954 11.3424V16.1238C15.9954 18.2926 14.1654 19.9802 12.1334 19.9802ZM3.69897 16.4419C3.24145 15.6637 3.07607 14.7479 3.23247 13.8587C3.26333 13.8771 3.31696 13.9102 3.35589 13.9322L7.50662 16.2979C7.61026 16.3577 7.72783 16.3892 7.8475 16.3892C7.96717 16.3892 8.08473 16.3577 8.18837 16.2979L13.2559 13.4106V15.4089C13.2565 15.4191 13.2546 15.4293 13.2502 15.4386C13.2458 15.4478 13.2392 15.4558 13.231 15.4618L9.03541 17.8532C8.13546 18.3637 7.07136 18.5014 6.07113 18.2367C5.07431 17.9751 4.22209 17.3299 3.69897 16.4419ZM2.60509 7.50076C3.06415 6.71658 3.78377 6.11833 4.63858 5.81025V10.6827C4.63744 10.8015 4.66853 10.9185 4.72856 11.0211C4.78858 11.1237 4.87529 11.2081 4.97945 11.2653L10.0463 14.1526L8.29196 15.1518C8.28336 15.1574 8.27352 15.1609 8.26329 15.1619C8.25306 15.163 8.24273 15.1615 8.23318 15.1577L4.03544 12.7648C3.59337 12.5135 3.20522 12.1775 2.89322 11.776C2.58121 11.3744 2.35149 10.9153 2.2172 10.4248C2.08441 9.93612 2.05026 9.42588 2.11673 8.92385C2.1832 8.42182 2.3497 7.93805 2.60509 7.50076ZM17.021 10.8113L11.9534 7.92394L13.7077 6.92477C13.7163 6.91913 13.7262 6.91566 13.7364 6.91463C13.7466 6.91361 13.757 6.91507 13.7665 6.91889L17.9635 9.3103C18.6041 9.67505 19.1276 10.2148 19.4725 10.8664C19.8153 11.5148 19.9639 12.2485 19.9003 12.9793C19.8367 13.71 19.5637 14.407 19.114 14.9865C18.6616 15.5707 18.0528 16.0145 17.3582 16.2663V11.3931C17.3595 11.2748 17.3288 11.1583 17.2695 11.0559C17.2101 10.9535 17.1243 10.869 17.021 10.8113ZM18.7672 8.21561C18.7264 8.19087 18.6852 8.16662 18.6438 8.14288L14.4931 5.77719C14.3894 5.71749 14.2718 5.68607 14.1522 5.68607C14.0326 5.68607 13.915 5.71749 13.8113 5.77719L8.74376 8.66451V6.66469C8.74316 6.65448 8.74513 6.64429 8.74949 6.63505C8.75386 6.62581 8.76048 6.61781 8.76874 6.61179L12.965 4.22332C13.6091 3.85713 14.3432 3.67955 15.0834 3.71086C15.8237 3.74217 16.5401 3.98111 17.151 4.40038C17.7579 4.81692 18.2332 5.39805 18.5211 6.07547C18.8076 6.75138 18.8929 7.49341 18.7672 8.21561ZM7.79019 11.7803L6.0344 10.7811C6.02522 10.7767 6.01731 10.7699 6.0114 10.7616C6.0055 10.7532 6.00178 10.7435 6.00061 10.7334V5.95131C6.00134 5.21882 6.21365 4.50177 6.61183 3.8839C7.01235 3.26422 7.58077 2.77118 8.25082 2.46228C8.92372 2.15201 9.67027 2.03708 10.4053 2.13061C11.1404 2.22414 11.8344 2.52236 12.4082 2.99125C12.3666 3.01322 12.3254 3.036 12.2847 3.05958L8.13401 5.42527C8.03063 5.48349 7.94455 5.56809 7.88453 5.67044C7.82452 5.77279 7.79273 5.88923 7.7924 6.00788L7.79019 11.7803ZM8.74303 9.75258L10.9998 8.46761L13.2567 9.75331V12.3247L10.9998 13.6097L8.74303 12.324V9.75258Z"
|
455 |
+
fill="#FAFAFA"
|
456 |
+
/>
|
457 |
+
</svg>
|
458 |
+
)
|
459 |
+
|
460 |
+
export const SheetIcon: FC = ({ ...props }) => (
|
461 |
+
<svg
|
462 |
+
width="16"
|
463 |
+
height="16"
|
464 |
+
viewBox="0 0 16 16"
|
465 |
+
fill="none"
|
466 |
+
xmlns="http://www.w3.org/2000/svg"
|
467 |
+
{...props}
|
468 |
+
>
|
469 |
+
<path
|
470 |
+
d="M6 2V14M10.6667 10L8.66667 8L10.6667 6M3.33333 2H12.6667C13.403 2 14 2.59695 14 3.33333V12.6667C14 13.403 13.403 14 12.6667 14H3.33333C2.59695 14 2 13.403 2 12.6667V3.33333C2 2.59695 2.59695 2 3.33333 2Z"
|
471 |
+
stroke="#FAFAFA"
|
472 |
+
strokeLinecap="round"
|
473 |
+
strokeLinejoin="round"
|
474 |
+
/>
|
475 |
+
</svg>
|
476 |
+
)
|
477 |
+
|
478 |
+
export const NextjsTag: FC = ({ ...props }) => (
|
479 |
+
<svg
|
480 |
+
width="29"
|
481 |
+
height="30"
|
482 |
+
viewBox="12 0 29 30"
|
483 |
+
fill="none"
|
484 |
+
xmlns="http://www.w3.org/2000/svg"
|
485 |
+
{...props}
|
486 |
+
>
|
487 |
+
<g filter="url(#filter0_dd_2859_5307)">
|
488 |
+
<rect
|
489 |
+
x="12.1167"
|
490 |
+
y="2"
|
491 |
+
width="28"
|
492 |
+
height="28"
|
493 |
+
rx="8"
|
494 |
+
fill="#FAFAFA"
|
495 |
+
shapeRendering="crispEdges"
|
496 |
+
/>
|
497 |
+
<g clipPath="url(#clip0_2859_5307)">
|
498 |
+
<rect
|
499 |
+
width="20"
|
500 |
+
height="20"
|
501 |
+
transform="translate(16.1167 6)"
|
502 |
+
fill="white"
|
503 |
+
/>
|
504 |
+
<path
|
505 |
+
d="M30.9598 24.7533C30.8854 24.7927 30.8917 24.8052 30.9629 24.7689C30.9861 24.7595 31.0055 24.7464 31.0223 24.7308C31.0223 24.7177 31.0223 24.7177 30.9598 24.7533ZM31.1098 24.672C31.0742 24.7014 31.0742 24.7014 31.1167 24.682C31.1392 24.6689 31.1592 24.6564 31.1592 24.6527C31.1592 24.6358 31.1492 24.6395 31.1098 24.672ZM31.2073 24.6133C31.1717 24.6427 31.1717 24.6427 31.2142 24.6233C31.2373 24.6102 31.2567 24.5964 31.2567 24.5933C31.2567 24.5777 31.2467 24.5808 31.2073 24.6133ZM31.3061 24.5552C31.2704 24.5845 31.2704 24.5845 31.3117 24.5645C31.3348 24.552 31.3542 24.5389 31.3542 24.5352C31.3542 24.5195 31.3442 24.5227 31.3061 24.5552ZM31.4392 24.467C31.3711 24.5127 31.3473 24.542 31.4098 24.5095C31.4517 24.4839 31.5229 24.4277 31.5104 24.4277C31.4836 24.4377 31.4611 24.4545 31.4386 24.467H31.4392ZM25.4623 6.00704C25.4167 6.01016 25.2798 6.02266 25.1598 6.03266C22.3173 6.29016 19.6579 7.82016 17.9723 10.177C17.0404 11.4689 16.4354 12.9695 16.2073 14.5452C16.1267 15.0952 16.1167 15.2577 16.1167 16.0033C16.1167 16.7483 16.1267 16.9083 16.2073 17.4583C16.7517 21.2152 19.4242 24.3689 23.0467 25.5377C23.6986 25.7458 24.3817 25.8895 25.1598 25.9777C25.4623 26.0102 26.7704 26.0102 27.0729 25.9777C28.4179 25.8277 29.5536 25.4958 30.6773 24.9227C30.8498 24.8352 30.8823 24.812 30.8592 24.7927C30.3092 24.067 29.7692 23.3408 29.2286 22.6083L27.6304 20.4502L25.6286 17.4845C24.9611 16.492 24.2911 15.502 23.6104 14.5195C23.6036 14.5195 23.5948 15.8377 23.5911 17.4452C23.5842 20.2608 23.5842 20.3752 23.5486 20.4402C23.5129 20.5183 23.4542 20.5833 23.3761 20.6195C23.3142 20.6489 23.2586 20.6552 22.9629 20.6552H22.6248L22.5367 20.6002C22.4817 20.5645 22.4361 20.5152 22.4067 20.457L22.3642 20.3689L22.3673 16.4495L22.3742 12.5302L22.4361 12.452C22.4754 12.4039 22.5242 12.3645 22.5792 12.3352C22.6611 12.2958 22.6936 12.2895 23.0317 12.2895C23.4286 12.2895 23.4942 12.3052 23.5986 12.4195C24.4086 13.627 25.2161 14.8377 26.0104 16.052C27.3098 18.022 29.0836 20.7102 29.9554 22.0289L31.5411 24.4283L31.6192 24.3764C32.3811 23.8683 33.0742 23.2633 33.6723 22.5733C34.9323 21.1308 35.7498 19.3564 36.0267 17.4627C36.1073 16.9127 36.1173 16.7495 36.1173 16.0045C36.1173 15.2589 36.1073 15.0995 36.0267 14.5495C35.4823 10.7927 32.8098 7.63891 29.1873 6.46954C28.5098 6.25516 27.8129 6.10891 27.1073 6.03391C26.9179 6.01454 25.6254 5.99141 25.4629 6.00829L25.4623 6.00704ZM29.5542 12.0552C29.6486 12.1002 29.7198 12.1852 29.7523 12.2827C29.7692 12.3352 29.7723 13.422 29.7692 15.8702L29.7623 19.3852L29.1442 18.4352L28.5223 17.4845V14.9327C28.5223 13.2783 28.5292 12.3508 28.5379 12.3052C28.5673 12.2008 28.6386 12.1133 28.7336 12.0583C28.8111 12.0189 28.8411 12.0158 29.1504 12.0158C29.4398 12.0158 29.4892 12.0189 29.5542 12.0552Z"
|
506 |
+
fill="black"
|
507 |
+
/>
|
508 |
+
</g>
|
509 |
+
</g>
|
510 |
+
<defs>
|
511 |
+
<filter
|
512 |
+
id="filter0_dd_2859_5307"
|
513 |
+
x="0.116699"
|
514 |
+
y="0"
|
515 |
+
width="52"
|
516 |
+
height="52"
|
517 |
+
filterUnits="userSpaceOnUse"
|
518 |
+
colorInterpolationFilters="sRGB"
|
519 |
+
>
|
520 |
+
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
521 |
+
<feColorMatrix
|
522 |
+
in="SourceAlpha"
|
523 |
+
type="matrix"
|
524 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
525 |
+
result="hardAlpha"
|
526 |
+
/>
|
527 |
+
<feMorphology
|
528 |
+
radius="3"
|
529 |
+
operator="erode"
|
530 |
+
in="SourceAlpha"
|
531 |
+
result="effect1_dropShadow_2859_5307"
|
532 |
+
/>
|
533 |
+
<feOffset dy="10" />
|
534 |
+
<feGaussianBlur stdDeviation="7.5" />
|
535 |
+
<feComposite in2="hardAlpha" operator="out" />
|
536 |
+
<feColorMatrix
|
537 |
+
type="matrix"
|
538 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
539 |
+
/>
|
540 |
+
<feBlend
|
541 |
+
mode="normal"
|
542 |
+
in2="BackgroundImageFix"
|
543 |
+
result="effect1_dropShadow_2859_5307"
|
544 |
+
/>
|
545 |
+
<feColorMatrix
|
546 |
+
in="SourceAlpha"
|
547 |
+
type="matrix"
|
548 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
549 |
+
result="hardAlpha"
|
550 |
+
/>
|
551 |
+
<feMorphology
|
552 |
+
radius="4"
|
553 |
+
operator="erode"
|
554 |
+
in="SourceAlpha"
|
555 |
+
result="effect2_dropShadow_2859_5307"
|
556 |
+
/>
|
557 |
+
<feOffset dy="4" />
|
558 |
+
<feGaussianBlur stdDeviation="3" />
|
559 |
+
<feComposite in2="hardAlpha" operator="out" />
|
560 |
+
<feColorMatrix
|
561 |
+
type="matrix"
|
562 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
563 |
+
/>
|
564 |
+
<feBlend
|
565 |
+
mode="normal"
|
566 |
+
in2="effect1_dropShadow_2859_5307"
|
567 |
+
result="effect2_dropShadow_2859_5307"
|
568 |
+
/>
|
569 |
+
<feBlend
|
570 |
+
mode="normal"
|
571 |
+
in="SourceGraphic"
|
572 |
+
in2="effect2_dropShadow_2859_5307"
|
573 |
+
result="shape"
|
574 |
+
/>
|
575 |
+
</filter>
|
576 |
+
<clipPath id="clip0_2859_5307">
|
577 |
+
<rect
|
578 |
+
width="20"
|
579 |
+
height="20"
|
580 |
+
fill="white"
|
581 |
+
transform="translate(16.1167 6)"
|
582 |
+
/>
|
583 |
+
</clipPath>
|
584 |
+
</defs>
|
585 |
+
</svg>
|
586 |
+
)
|
587 |
+
|
588 |
+
export const ShadcnTag: FC = ({ ...props }) => (
|
589 |
+
<svg
|
590 |
+
width="29"
|
591 |
+
height="30"
|
592 |
+
viewBox="12 0 29 30"
|
593 |
+
fill="none"
|
594 |
+
xmlns="http://www.w3.org/2000/svg"
|
595 |
+
xlinkHref="http://www.w3.org/1999/xlink"
|
596 |
+
{...props}
|
597 |
+
>
|
598 |
+
<g filter="url(#filter0_dd_2859_5310)">
|
599 |
+
<rect
|
600 |
+
x="12.1167"
|
601 |
+
y="2"
|
602 |
+
width="28"
|
603 |
+
height="28"
|
604 |
+
rx="8"
|
605 |
+
fill="#FAFAFA"
|
606 |
+
shapeRendering="crispEdges"
|
607 |
+
/>
|
608 |
+
<g clipPath="url(#clip0_2859_5310)">
|
609 |
+
<path
|
610 |
+
d="M31.1167 6H21.1167C18.3553 6 16.1167 8.23858 16.1167 11V21C16.1167 23.7614 18.3553 26 21.1167 26H31.1167C33.8781 26 36.1167 23.7614 36.1167 21V11C36.1167 8.23858 33.8781 6 31.1167 6Z"
|
611 |
+
fill="url(#pattern0_2859_5310)"
|
612 |
+
/>
|
613 |
+
</g>
|
614 |
+
</g>
|
615 |
+
<defs>
|
616 |
+
<filter
|
617 |
+
id="filter0_dd_2859_5310"
|
618 |
+
x="0.116699"
|
619 |
+
y="0"
|
620 |
+
width="52"
|
621 |
+
height="52"
|
622 |
+
filterUnits="userSpaceOnUse"
|
623 |
+
colorInterpolationFilters="sRGB"
|
624 |
+
>
|
625 |
+
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
626 |
+
<feColorMatrix
|
627 |
+
in="SourceAlpha"
|
628 |
+
type="matrix"
|
629 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
630 |
+
result="hardAlpha"
|
631 |
+
/>
|
632 |
+
<feMorphology
|
633 |
+
radius="3"
|
634 |
+
operator="erode"
|
635 |
+
in="SourceAlpha"
|
636 |
+
result="effect1_dropShadow_2859_5310"
|
637 |
+
/>
|
638 |
+
<feOffset dy="10" />
|
639 |
+
<feGaussianBlur stdDeviation="7.5" />
|
640 |
+
<feComposite in2="hardAlpha" operator="out" />
|
641 |
+
<feColorMatrix
|
642 |
+
type="matrix"
|
643 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
644 |
+
/>
|
645 |
+
<feBlend
|
646 |
+
mode="normal"
|
647 |
+
in2="BackgroundImageFix"
|
648 |
+
result="effect1_dropShadow_2859_5310"
|
649 |
+
/>
|
650 |
+
<feColorMatrix
|
651 |
+
in="SourceAlpha"
|
652 |
+
type="matrix"
|
653 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
654 |
+
result="hardAlpha"
|
655 |
+
/>
|
656 |
+
<feMorphology
|
657 |
+
radius="4"
|
658 |
+
operator="erode"
|
659 |
+
in="SourceAlpha"
|
660 |
+
result="effect2_dropShadow_2859_5310"
|
661 |
+
/>
|
662 |
+
<feOffset dy="4" />
|
663 |
+
<feGaussianBlur stdDeviation="3" />
|
664 |
+
<feComposite in2="hardAlpha" operator="out" />
|
665 |
+
<feColorMatrix
|
666 |
+
type="matrix"
|
667 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
668 |
+
/>
|
669 |
+
<feBlend
|
670 |
+
mode="normal"
|
671 |
+
in2="effect1_dropShadow_2859_5310"
|
672 |
+
result="effect2_dropShadow_2859_5310"
|
673 |
+
/>
|
674 |
+
<feBlend
|
675 |
+
mode="normal"
|
676 |
+
in="SourceGraphic"
|
677 |
+
in2="effect2_dropShadow_2859_5310"
|
678 |
+
result="shape"
|
679 |
+
/>
|
680 |
+
</filter>
|
681 |
+
<pattern
|
682 |
+
id="pattern0_2859_5310"
|
683 |
+
patternContentUnits="objectBoundingBox"
|
684 |
+
width="1"
|
685 |
+
height="1"
|
686 |
+
>
|
687 |
+
<use xlinkHref="#image0_2859_5310" transform="scale(0.005)" />
|
688 |
+
</pattern>
|
689 |
+
<clipPath id="clip0_2859_5310">
|
690 |
+
<rect
|
691 |
+
width="20"
|
692 |
+
height="20"
|
693 |
+
fill="white"
|
694 |
+
transform="translate(16.1167 6)"
|
695 |
+
/>
|
696 |
+
</clipPath>
|
697 |
+
<image
|
698 |
+
id="image0_2859_5310"
|
699 |
+
width="200"
|
700 |
+
height="200"
|
701 |
+
xlinkHref="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAIAAAAiOjnJAAAMPWlDQ1BJQ0MgUHJvZmlsZQAASImVVwdYU8kWnltSSWgBBKSE3gSRGkBKCC2A9CLYCEmAUGIMBBU7uqjg2kUEbOiqiGIHxI7YWRR7XyyoKOtiwa68SQFd95Xvne+be//7z5n/nDl3bhkANI7zJJJcVBOAPHGBNC40kDk6JZVJegrIAAE0gAEPHj9fwo6JiQTQBs5/t3fXoS+0K45yrX/2/1fTEgjz+QAgMRCnC/L5eRDvBwCv5kukBQAQ5bzF5AKJHMMGdKQwQYgXyHGmElfLcboS71b4JMRxIG4FgEzj8aSZAKhfgjyzkJ8JNdR7IXYWC0RiADSYEPvl5U0UQJwGsS30kUAs12el/6CT+TfN9EFNHi9zECvnojBykChfksub+n+W439bXq5sIIY1bLQsaVicfM6wbjdzJkbIMQ3iHnF6VDTE2hB/EAkU/hCj1CxZWKLSHzXi53NgzYAexM4CXlAExEYQh4hzoyJVfHqGKIQLMVwh6BRRATcBYn2IFwjzg+NVPhukE+NUsdCGDCmHreLP8qSKuPJY92U5iWyV/ussIVelj6kXZSUkQ0yF2LJQlBQFsTrETvk58REqn5FFWZyoAR+pLE6evyXEcUJxaKBSHyvMkIbEqfxL8/IH5ottyBJxo1R4b0FWQpiyPlgrn6fIH84FuyQUsxMHdIT5oyMH5iIQBgUr5449E4oT41U6HyQFgXHKsThVkhuj8sfNhbmhct4cYrf8wnjVWDypAC5IpT6eISmISVDmiRdl88JjlPngS0Ek4IAgwAQy2NLBRJANRO09jT3wStkTAnhACjKBEDiqmIERyYoeMTzGgyLwJ0RCkD84LlDRKwSFkP86yCqPjiBD0VuoGJEDnkCcByJALryWKUaJB6MlgceQEf0jOg82Psw3FzZ5/7/nB9jvDBsykSpGNhCRqTHgSQwmBhHDiCFEO9wQ98N98Eh4DIDNBWfhXgPz+O5PeELoIDwkXCN0Em5NEBVLf8pyFOiE+iGqWqT/WAvcGmq644G4L1SHyrgebggccTcYh437w8jukOWo8pZXhfmT9t9m8MPdUPlRnCkoZQglgGL780h1e3X3QRV5rX+sjzLX9MF6cwZ7fo7P+aH6AniO+NkTW4Dtw85gJ7Bz2GGsETCxY1gT1oYdkePB1fVYsboGosUp8smBOqJ/xBu4s/JK5jvXOXc7f1H2FQinyN/RgDNRMlUqyswqYLLhF0HI5Ir5TsOYLs4urgDIvy/K19ebWMV3A9Fr+87N/QMA32P9/f2HvnPhxwDY4wkf/4PfOVsW/HSoAXD2IF8mLVRyuPxAgG8JDfikGQATYAFs4XxcgAfwAQEgGISDaJAAUsB4mH0WXOdSMBlMB3NACSgDS8EqUAnWg01gG9gJ9oJGcBicAKfBBXAJXAN34OrpAi9AL3gHPiMIQkLoCAMxQEwRK8QBcUFYiB8SjEQicUgKkoZkImJEhkxH5iJlyHKkEtmI1CJ7kIPICeQc0oHcQh4g3chr5BOKoTRUBzVGrdHhKAtloxFoAjoOzUQnoUXoPHQxWoHWoDvQBvQEegG9hnaiL9A+DGBqmB5mhjliLIyDRWOpWAYmxWZipVg5VoPVY83wPl/BOrEe7CNOxBk4E3eEKzgMT8T5+CR8Jr4Ir8S34Q14K34Ff4D34t8IdIIRwYHgTeASRhMyCZMJJYRywhbCAcIp+Cx1Ed4RiUQ9og3REz6LKcRs4jTiIuJa4i7icWIH8RGxj0QiGZAcSL6kaBKPVEAqIa0h7SAdI10mdZE+kNXIpmQXcgg5lSwmF5PLydvJR8mXyU/JnymaFCuKNyWaIqBMpSyhbKY0Uy5SuiifqVpUG6ovNYGaTZ1DraDWU09R71LfqKmpmat5qcWqidRmq1Wo7VY7q/ZA7SNNm2ZP49DG0mS0xbSttOO0W7Q3dDrdmh5AT6UX0BfTa+kn6ffpH9QZ6k7qXHWB+iz1KvUG9cvqLzUoGlYabI3xGkUa5Rr7NC5q9GhSNK01OZo8zZmaVZoHNW9o9mkxtEZoRWvlaS3S2q51TuuZNknbWjtYW6A9T3uT9kntRwyMYcHgMPiMuYzNjFOMLh2ijo0OVydbp0xnp067Tq+utq6bbpLuFN0q3SO6nXqYnrUeVy9Xb4neXr3rep+GGA9hDxEOWTikfsjlIe/1h+oH6Av1S/V36V/T/2TANAg2yDFYZtBocM8QN7Q3jDWcbLjO8JRhz1CdoT5D+UNLh+4detsINbI3ijOaZrTJqM2oz9jEONRYYrzG+KRxj4meSYBJtslKk6Mm3aYMUz9TkelK02Omz5m6TDYzl1nBbGX2mhmZhZnJzDaatZt9NrcxTzQvNt9lfs+CasGyyLBYadFi0WtpajnKcrplneVtK4oVyyrLarXVGav31jbWydbzrRutn9no23BtimzqbO7a0m39bSfZ1thetSPasexy7NbaXbJH7d3ts+yr7C86oA4eDiKHtQ4dwwjDvIaJh9UMu+FIc2Q7FjrWOT5w0nOKdCp2anR6OdxyeOrwZcPPDP/m7O6c67zZ+c4I7RHhI4pHNI947WLvwnepcrnqSncNcZ3l2uT6ys3BTei2zu2mO8N9lPt89xb3rx6eHlKPeo9uT0vPNM9qzxssHVYMaxHrrBfBK9Brltdhr4/eHt4F3nu9//Jx9Mnx2e7zbKTNSOHIzSMf+Zr78nw3+nb6Mf3S/Db4dfqb+fP8a/wfBlgECAK2BDxl27Gz2TvYLwOdA6WBBwLfc7w5MzjHg7Cg0KDSoPZg7eDE4Mrg+yHmIZkhdSG9oe6h00KPhxHCIsKWhd3gGnP53Fpub7hn+Izw1ghaRHxEZcTDSPtIaWTzKHRU+KgVo+5GWUWJoxqjQTQ3ekX0vRibmEkxh2KJsTGxVbFP4kbETY87E8+InxC/Pf5dQmDCkoQ7ibaJssSWJI2ksUm1Se+Tg5KXJ3eOHj56xugLKYYpopSmVFJqUuqW1L4xwWNWjeka6z62ZOz1cTbjpow7N95wfO74IxM0JvAm7EsjpCWnbU/7wovm1fD60rnp1em9fA5/Nf+FIECwUtAt9BUuFz7N8M1YnvEs0zdzRWZ3ln9WeVaPiCOqFL3KDsten/0+Jzpna05/bnLurjxyXlreQbG2OEfcOtFk4pSJHRIHSYmkc5L3pFWTeqUR0i35SP64/KYCHfgj3yazlf0ie1DoV1hV+GFy0uR9U7SmiKe0TbWfunDq06KQot+m4dP401qmm02fM/3BDPaMjTORmekzW2ZZzJo3q2t26Oxtc6hzcub8XuxcvLz47dzkuc3zjOfNnvfol9Bf6krUS6QlN+b7zF+/AF8gWtC+0HXhmoXfSgWl58ucy8rLviziLzr/64hfK37tX5yxuH2Jx5J1S4lLxUuvL/Nftm251vKi5Y9WjFrRsJK5snTl21UTVp0rdytfv5q6Wra6syKyommN5Zqla75UZlVeqwqs2lVtVL2w+v1awdrL6wLW1a83Xl+2/tMG0YabG0M3NtRY15RvIm4q3PRkc9LmM7+xfqvdYrilbMvXreKtndvitrXWetbWbjfavqQOrZPVde8Yu+PSzqCdTfWO9Rt36e0q2w12y3Y/35O25/reiL0t+1j76vdb7a8+wDhQ2oA0TG3obcxq7GxKaeo4GH6wpdmn+cAhp0NbD5sdrjqie2TJUerReUf7jxUd6zsuOd5zIvPEo5YJLXdOjj55tTW2tf1UxKmzp0NOnzzDPnPsrO/Zw+e8zx08zzrfeMHjQkObe9uB391/P9Du0d5w0fNi0yWvS80dIzuOXva/fOJK0JXTV7lXL1yLutZxPfH6zRtjb3TeFNx8div31qvbhbc/35l9l3C39J7mvfL7Rvdr/rD7Y1enR+eRB0EP2h7GP7zziP/oxeP8x1+65j2hPyl/avq09pnLs8PdId2Xno953vVC8uJzT8mfWn9Wv7R9uf+vgL/aekf3dr2Svup/veiNwZutb93etvTF9N1/l/fu8/vSDwYftn1kfTzzKfnT08+Tv5C+VHy1+9r8LeLb3f68/n4JT8pT/ApgsKEZGQC83goAPQUABtyfUcco938KQ5R7VgUC/wkr94gK8wCgHv6/x/bAv5sbAOzeDLdfUF9jLAAxdAASvADq6jrYBvZqin2l3IhwH7Ah+mt6Xjr4N6bcc/6Q989nIFd1Az+f/wU1+nxXkTLBcwAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAyKADAAQAAAABAAAAyAAAAAC4kx+vAAAHUUlEQVR4Ae3du07jQBiG4YWGgtCAgB5oUnFokRAVF8ANQJMgUSCokKg5VbTQIAR9JKCmRKkiISHuACiooQqg3V/KyvI6Y+dnHXtm7Jdi5Ux8mmc+7PEks/z6xQ8CCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAIIIIAAAggggAACCCCAAAJ2BQbsHp6jGwXm5+eXl5eHhoYeHh7u7u6+v7+Nq1GIgFagUqk0Go3foZ+np6dqtardnvUQ6BYYGBi4vr4Oherv4uvr6+joaPf6lCDQW0BSdX5+3p2qTsnh4WHvXbAGAhGB5FRJtprNZmQTXiLQQ6BnqiRYrVarx154G4GwwMjIyP39fdwdMCi/vLwMb8UyAkkCylS12+2FhYWkHfEeAoGAMlUyiFWr1YKtWEAgSUCfqo2NjaQd8R4CgYD01jX9KrlWkaoAjYUeAppnQOmzk6oejrwdFiBVYQ2W+yNAqvrjyF7CAtJbN34OGIxUdRbe399XV1fDG7KMQKyA/hmQVMUi8kZEQJ8qngEjdLyMFSBVsTS88d8Cw8PDjFf9tx4bmgV4BjS7UJpGgFSl0WNbswCpMrtQmkZA+lUJ3zAORq0+Pj7q9XqaA7FtiQT0z4BLS0slcqGqaQT0qWK8Ko1zubYlVeVq73xqS6rycS7XUeQZUPPpMt+vKlcsUtaWkYWUgGxuECBVBhSKUgqQqpSAbG4QUPbWZRSU8SoDH0VGAWWqmA9o1KPQLKBPFaOgZkFKuwVIVbcJJWkFpLfOt/bSIrJ9RIBnwAgIL/sgQKr6gMguIgKkKgLCyz4ISG9d8zkgs0z7YF2eXeifAZllWp5UpK2pPlWMV6W1Ls/2pKo8bZ1fTZllmp91eY7EM2B52jq/mpKq/KzLcyRSVZ62zq+mzDLNz7o8R9I/A/KtvfKkIm1N9alivCqtdXm2J1Xlaev8auppqmZmZnZ2do6Pj+UKOjExkZ8XR9IIyDOg5tNlp2aZyjnLn8P8+voK/5c16+vrmvqyTh4CPo4syDmfnp4GkQoWJPpyDctDjWMkC/iYKqnR9vZ2EKbIwsXFRXKVeTdzAU9TJd0puTJF8hS8fH5+zhyOAyQIKHvrTs0yjbsDBqmShbe3t4Ra81a2AspUOTXLVJMqCdbt7W22duw9TkCfKndGQZWpkmAtLi7GVZzyDAWKnSp5VMzQjl3HCcjvvXezTPXXKkmVrBxXd8qzEhB0zf+M7dooqHG8Ktxb7yyTqqxyk7xfH1MlNdrf3+/OUHcJqUpu/aze9TRVyeNVQbxIVVa5Sd6v9NY1nwM6NctUfhPkWpUwCtpJlaywt7cnKycL8G7/BfTPgO7MMpWgaPpVTvUF+99yLu9RnyrvxqtIlbXgFThVch88OTmxJlvmA/s4y1R5B5RU0Vu3k21pIcar7NAX+Kg+pkqaQ9Nb51plLbeepkoeHTrDB8n/cge0EywfZ5nKb4J8F1QzXiW9dVnZjmyZj6p/BnRnlqkERXMHZGTBWrD1qWK8ylojeXfgAqdKulzyiY13LVKEEy52quit28mo9FE0ny471UdR9qsYWbATKTmqtBCjoNb0i3pgH1MlbZEwyzQ8gsUd0E5uPU0V39qzExflUZW9de9mmcoVy6m+oLI5CrKaMlXSQrVazZE6K3vrpMpae+lT5d0oqFyu3Dlnaw1s5cDFTpX01q2olv2gcjdhlmnZQ9D3+vv4DKjsVzEK2ve0aHfoY6qkbswy1TawlfU8TRXjVVbSoj1opVLRfA7ILFMtKOt1BBqNRvhTDuOyjP0wy5TA/EBgbm7OmKRwoVMjisreulPn/IP2KMyqW1tb4Qx1LzvVQspUSS2YZWo5oru7u91hCko8TRXfWbCcKjn8yspKEKPIAqmy3zz+nsHg4ODj42MkUvLSqVQJr1yEuk+yu4RrlUNRrFarLy8v4UZqt9vufGdBpGS8Knx6ccukyqFUdU5lbGzs4OCg2Wy2Wq2rq6vZ2VlHTlF668wydaQtinMaymdA1+7axWmAotbk6Ogo7q4XlJOqorZ+VvWanp7+/PwMAhS3wCzTrBqgqPvVTLOht25s/UFjKYUdgcnJyWSKs7Ozzc1NuZIlr8a7CPwjUK/X425/Us616h8sXugFxsfHZWKZMVukSs/ImgaBtbU1eeiLZItUGaQo+qnA1NSU/N1l+Qu58rdMb25u+PuAPwVkfQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAABBGIF/gDBGgU9zku5PgAAAABJRU5ErkJggg=="
|
702 |
+
/>
|
703 |
+
</defs>
|
704 |
+
</svg>
|
705 |
+
)
|
706 |
+
|
707 |
+
export const TailwindTag: FC = ({ ...props }) => (
|
708 |
+
<svg
|
709 |
+
width="29"
|
710 |
+
height="30"
|
711 |
+
viewBox="12 0 29 30"
|
712 |
+
fill="none"
|
713 |
+
xmlns="http://www.w3.org/2000/svg"
|
714 |
+
{...props}
|
715 |
+
>
|
716 |
+
<g filter="url(#filter0_dd_2859_5313)">
|
717 |
+
<rect
|
718 |
+
x="12.1167"
|
719 |
+
y="2"
|
720 |
+
width="28"
|
721 |
+
height="28"
|
722 |
+
rx="8"
|
723 |
+
fill="#FAFAFA"
|
724 |
+
shapeRendering="crispEdges"
|
725 |
+
/>
|
726 |
+
<rect x="16.1167" y="6" width="20" height="20" rx="5" fill="#18181B" />
|
727 |
+
<mask
|
728 |
+
id="mask0_2859_5313"
|
729 |
+
// style="mask-type:luminance"
|
730 |
+
maskUnits="userSpaceOnUse"
|
731 |
+
x="20"
|
732 |
+
y="12"
|
733 |
+
width="13"
|
734 |
+
height="8"
|
735 |
+
>
|
736 |
+
<path
|
737 |
+
d="M20.1167 12.3999H32.1167V19.5999H20.1167V12.3999Z"
|
738 |
+
fill="white"
|
739 |
+
/>
|
740 |
+
</mask>
|
741 |
+
<g mask="url(#mask0_2859_5313)">
|
742 |
+
<path
|
743 |
+
fillRule="evenodd"
|
744 |
+
clipRule="evenodd"
|
745 |
+
d="M26.1167 12.3999C24.5167 12.3999 23.5167 13.1999 23.1167 14.7999C23.7167 13.9999 24.4167 13.6999 25.2167 13.8999C25.6731 14.0139 25.9994 14.3452 26.3605 14.7117C26.9487 15.3088 27.6296 15.9999 29.1167 15.9999C30.7167 15.9999 31.7167 15.1999 32.1167 13.5999C31.5167 14.3999 30.8167 14.6999 30.0167 14.4999C29.5603 14.3859 29.234 14.0546 28.8729 13.6881C28.2847 13.091 27.6038 12.3999 26.1167 12.3999ZM23.1167 15.9999C21.5167 15.9999 20.5167 16.7999 20.1167 18.3999C20.7167 17.5999 21.4167 17.2999 22.2167 17.4999C22.6731 17.6141 22.9994 17.9452 23.3605 18.3117C23.9487 18.9088 24.6296 19.5999 26.1167 19.5999C27.7167 19.5999 28.7167 18.7999 29.1167 17.1999C28.5167 17.9999 27.8167 18.2999 27.0167 18.0999C26.5603 17.9859 26.234 17.6546 25.8729 17.2881C25.2847 16.691 24.6038 15.9999 23.1167 15.9999Z"
|
746 |
+
fill="#FAFAFA"
|
747 |
+
/>
|
748 |
+
</g>
|
749 |
+
</g>
|
750 |
+
<defs>
|
751 |
+
<filter
|
752 |
+
id="filter0_dd_2859_5313"
|
753 |
+
x="0.116699"
|
754 |
+
y="0"
|
755 |
+
width="52"
|
756 |
+
height="52"
|
757 |
+
filterUnits="userSpaceOnUse"
|
758 |
+
colorInterpolationFilters="sRGB"
|
759 |
+
>
|
760 |
+
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
761 |
+
<feColorMatrix
|
762 |
+
in="SourceAlpha"
|
763 |
+
type="matrix"
|
764 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
765 |
+
result="hardAlpha"
|
766 |
+
/>
|
767 |
+
<feMorphology
|
768 |
+
radius="3"
|
769 |
+
operator="erode"
|
770 |
+
in="SourceAlpha"
|
771 |
+
result="effect1_dropShadow_2859_5313"
|
772 |
+
/>
|
773 |
+
<feOffset dy="10" />
|
774 |
+
<feGaussianBlur stdDeviation="7.5" />
|
775 |
+
<feComposite in2="hardAlpha" operator="out" />
|
776 |
+
<feColorMatrix
|
777 |
+
type="matrix"
|
778 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
779 |
+
/>
|
780 |
+
<feBlend
|
781 |
+
mode="normal"
|
782 |
+
in2="BackgroundImageFix"
|
783 |
+
result="effect1_dropShadow_2859_5313"
|
784 |
+
/>
|
785 |
+
<feColorMatrix
|
786 |
+
in="SourceAlpha"
|
787 |
+
type="matrix"
|
788 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
789 |
+
result="hardAlpha"
|
790 |
+
/>
|
791 |
+
<feMorphology
|
792 |
+
radius="4"
|
793 |
+
operator="erode"
|
794 |
+
in="SourceAlpha"
|
795 |
+
result="effect2_dropShadow_2859_5313"
|
796 |
+
/>
|
797 |
+
<feOffset dy="4" />
|
798 |
+
<feGaussianBlur stdDeviation="3" />
|
799 |
+
<feComposite in2="hardAlpha" operator="out" />
|
800 |
+
<feColorMatrix
|
801 |
+
type="matrix"
|
802 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"
|
803 |
+
/>
|
804 |
+
<feBlend
|
805 |
+
mode="normal"
|
806 |
+
in2="effect1_dropShadow_2859_5313"
|
807 |
+
result="effect2_dropShadow_2859_5313"
|
808 |
+
/>
|
809 |
+
<feBlend
|
810 |
+
mode="normal"
|
811 |
+
in="SourceGraphic"
|
812 |
+
in2="effect2_dropShadow_2859_5313"
|
813 |
+
result="shape"
|
814 |
+
/>
|
815 |
+
</filter>
|
816 |
+
</defs>
|
817 |
+
</svg>
|
818 |
+
)
|
819 |
+
|
820 |
+
export const AgnoTag: FC = ({ ...props }) => {
|
821 |
+
return (
|
822 |
+
<svg
|
823 |
+
width="101"
|
824 |
+
height="56"
|
825 |
+
viewBox="0 0 101 56"
|
826 |
+
fill="none"
|
827 |
+
xmlns="http://www.w3.org/2000/svg"
|
828 |
+
{...props}
|
829 |
+
>
|
830 |
+
<g filter="url(#filter0_dd_2859_5300)">
|
831 |
+
<rect
|
832 |
+
x="11.6504"
|
833 |
+
y="6.56763"
|
834 |
+
width="76"
|
835 |
+
height="28"
|
836 |
+
rx="8"
|
837 |
+
transform="rotate(-3.82708 11.6504 6.56763)"
|
838 |
+
fill="#FAFAFA"
|
839 |
+
shapeRendering="geometricPrecision"
|
840 |
+
/>
|
841 |
+
<g clipPath="url(#clip0_2859_5300)">
|
842 |
+
<path
|
843 |
+
fillRule="evenodd"
|
844 |
+
clipRule="evenodd"
|
845 |
+
d="M35.7024 11.2754C36.1945 12.1001 36.2693 13.2177 36.4188 15.4529L36.8994 22.6374C37.0489 24.8726 37.1237 25.9902 36.7458 26.8731C36.4134 27.6496 35.8437 28.301 35.1183 28.7339C34.2937 29.226 33.1761 29.3008 30.9408 29.4503L23.7563 29.9309C21.5211 30.0804 20.4035 30.1552 19.5207 29.7773C18.7441 29.4449 18.0927 28.8752 17.6598 28.1498C17.1677 27.3252 17.0929 26.2076 16.9434 23.9724L16.4628 16.7878C16.3133 14.5526 16.2385 13.435 16.6164 12.5522C16.9488 11.7756 17.5185 11.1242 18.2439 10.6913C19.0686 10.1992 20.1862 10.1245 22.4214 9.97493L29.6059 9.49432C31.8411 9.3448 32.9587 9.27004 33.8416 9.64793C34.6181 9.98033 35.2695 10.55 35.7024 11.2754ZM22.802 14.5601L27.829 14.2239L32.6254 24.3203L30.5336 24.4602L26.7197 16.0701L22.92 16.3243L22.802 14.5601ZM20.5341 23.3571L25.6815 23.0127L25.7995 24.7769L20.6521 25.1212L20.5341 23.3571Z"
|
846 |
+
fill="#FF4017"
|
847 |
+
/>
|
848 |
+
</g>
|
849 |
+
<path
|
850 |
+
d="M47.0613 24.2435L45.5873 24.3421L49.0739 12.4465L50.5252 12.3495L55.565 23.6747L54.0911 23.7733L49.9677 14.2318L49.877 14.2378L47.0613 24.2435ZM47.3022 19.6718L53.2434 19.2744L53.3269 20.5216L47.3856 20.919L47.3022 19.6718ZM60.9375 26.7776C60.2912 26.8208 59.7301 26.7748 59.2541 26.6396C58.7784 26.5082 58.3766 26.3187 58.0487 26.0711C57.7249 25.827 57.4621 25.5598 57.2605 25.2696L58.2762 24.45C58.4078 24.6006 58.573 24.7718 58.7718 24.9635C58.9709 25.159 59.2362 25.3216 59.5675 25.4513C59.9029 25.5845 60.3333 25.6335 60.8586 25.5984C61.5616 25.5514 62.1304 25.3425 62.5649 24.9717C62.9995 24.601 63.1925 24.0528 63.144 23.3271L63.0256 21.5584L62.9123 21.566C62.8246 21.7313 62.6979 21.9371 62.5322 22.1836C62.37 22.426 62.1267 22.6492 61.8025 22.8531C61.4818 23.053 61.038 23.1719 60.4711 23.2098C59.7681 23.2569 59.1258 23.1328 58.5442 22.8376C57.9664 22.5422 57.4937 22.0879 57.1262 21.4747C56.7625 20.8612 56.5503 20.101 56.4896 19.1939C56.4299 18.3019 56.5348 17.5148 56.8043 16.8324C57.0735 16.1462 57.4756 15.603 58.0107 15.2028C58.5455 14.7988 59.1796 14.5722 59.9128 14.5232C60.4797 14.4853 60.9358 14.5497 61.281 14.7164C61.6297 14.8791 61.9009 15.0735 62.0945 15.2997C62.2916 15.5219 62.4443 15.7053 62.5527 15.8499L62.6887 15.8408L62.5962 14.4576L63.8888 14.3711L64.4879 23.3283C64.538 24.0767 64.4086 24.6965 64.0998 25.1879C63.7951 25.6829 63.3647 26.059 62.8086 26.3164C62.2566 26.5773 61.6329 26.731 60.9375 26.7776ZM60.5721 21.9958C61.1088 21.9599 61.5541 21.8068 61.908 21.5363C62.262 21.2659 62.5199 20.8937 62.6818 20.4197C62.8437 19.9457 62.9032 19.3875 62.8602 18.745C62.8182 18.1176 62.6867 17.5702 62.4656 17.1029C62.2446 16.6355 61.9397 16.2782 61.5511 16.0308C61.1626 15.7835 60.6961 15.678 60.1519 15.7144C59.585 15.7523 59.1222 15.9276 58.7634 16.2401C58.4085 16.5523 58.1527 16.9567 57.9961 17.4531C57.8433 17.9492 57.7866 18.4921 57.826 19.0817C57.8665 19.6864 57.9967 20.2149 58.2168 20.6671C58.4404 21.1153 58.7481 21.4592 59.14 21.6987C59.5354 21.9342 60.0127 22.0332 60.5721 21.9958ZM67.9078 17.5873L68.2583 22.8256L66.9203 22.9151L66.3378 14.2073L67.6304 14.1208L67.7214 15.4814L67.8348 15.4738C68.0093 15.018 68.2954 14.642 68.6932 14.3458C69.0908 14.0459 69.6183 13.8739 70.276 13.8299C70.8656 13.7905 71.3895 13.8769 71.8479 14.0892C72.306 14.2978 72.6742 14.6376 72.9525 15.1087C73.2305 15.576 73.3943 16.1801 73.4439 16.9208L73.814 22.4539L72.4761 22.5434L72.112 17.101C72.0663 16.417 71.853 15.8959 71.4722 15.538C71.0911 15.1763 70.5907 15.0161 69.9709 15.0576C69.5438 15.0861 69.1683 15.2043 68.8443 15.412C68.5241 15.6194 68.2795 15.9072 68.1105 16.2754C67.9415 16.6435 67.874 17.0808 67.9078 17.5873ZM79.8085 22.2351C79.0224 22.2877 78.3201 22.1468 77.7017 21.8123C77.0871 21.4776 76.591 20.985 76.2134 20.3345C75.8396 19.6838 75.6226 18.9086 75.5624 18.0091C75.5018 17.1021 75.6132 16.2993 75.8968 15.6008C76.1841 14.902 76.61 14.3458 77.1746 13.9322C77.7429 13.5184 78.4202 13.2851 79.2063 13.2325C79.9924 13.18 80.6928 13.321 81.3074 13.6557C81.9258 13.9902 82.422 14.4847 82.7961 15.1392C83.174 15.7935 83.3932 16.5742 83.4539 17.4812C83.5141 18.3807 83.4004 19.178 83.1128 19.873C82.829 20.5677 82.4029 21.122 81.8345 21.5359C81.27 21.9495 80.5946 22.1826 79.8085 22.2351ZM79.7281 21.0333C80.3253 20.9933 80.8064 20.8074 81.1714 20.4755C81.5364 20.1436 81.7948 19.722 81.9466 19.2107C82.0985 18.6994 82.1549 18.1528 82.116 17.5707C82.077 16.9887 81.9482 16.4525 81.7293 15.9623C81.5105 15.472 81.198 15.0848 80.7918 14.8007C80.3855 14.5165 79.8838 14.3945 79.2867 14.4344C78.6895 14.4743 78.2086 14.6622 77.8438 14.9979C77.479 15.3336 77.2209 15.759 77.0693 16.274C76.9177 16.7891 76.8614 17.3376 76.9004 17.9196C76.9393 18.5017 77.068 19.0359 77.2866 19.5224C77.5052 20.0089 77.8174 20.3923 78.2234 20.6727C78.6294 20.953 79.131 21.0732 79.7281 21.0333Z"
|
851 |
+
fill="#18181B"
|
852 |
+
/>
|
853 |
+
</g>
|
854 |
+
<defs>
|
855 |
+
<filter
|
856 |
+
id="filter0_dd_2859_5300"
|
857 |
+
x="-0.349609"
|
858 |
+
y="-0.505127"
|
859 |
+
width="101.699"
|
860 |
+
height="57.0103"
|
861 |
+
filterUnits="userSpaceOnUse"
|
862 |
+
colorInterpolationFilters="sRGB"
|
863 |
+
>
|
864 |
+
<feFlood floodOpacity="0" result="BackgroundImageFix" />
|
865 |
+
<feColorMatrix
|
866 |
+
in="SourceAlpha"
|
867 |
+
type="matrix"
|
868 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
869 |
+
result="hardAlpha"
|
870 |
+
/>
|
871 |
+
<feMorphology
|
872 |
+
radius="2"
|
873 |
+
operator="erode"
|
874 |
+
in="SourceAlpha"
|
875 |
+
result="effect1_dropShadow_2859_5300"
|
876 |
+
/>
|
877 |
+
<feOffset dy="8" />
|
878 |
+
<feGaussianBlur stdDeviation="6" />
|
879 |
+
<feComposite in2="hardAlpha" operator="out" />
|
880 |
+
<feColorMatrix
|
881 |
+
type="matrix"
|
882 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"
|
883 |
+
/>
|
884 |
+
<feBlend
|
885 |
+
mode="normal"
|
886 |
+
in2="BackgroundImageFix"
|
887 |
+
result="effect1_dropShadow_2859_5300"
|
888 |
+
/>
|
889 |
+
<feColorMatrix
|
890 |
+
in="SourceAlpha"
|
891 |
+
type="matrix"
|
892 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"
|
893 |
+
result="hardAlpha"
|
894 |
+
/>
|
895 |
+
<feMorphology
|
896 |
+
radius="3"
|
897 |
+
operator="erode"
|
898 |
+
in="SourceAlpha"
|
899 |
+
result="effect2_dropShadow_2859_5300"
|
900 |
+
/>
|
901 |
+
<feOffset dy="3" />
|
902 |
+
<feGaussianBlur stdDeviation="2.5" />
|
903 |
+
<feComposite in2="hardAlpha" operator="out" />
|
904 |
+
<feColorMatrix
|
905 |
+
type="matrix"
|
906 |
+
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.08 0"
|
907 |
+
/>
|
908 |
+
<feBlend
|
909 |
+
mode="normal"
|
910 |
+
in2="effect1_dropShadow_2859_5300"
|
911 |
+
result="effect2_dropShadow_2859_5300"
|
912 |
+
/>
|
913 |
+
<feBlend
|
914 |
+
mode="normal"
|
915 |
+
in="SourceGraphic"
|
916 |
+
in2="effect2_dropShadow_2859_5300"
|
917 |
+
result="shape"
|
918 |
+
/>
|
919 |
+
</filter>
|
920 |
+
<clipPath id="clip0_2859_5300">
|
921 |
+
<rect
|
922 |
+
width="20"
|
923 |
+
height="20"
|
924 |
+
fill="white"
|
925 |
+
transform="translate(15.9087 10.2917) rotate(-3.82708)"
|
926 |
+
/>
|
927 |
+
</clipPath>
|
928 |
+
</defs>
|
929 |
+
</svg>
|
930 |
+
)
|
931 |
+
}
|
932 |
+
|
933 |
+
export const ReasoningIcon: FC = ({ ...props }) => (
|
934 |
+
<svg
|
935 |
+
width="24"
|
936 |
+
height="24"
|
937 |
+
viewBox="0 0 24 24"
|
938 |
+
fill="none"
|
939 |
+
xmlns="http://www.w3.org/2000/svg"
|
940 |
+
{...props}
|
941 |
+
>
|
942 |
+
<rect width="24" height="24" rx="6" fill="#27272A" />
|
943 |
+
<g clipPath="url(#clip0_8154_2999)">
|
944 |
+
<path
|
945 |
+
d="M11.9999 7.00004C11.9999 6.78117 11.9568 6.56445 11.873 6.36224C11.7893 6.16003 11.6665 5.97629 11.5117 5.82153C11.357 5.66677 11.1732 5.544 10.971 5.46024C10.7688 5.37648 10.5521 5.33337 10.3332 5.33337C9.94409 5.33296 9.56708 5.46871 9.26754 5.71711C8.968 5.96551 8.76483 6.31089 8.69323 6.69337C8.47346 6.73455 8.26423 6.81952 8.07798 6.94323C7.89174 7.06694 7.73229 7.22686 7.60912 7.41347C7.48596 7.60008 7.40161 7.80956 7.36108 8.02944C7.32055 8.24933 7.32468 8.47512 7.37322 8.69338C7.07233 8.74679 6.79192 8.88191 6.56264 9.08395C6.33336 9.28599 6.16405 9.54718 6.07321 9.83897C5.98237 10.1308 5.97351 10.4419 6.04758 10.7384C6.12166 11.0349 6.27583 11.3053 6.49323 11.52C6.12758 11.6889 5.82141 11.9641 5.6148 12.3098C5.40819 12.6555 5.31075 13.0555 5.33525 13.4575C5.35974 13.8595 5.50502 14.2447 5.75208 14.5628C5.99914 14.8808 6.33646 15.1169 6.71989 15.24C6.64668 15.5166 6.6459 15.8074 6.71762 16.0843C6.78933 16.3613 6.93114 16.6151 7.12938 16.8214C7.32762 17.0277 7.57562 17.1795 7.84951 17.2621C8.12341 17.3448 8.41397 17.3555 8.69323 17.2934C8.76732 17.7026 8.99176 18.0694 9.32246 18.3216C9.65316 18.5739 10.0662 18.6933 10.4805 18.6566C10.8948 18.6198 11.2804 18.4295 11.5615 18.123C11.8426 17.8165 11.999 17.416 11.9999 17M11.9999 7.00004V17M11.9999 7.00004C11.9999 6.55801 12.1755 6.13409 12.488 5.82153C12.8006 5.50897 13.2245 5.33337 13.6666 5.33337C14.0557 5.33296 14.4327 5.46871 14.7322 5.71711C15.0318 5.96551 15.235 6.31089 15.3066 6.69337C15.5263 6.73455 15.7356 6.81952 15.9218 6.94323C16.108 7.06694 16.2675 7.22686 16.3907 7.41347C16.5138 7.60008 16.5982 7.80956 16.6387 8.02944C16.6792 8.24933 16.6751 8.47512 16.6266 8.69338C16.9275 8.74679 17.2079 8.88191 17.4371 9.08395C17.6664 9.28599 17.8357 9.54718 17.9266 9.83897C18.0174 10.1308 18.0263 10.4419 17.9522 10.7384C17.8781 11.0349 17.724 11.3053 17.5066 11.52C17.8722 11.6889 18.1784 11.9641 18.385 12.3098C18.5916 12.6555 18.689 13.0555 18.6645 13.4575C18.64 13.8595 18.4948 14.2447 18.2477 14.5628C18.0006 14.8808 17.6633 15.1169 17.2799 15.24C17.3531 15.5166 17.3539 15.8074 17.2822 16.0843C17.2105 16.3613 17.0686 16.6151 16.8704 16.8214C16.6722 17.0277 16.4242 17.1795 16.1503 17.2621C15.8764 17.3448 15.5858 17.3555 15.3066 17.2934C15.2325 17.7026 15.008 18.0694 14.6773 18.3216C14.3466 18.5739 13.9336 18.6933 13.5193 18.6566C13.105 18.6198 12.7194 18.4295 12.4383 18.123C12.1572 17.8165 12.0008 17.416 11.9999 17"
|
946 |
+
stroke="#FAFAFA"
|
947 |
+
strokeLinecap="round"
|
948 |
+
strokeLinejoin="round"
|
949 |
+
/>
|
950 |
+
</g>
|
951 |
+
<defs>
|
952 |
+
<clipPath id="clip0_8154_2999">
|
953 |
+
<rect width="16" height="16" fill="white" transform="translate(4 4)" />
|
954 |
+
</clipPath>
|
955 |
+
</defs>
|
956 |
+
</svg>
|
957 |
+
)
|
958 |
+
|
959 |
+
export const ReferencesIcon: FC = ({ ...props }) => (
|
960 |
+
<svg
|
961 |
+
width="24"
|
962 |
+
height="24"
|
963 |
+
viewBox="0 0 24 24"
|
964 |
+
fill="none"
|
965 |
+
xmlns="http://www.w3.org/2000/svg"
|
966 |
+
{...props}
|
967 |
+
>
|
968 |
+
<rect width="24" height="24" rx="6" fill="#27272A" />
|
969 |
+
<g clipPath="url(#clip0_8556_11986)">
|
970 |
+
<path
|
971 |
+
d="M10.6667 17.5089C8.60809 17.0124 6.9877 15.392 6.49124 13.3333M17.5092 13.3334C17.0127 15.392 15.3923 17.0124 13.3338 17.5089M13.3336 6.49109C15.3923 6.98757 17.0127 8.60799 17.5092 10.6666M6.49137 10.6667C6.98784 8.60803 8.60829 6.98757 10.667 6.49109M6.40016 13.3334H6.9335C7.30686 13.3334 7.49355 13.3334 7.63616 13.2607C7.7616 13.1968 7.86358 13.0948 7.9275 12.9694C8.00016 12.8268 8.00016 12.6401 8.00016 12.2667V11.7334C8.00016 11.36 8.00016 11.1733 7.9275 11.0307C7.86358 10.9053 7.7616 10.8033 7.63616 10.7394C7.49355 10.6667 7.30686 10.6667 6.9335 10.6667H6.40016C6.02679 10.6667 5.84011 10.6667 5.6975 10.7394C5.57206 10.8033 5.47007 10.9053 5.40616 11.0307C5.3335 11.1733 5.3335 11.36 5.3335 11.7334V12.2667C5.3335 12.6401 5.3335 12.8268 5.40616 12.9694C5.47007 13.0948 5.57206 13.1968 5.6975 13.2607C5.84011 13.3334 6.02679 13.3334 6.40016 13.3334ZM17.0668 13.3334H17.6002C17.9735 13.3334 18.1602 13.3334 18.3028 13.2607C18.4283 13.1968 18.5303 13.0948 18.5942 12.9694C18.6668 12.8268 18.6668 12.6401 18.6668 12.2667V11.7334C18.6668 11.36 18.6668 11.1733 18.5942 11.0307C18.5303 10.9053 18.4283 10.8033 18.3028 10.7394C18.1602 10.6667 17.9735 10.6667 17.6002 10.6667H17.0668C16.6935 10.6667 16.5068 10.6667 16.3642 10.7394C16.2387 10.8033 16.1367 10.9053 16.0728 11.0307C16.0002 11.1733 16.0002 11.36 16.0002 11.7334V12.2667C16.0002 12.6401 16.0002 12.8268 16.0728 12.9694C16.1367 13.0948 16.2387 13.1968 16.3642 13.2607C16.5068 13.3334 16.6935 13.3334 17.0668 13.3334ZM11.7335 8.00004H12.2668C12.6402 8.00004 12.8269 8.00004 12.9695 7.92738C13.0949 7.86346 13.1969 7.76148 13.2608 7.63603C13.3335 7.49343 13.3335 7.30674 13.3335 6.93337V6.40004C13.3335 6.02667 13.3335 5.83999 13.2608 5.69738C13.1969 5.57194 13.0949 5.46995 12.9695 5.40604C12.8269 5.33337 12.6402 5.33337 12.2668 5.33337H11.7335C11.3601 5.33337 11.1734 5.33337 11.0308 5.40604C10.9054 5.46995 10.8034 5.57194 10.7395 5.69738C10.6668 5.83999 10.6668 6.02667 10.6668 6.40004V6.93337C10.6668 7.30674 10.6668 7.49343 10.7395 7.63603C10.8034 7.76148 10.9054 7.86346 11.0308 7.92738C11.1734 8.00004 11.3601 8.00004 11.7335 8.00004ZM11.7335 18.6667H12.2668C12.6402 18.6667 12.8269 18.6667 12.9695 18.594C13.0949 18.5301 13.1969 18.4281 13.2608 18.3027C13.3335 18.1601 13.3335 17.9734 13.3335 17.6V17.0667C13.3335 16.6933 13.3335 16.5067 13.2608 16.364C13.1969 16.2386 13.0949 16.1366 12.9695 16.0727C12.8269 16 12.6402 16 12.2668 16H11.7335C11.3601 16 11.1734 16 11.0308 16.0727C10.9054 16.1366 10.8034 16.2386 10.7395 16.364C10.6668 16.5067 10.6668 16.6933 10.6668 17.0667V17.6C10.6668 17.9734 10.6668 18.1601 10.7395 18.3027C10.8034 18.4281 10.9054 18.5301 11.0308 18.594C11.1734 18.6667 11.3601 18.6667 11.7335 18.6667Z"
|
972 |
+
stroke="#FAFAFA"
|
973 |
+
strokeLinecap="round"
|
974 |
+
strokeLinejoin="round"
|
975 |
+
/>
|
976 |
+
</g>
|
977 |
+
<defs>
|
978 |
+
<clipPath id="clip0_8556_11986">
|
979 |
+
<rect width="16" height="16" fill="white" transform="translate(4 4)" />
|
980 |
+
</clipPath>
|
981 |
+
</defs>
|
982 |
+
</svg>
|
983 |
+
)
|