θΏ™ζ˜―indexlocζδΎ›ηš„ζœεŠ‘οΌŒδΈθ¦θΎ“ε…₯任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions frontend/jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"target": "esnext",
"jsx": "react",
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
}
}
}
}
5 changes: 5 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const AdminInvites = lazy(() => import("@/pages/Admin/Invitations"));
const AdminWorkspaces = lazy(() => import("@/pages/Admin/Workspaces"));
const AdminSystem = lazy(() => import("@/pages/Admin/System"));
const AdminLogs = lazy(() => import("@/pages/Admin/Logging"));
const AdminAgents = lazy(() => import("@/pages/Admin/Agents"));
const GeneralChats = lazy(() => import("@/pages/GeneralSettings/Chats"));
const GeneralAppearance = lazy(
() => import("@/pages/GeneralSettings/Appearance")
Expand Down Expand Up @@ -106,6 +107,10 @@ export default function App() {
path="/settings/vector-database"
element={<AdminRoute Component={GeneralVectorDatabase} />}
/>
<Route
path="/settings/agents"
element={<AdminRoute Component={AdminAgents} />}
/>
<Route
path="/settings/event-logs"
element={<AdminRoute Component={AdminLogs} />}
Expand Down
32 changes: 32 additions & 0 deletions frontend/src/components/ContextualSaveBar/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Warning } from "@phosphor-icons/react";

export default function ContextualSaveBar({
showing = false,
onSave,
onCancel,
}) {
if (!showing) return null;

return (
<div className="fixed top-0 left-0 right-0 h-14 bg-[#18181B] flex items-center justify-end px-4 z-[9999]">
<div className="absolute left-1/2 transform -translate-x-1/2 flex items-center gap-x-2">
<Warning size={18} className="text-white" />
<p className="text-white font-medium text-xs">Unsaved Changes</p>
</div>
<div className="flex items-center gap-x-2">
<button
className="border-none text-white font-medium text-sm px-[10px] py-[6px] rounded-md bg-white/5 hover:bg-white/10"
onClick={onCancel}
>
Cancel
</button>
<button
className="border-none text-[#222628] font-medium text-sm px-[10px] py-[6px] rounded-md bg-[#46C8FF] hover:bg-[#3DB5E8]"
onClick={onSave}
>
Save
</button>
</div>
</div>
);
}
10 changes: 10 additions & 0 deletions frontend/src/components/SettingsSidebar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
EyeSlash,
SplitVertical,
Microphone,
Robot,
} from "@phosphor-icons/react";
import useUser from "@/hooks/useUser";
import { USER_BACKGROUND_COLOR } from "@/utils/constants";
Expand Down Expand Up @@ -258,6 +259,15 @@ const SidebarOptions = ({ user = null }) => (
flex={true}
allowedRole={["admin", "manager"]}
/>

<Option
href={paths.settings.agentSkills()}
btnText="Agent Skills"
icon={<Robot className="h-5 w-5 flex-shrink-0" />}
user={user}
flex={true}
allowedRole={["admin", "manager"]}
/>
<Option
href={paths.settings.appearance()}
btnText="Appearance"
Expand Down
Binary file added frontend/src/media/agents/generate-charts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/media/agents/rag-memory.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/media/agents/scrape-websites.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/media/agents/sql-agent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/media/agents/view-summarize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions frontend/src/pages/Admin/Agents/Badges/default.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Tooltip } from "react-tooltip";

export function DefaultBadge({ title }) {
return (
<>
<span
className="w-fit"
data-tooltip-id={`default-skill-${title}`}
data-tooltip-content="This skill is enabled by default and cannot be turned off."
>
<div className="flex items-center gap-x-1 w-fit rounded-full bg-[#F4FFD0]/10 px-2.5 py-0.5 text-sm font-medium text-sky-400 shadow-sm cursor-pointer">
<div className="text-[#F4FFD0] text-[12px] leading-[15px]">
Default
</div>
</div>
</span>
<Tooltip
id={`default-skill-${title}`}
place="bottom"
delayShow={300}
className="tooltip !text-xs"
/>
</>
);
}
29 changes: 29 additions & 0 deletions frontend/src/pages/Admin/Agents/DefaultSkillPanel/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import { DefaultBadge } from "../Badges/default";

export default function DefaultSkillPanel({ title, description, image, icon }) {
return (
<div className="p-2">
<div className="flex flex-col gap-y-[18px] max-w-[500px]">
<div className="flex w-full justify-between items-center">
<div className="flex items-center gap-x-2">
{icon &&
React.createElement(icon, {
size: 24,
color: "white",
weight: "bold",
})}
<label htmlFor="name" className="text-white text-md font-bold">
{title}
</label>
<DefaultBadge title={title} />
</div>
</div>
<img src={image} alt={title} className="w-full rounded-md" />
<p className="text-white text-opacity-60 text-xs font-medium py-1.5">
{description}
</p>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
import React from "react";
export default function GenericSkill({

export default function GenericSkillPanel({
title,
description,
skill,
toggleSkill,
enabled = false,
disabled = false,
image,
icon,
}) {
return (
<div className="border-b border-white/40 pb-4">
<div className="flex flex-col">
<div className="flex w-full justify-between items-center">
<label htmlFor="name" className="block input-label">
<div className="p-2">
<div className="flex flex-col gap-y-[18px] max-w-[500px]">
<div className="flex items-center gap-x-2">
{icon &&
React.createElement(icon, {
size: 24,
color: "white",
weight: "bold",
})}
<label htmlFor="name" className="text-white text-md font-bold">
{title}
</label>
<label
className={`border-none relative inline-flex items-center mt-2 ${
className={`border-none relative inline-flex items-center ml-auto ${
disabled ? "cursor-not-allowed" : "cursor-pointer"
}`}
>
Expand All @@ -24,12 +33,13 @@ export default function GenericSkill({
disabled={disabled}
className="peer sr-only"
checked={enabled}
onClick={() => toggleSkill(skill)}
onChange={() => toggleSkill(skill)}
/>
<div className="peer-disabled:opacity-50 pointer-events-none peer h-6 w-11 rounded-full bg-stone-400 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:shadow-xl after:border after:border-gray-600 after:bg-white after:box-shadow-md after:transition-all after:content-[''] peer-checked:bg-lime-300 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800"></div>
<span className="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300"></span>
</label>
</div>
<img src={image} alt={title} className="w-full rounded-md" />
<p className="text-white text-opacity-60 text-xs font-medium py-1.5">
{description}
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ export default function NewSQLConnection({ isOpen, closeModal, onSubmit }) {
// to the parent container form so we don't have nested forms.
return createPortal(
<ModalWrapper isOpen={isOpen}>
<div className="relative w-1/3 max-h-full ">
<div className="relative bg-main-gradient rounded-xl shadow-[0_4px_14px_rgba(0,0,0,0.25)] max-h-[90vh] overflow-y-scroll no-scroll">
<div className="relative w-1/3 max-h-full mt-8">
<div className="relative bg-main-gradient rounded-xl shadow-[0_4px_14px_rgba(0,0,0,0.25)] max-h-[85vh] overflow-y-scroll no-scroll">
<div className="flex items-start justify-between p-4 border-b rounded-t border-gray-500/50">
<h3 className="text-xl font-semibold text-white">
New SQL Connection
Expand Down
117 changes: 117 additions & 0 deletions frontend/src/pages/Admin/Agents/SQLConnectorSelection/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import React, { useState } from "react";
import DBConnection from "./DBConnection";
import { Plus, Database } from "@phosphor-icons/react";
import NewSQLConnection from "./NewConnectionModal";
import { useModal } from "@/hooks/useModal";
import SQLAgentImage from "@/media/agents/sql-agent.png";

export default function AgentSQLConnectorSelection({
skill,
settings,
toggleSkill,
enabled = false,
setHasChanges,
}) {
const { isOpen, openModal, closeModal } = useModal();
const [connections, setConnections] = useState(
settings?.preferences?.agent_sql_connections || []
);
return (
<>
<div className="p-2">
<div className="flex flex-col gap-y-[18px] max-w-[500px]">
<div className="flex items-center gap-x-2">
<Database size={24} color="white" weight="bold" />
<label htmlFor="name" className="text-white text-md font-bold">
SQL Agent
</label>
<label className="border-none relative inline-flex cursor-pointer items-center ml-auto">
<input
type="checkbox"
className="peer sr-only"
checked={enabled}
onChange={() => toggleSkill(skill)}
/>
<div className="pointer-events-none peer h-6 w-11 rounded-full bg-stone-400 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:shadow-xl after:border after:border-gray-600 after:bg-white after:box-shadow-md after:transition-all after:content-[''] peer-checked:bg-lime-300 peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-800"></div>
<span className="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300"></span>
</label>
</div>
<img
src={SQLAgentImage}
alt="SQL Agent"
className="w-full rounded-md"
/>
<p className="text-white text-opacity-60 text-xs font-medium py-1.5">
Enable your agent to be able to leverage SQL to answer you questions
by connecting to various SQL database providers.
</p>
{enabled && (
<>
<input
name="system::agent_sql_connections"
type="hidden"
value={JSON.stringify(connections)}
/>
<input
type="hidden"
value={JSON.stringify(
connections.filter((conn) => conn.action !== "remove")
)}
/>
<div className="flex flex-col mt-2 gap-y-2">
<p className="text-white font-semibold text-sm">
Your database connections
</p>
<div className="flex flex-col gap-y-3">
{connections
.filter((connection) => connection.action !== "remove")
.map((connection) => (
<DBConnection
key={connection.database_id}
connection={connection}
onRemove={(databaseId) => {
setHasChanges(true);
setConnections((prev) =>
prev.map((conn) => {
if (conn.database_id === databaseId)
return { ...conn, action: "remove" };
return conn;
})
);
}}
/>
))}
<button
type="button"
onClick={openModal}
className="w-fit relative flex h-[40px] items-center border-none hover:bg-slate-600/20 rounded-lg"
>
<div className="flex w-full gap-x-2 items-center p-4">
<div className="bg-zinc-600 p-2 rounded-lg h-[24px] w-[24px] flex items-center justify-center">
<Plus
weight="bold"
size={14}
className="shrink-0 text-slate-100"
/>
</div>
<p className="text-left text-slate-100 text-sm">
New SQL connection
</p>
</div>
</button>
</div>
</div>
</>
)}
</div>
</div>
<NewSQLConnection
isOpen={isOpen}
closeModal={closeModal}
onSubmit={(newDb) =>
setConnections((prev) => [...prev, { action: "add", ...newDb }])
}
/>
</>
);
}
Loading