From b7a6bad7cdf2a807059b3929f49f9289c8842672 Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Tue, 27 May 2025 13:50:13 +0530 Subject: [PATCH 01/16] fix: minor bugs and route errors --- application/api/user/routes.py | 5 ++++- application/requirements.txt | 4 ++-- frontend/src/App.tsx | 6 ++++-- frontend/src/agents/SharedAgentGate.tsx | 7 +++++++ 4 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 frontend/src/agents/SharedAgentGate.tsx diff --git a/application/api/user/routes.py b/application/api/user/routes.py index ae653c39..60277132 100644 --- a/application/api/user/routes.py +++ b/application/api/user/routes.py @@ -1500,7 +1500,10 @@ class PinnedAgents(Resource): "description": agent.get("description", ""), "source": ( str(db.dereference(agent["source"])["_id"]) - if "source" in agent and isinstance(agent["source"], DBRef) + if "source" in agent + and agent["source"] + and isinstance(agent["source"], DBRef) + and db.dereference(agent["source"]) is not None else "" ), "chunks": agent.get("chunks", ""), diff --git a/application/requirements.txt b/application/requirements.txt index 3891c852..3778d941 100644 --- a/application/requirements.txt +++ b/application/requirements.txt @@ -46,7 +46,7 @@ pandas==2.2.3 openpyxl==3.1.5 pathable==0.4.4 pillow==11.1.0 -portalocker==3.1.1 +portalocker>=2.7.0,<3.0.0 prance==23.6.21.0 prompt-toolkit==3.0.51 protobuf==5.29.3 @@ -62,7 +62,7 @@ python-dotenv==1.0.1 python-jose==3.4.0 python-pptx==1.0.2 redis==5.2.1 -referencing==0.36.2 +referencing>=0.28.0,<0.31.0 regex==2024.11.6 requests==2.32.3 retry==0.9.2 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 1bba5f44..b3604c46 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4,6 +4,9 @@ import { useState } from 'react'; import { Outlet, Route, Routes } from 'react-router-dom'; import About from './About'; +import Agents from './agents'; +import SharedAgentGate from './agents/SharedAgentGate'; +import ActionButtons from './components/ActionButtons'; import Spinner from './components/Spinner'; import Conversation from './conversation/Conversation'; import { SharedConversation } from './conversation/SharedConversation'; @@ -12,8 +15,6 @@ import useTokenAuth from './hooks/useTokenAuth'; import Navigation from './Navigation'; import PageNotFound from './PageNotFound'; import Setting from './settings'; -import Agents from './agents'; -import ActionButtons from './components/ActionButtons'; function AuthWrapper({ children }: { children: React.ReactNode }) { const { isAuthLoading } = useTokenAuth(); @@ -69,6 +70,7 @@ export default function App() { } /> } /> + } /> } /> diff --git a/frontend/src/agents/SharedAgentGate.tsx b/frontend/src/agents/SharedAgentGate.tsx new file mode 100644 index 00000000..877b6b1f --- /dev/null +++ b/frontend/src/agents/SharedAgentGate.tsx @@ -0,0 +1,7 @@ +import { Navigate, useParams } from 'react-router-dom'; + +export default function SharedAgentGate() { + const { agentId } = useParams(); + + return ; +} From ad1a944276b9e5118bc7257c5983d051cd0971af Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Wed, 28 May 2025 13:58:55 +0530 Subject: [PATCH 02/16] refactor: agents sharing and shared with me logic --- application/api/user/routes.py | 157 +++++++++++++---------- frontend/src/agents/SharedAgent.tsx | 63 +-------- frontend/src/agents/SharedAgentCard.tsx | 64 +++++++++ frontend/src/agents/index.tsx | 5 +- frontend/src/api/endpoints.ts | 2 +- frontend/src/api/services/userService.ts | 4 +- 6 files changed, 158 insertions(+), 137 deletions(-) create mode 100644 frontend/src/agents/SharedAgentCard.tsx diff --git a/application/api/user/routes.py b/application/api/user/routes.py index 60277132..32d76fd7 100644 --- a/application/api/user/routes.py +++ b/application/api/user/routes.py @@ -15,6 +15,7 @@ from flask_restx import fields, inputs, Namespace, Resource from werkzeug.utils import secure_filename from application.agents.tools.tool_manager import ToolManager +from pymongo import ReturnDocument from application.api.user.tasks import ( ingest, @@ -50,6 +51,7 @@ agents_collection.create_index( name="shared_index", background=True, ) +users_collection.create_index("user_id", unique=True) user = Blueprint("user", __name__) user_ns = Namespace("user", description="User related operations", path="/") @@ -85,29 +87,29 @@ def generate_date_range(start_date, end_date): def ensure_user_doc(user_id): - user_doc = users_collection.find_one({"user_id": user_id}) + default_prefs = { + "pinned": [], + "shared_with_me": [], + } - if not user_doc: - user_doc = { - "user_id": user_id, - "agent_preferences": {"pinned": [], "hidden_shared": []}, - } - users_collection.insert_one(user_doc) - return user_doc - updated = False - preferences = user_doc.get("agent_preferences", {}) + user_doc = users_collection.find_one_and_update( + {"user_id": user_id}, + {"$setOnInsert": {"agent_preferences": default_prefs}}, + upsert=True, + return_document=ReturnDocument.AFTER, + ) + + prefs = user_doc.get("agent_preferences", {}) + updates = {} + if "pinned" not in prefs: + updates["agent_preferences.pinned"] = [] + if "shared_with_me" not in prefs: + updates["agent_preferences.shared_with_me"] = [] + + if updates: + users_collection.update_one({"user_id": user_id}, {"$set": updates}) + user_doc = users_collection.find_one({"user_id": user_id}) - if "pinned" not in preferences: - preferences["pinned"] = [] - updated = True - if "hidden_shared" not in preferences: - preferences["hidden_shared"] = [] - updated = True - if updated: - users_collection.update_one( - {"user_id": user_id}, {"$set": {"agent_preferences": preferences}} - ) - user_doc["agent_preferences"] = preferences return user_doc @@ -1464,26 +1466,25 @@ class PinnedAgents(Resource): decoded_token = request.decoded_token if not decoded_token: return make_response(jsonify({"success": False}), 401) + user_id = decoded_token.get("sub") try: user_doc = ensure_user_doc(user_id) pinned_ids = user_doc.get("agent_preferences", {}).get("pinned", []) - hidden_ids = set( - user_doc.get("agent_preferences", {}).get("hidden_shared", []) - ) if not pinned_ids: return make_response(jsonify([]), 200) + pinned_object_ids = [ObjectId(agent_id) for agent_id in pinned_ids] + pinned_agents_cursor = agents_collection.find( {"_id": {"$in": pinned_object_ids}} ) pinned_agents = list(pinned_agents_cursor) + existing_ids = {str(agent["_id"]) for agent in pinned_agents} - existing_agents = pinned_agents - existing_ids = {str(agent["_id"]) for agent in existing_agents} - + # Clean up any stale pinned IDs stale_ids = [ agent_id for agent_id in pinned_ids if agent_id not in existing_ids ] @@ -1523,12 +1524,13 @@ class PinnedAgents(Resource): "pinned": True, } for agent in pinned_agents - if ("source" in agent or "retriever" in agent) - and str(agent["_id"]) not in hidden_ids + if "source" in agent or "retriever" in agent ] + except Exception as err: current_app.logger.error(f"Error retrieving pinned agents: {err}") return make_response(jsonify({"success": False}), 400) + return make_response(jsonify(list_pinned_agents), 200) @@ -1575,11 +1577,11 @@ class PinAgent(Resource): return make_response(jsonify({"success": True, "action": action}), 200) -@user_ns.route("/api/hide_shared_agent") -class HideSharedAgent(Resource): +@user_ns.route("/api/remove_shared_agent") +class RemoveSharedAgent(Resource): @api.doc( params={"id": "ID of the shared agent"}, - description="Hide or unhide a shared agent for the current user", + description="Remove a shared agent from the current user's shared list", ) def delete(self): decoded_token = request.decoded_token @@ -1592,6 +1594,7 @@ class HideSharedAgent(Resource): return make_response( jsonify({"success": False, "message": "ID is required"}), 400 ) + try: agent = agents_collection.find_one( {"_id": ObjectId(agent_id), "shared_publicly": True} @@ -1601,27 +1604,25 @@ class HideSharedAgent(Resource): jsonify({"success": False, "message": "Shared agent not found"}), 404, ) - user_doc = ensure_user_doc(user_id) - hidden_list = user_doc.get("agent_preferences", {}).get("hidden_shared", []) - if agent_id in hidden_list: - users_collection.update_one( - {"user_id": user_id}, - {"$pull": {"agent_preferences.hidden_shared": agent_id}}, - ) - action = "unhidden" - else: - users_collection.update_one( - {"user_id": user_id}, - {"$addToSet": {"agent_preferences.hidden_shared": agent_id}}, - ) - action = "hidden" + ensure_user_doc(user_id) + users_collection.update_one( + {"user_id": user_id}, + { + "$pull": { + "agent_preferences.shared_with_me": agent_id, + "agent_preferences.pinned": agent_id, + } + }, + ) + + return make_response(jsonify({"success": True, "action": "removed"}), 200) + except Exception as err: - current_app.logger.error(f"Error hiding/unhiding shared agent: {err}") + current_app.logger.error(f"Error removing shared agent: {err}") return make_response( jsonify({"success": False, "message": "Server error"}), 500 ) - return make_response(jsonify({"success": True, "action": action}), 200) @user_ns.route("/api/shared_agent") @@ -1639,19 +1640,22 @@ class SharedAgent(Resource): return make_response( jsonify({"success": False, "message": "Token or ID is required"}), 400 ) - try: - query = {} - query["shared_publicly"] = True - query["shared_token"] = shared_token + try: + query = { + "shared_publicly": True, + "shared_token": shared_token, + } shared_agent = agents_collection.find_one(query) if not shared_agent: return make_response( jsonify({"success": False, "message": "Shared agent not found"}), 404, ) + + agent_id = str(shared_agent["_id"]) data = { - "id": str(shared_agent["_id"]), + "id": agent_id, "user": shared_agent.get("user", ""), "name": shared_agent.get("name", ""), "description": shared_agent.get("description", ""), @@ -1672,15 +1676,29 @@ class SharedAgent(Resource): if tool_data: enriched_tools.append(tool_data.get("name", "")) data["tools"] = enriched_tools + + decoded_token = getattr(request, "decoded_token", None) + if decoded_token: + user_id = decoded_token.get("sub") + owner_id = shared_agent.get("user") + + if user_id != owner_id: + ensure_user_doc(user_id) + users_collection.update_one( + {"user_id": user_id}, + {"$addToSet": {"agent_preferences.shared_with_me": agent_id}}, + ) + + return make_response(jsonify(data), 200) + except Exception as err: current_app.logger.error(f"Error retrieving shared agent: {err}") return make_response(jsonify({"success": False}), 400) - return make_response(jsonify(data), 200) @user_ns.route("/api/shared_agents") class SharedAgents(Resource): - @api.doc(description="Get shared agents") + @api.doc(description="Get shared agents explicitly shared with the user") def get(self): try: decoded_token = request.decoded_token @@ -1689,29 +1707,25 @@ class SharedAgents(Resource): user_id = decoded_token.get("sub") user_doc = ensure_user_doc(user_id) - pinned_ids = set(user_doc.get("agent_preferences", {}).get("pinned", [])) - hidden_ids = user_doc.get("agent_preferences", {}).get("hidden_shared", []) - hidden_object_ids = [ObjectId(id) for id in hidden_ids] + shared_with_ids = user_doc.get("agent_preferences", {}).get( + "shared_with_me", [] + ) + shared_object_ids = [ObjectId(id) for id in shared_with_ids] shared_agents_cursor = agents_collection.find( - {"shared_publicly": True, "user": {"$ne": user_id}} + {"_id": {"$in": shared_object_ids}, "shared_publicly": True} ) shared_agents = list(shared_agents_cursor) - shared_ids_set = {agent["_id"] for agent in shared_agents} - hidden_ids_set = set(hidden_object_ids) - - stale_hidden_ids = [ - str(id) for id in hidden_ids_set if id not in shared_ids_set - ] - if stale_hidden_ids: + found_ids_set = {str(agent["_id"]) for agent in shared_agents} + stale_ids = [id for id in shared_with_ids if id not in found_ids_set] + if stale_ids: users_collection.update_one( {"user_id": user_id}, - {"$pullAll": {"agent_preferences.hidden_shared": stale_hidden_ids}}, + {"$pullAll": {"agent_preferences.shared_with_me": stale_ids}}, ) - visible_shared_agents = [ - agent for agent in shared_agents if agent["_id"] not in hidden_ids_set - ] + + pinned_ids = set(user_doc.get("agent_preferences", {}).get("pinned", [])) list_shared_agents = [ { @@ -1728,10 +1742,11 @@ class SharedAgents(Resource): "shared_token": agent.get("shared_token", ""), "shared_metadata": agent.get("shared_metadata", {}), } - for agent in visible_shared_agents + for agent in shared_agents ] return make_response(jsonify(list_shared_agents), 200) + except Exception as err: current_app.logger.error(f"Error retrieving shared agents: {err}") return make_response(jsonify({"success": False}), 400) diff --git a/frontend/src/agents/SharedAgent.tsx b/frontend/src/agents/SharedAgent.tsx index 8c7e76c9..d1d2d370 100644 --- a/frontend/src/agents/SharedAgent.tsx +++ b/frontend/src/agents/SharedAgent.tsx @@ -21,6 +21,7 @@ import { import { useDarkTheme } from '../hooks'; import { selectToken, setSelectedAgent } from '../preferences/preferenceSlice'; import { AppDispatch } from '../store'; +import SharedAgentCard from './SharedAgentCard'; import { Agent } from './types'; export default function SharedAgent() { @@ -193,65 +194,3 @@ export default function SharedAgent() { ); } - -function SharedAgentCard({ agent }: { agent: Agent }) { - return ( -
-
-
- -
-
-

- {agent.name} -

-

- {agent.description} -

-
-
-
- {agent.shared_metadata?.shared_by && ( -

- by {agent.shared_metadata.shared_by} -

- )} - {agent.shared_metadata?.shared_at && ( -

- Shared on{' '} - {new Date(agent.shared_metadata.shared_at).toLocaleString('en-US', { - month: 'long', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - hour12: true, - })} -

- )} -
- {agent.tools.length > 0 && ( -
-

- Connected Tools -

-
- {agent.tools.map((tool, index) => ( - - {`${tool}{' '} - {tool} - - ))} -
-
- )} -
- ); -} diff --git a/frontend/src/agents/SharedAgentCard.tsx b/frontend/src/agents/SharedAgentCard.tsx new file mode 100644 index 00000000..9c8160e5 --- /dev/null +++ b/frontend/src/agents/SharedAgentCard.tsx @@ -0,0 +1,64 @@ +import Robot from '../assets/robot.svg'; +import { Agent } from './types'; + +export default function SharedAgentCard({ agent }: { agent: Agent }) { + return ( +
+
+
+ +
+
+

+ {agent.name} +

+

+ {agent.description} +

+
+
+
+ {agent.shared_metadata?.shared_by && ( +

+ by {agent.shared_metadata.shared_by} +

+ )} + {agent.shared_metadata?.shared_at && ( +

+ Shared on{' '} + {new Date(agent.shared_metadata.shared_at).toLocaleString('en-US', { + month: 'long', + day: 'numeric', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + hour12: true, + })} +

+ )} +
+ {agent.tools.length > 0 && ( +
+

+ Connected Tools +

+
+ {agent.tools.map((tool, index) => ( + + {`${tool}{' '} + {tool} + + ))} +
+
+ )} +
+ ); +} diff --git a/frontend/src/agents/index.tsx b/frontend/src/agents/index.tsx index 2f8bf484..8fe1afc9 100644 --- a/frontend/src/agents/index.tsx +++ b/frontend/src/agents/index.tsx @@ -286,7 +286,10 @@ function AgentCard({ const handleHideSharedAgent = async () => { try { - const response = await userService.hideSharedAgent(agent.id ?? '', token); + const response = await userService.removeSharedAgent( + agent.id ?? '', + token, + ); if (!response.ok) throw new Error('Failed to hide shared agent'); const updatedAgents = agents.filter( (prevAgent) => prevAgent.id !== agent.id, diff --git a/frontend/src/api/endpoints.ts b/frontend/src/api/endpoints.ts index 72db0595..bb98f02a 100644 --- a/frontend/src/api/endpoints.ts +++ b/frontend/src/api/endpoints.ts @@ -18,7 +18,7 @@ const endpoints = { SHARED_AGENT: (id: string) => `/api/shared_agent?token=${id}`, SHARED_AGENTS: '/api/shared_agents', SHARE_AGENT: `/api/share_agent`, - HIDE_SHARED_AGENT: (id: string) => `/api/hide_shared_agent?id=${id}`, + REMOVE_SHARED_AGENT: (id: string) => `/api/remove_shared_agent?id=${id}`, AGENT_WEBHOOK: (id: string) => `/api/agent_webhook?id=${id}`, PROMPTS: '/api/get_prompts', CREATE_PROMPT: '/api/create_prompt', diff --git a/frontend/src/api/services/userService.ts b/frontend/src/api/services/userService.ts index 9dd679a5..564c3b97 100644 --- a/frontend/src/api/services/userService.ts +++ b/frontend/src/api/services/userService.ts @@ -41,8 +41,8 @@ const userService = { apiClient.get(endpoints.USER.SHARED_AGENTS, token), shareAgent: (data: any, token: string | null): Promise => apiClient.put(endpoints.USER.SHARE_AGENT, data, token), - hideSharedAgent: (id: string, token: string | null): Promise => - apiClient.delete(endpoints.USER.HIDE_SHARED_AGENT(id), token), + removeSharedAgent: (id: string, token: string | null): Promise => + apiClient.delete(endpoints.USER.REMOVE_SHARED_AGENT(id), token), getAgentWebhook: (id: string, token: string | null): Promise => apiClient.get(endpoints.USER.AGENT_WEBHOOK(id), token), getPrompts: (token: string | null): Promise => From 8cd41956571c96e483fd5c8738e391d3fd0abfb4 Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Wed, 28 May 2025 14:25:37 +0530 Subject: [PATCH 03/16] feat: add SharedAgentCard to display selected agent in Conversation component --- frontend/src/conversation/Conversation.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/conversation/Conversation.tsx b/frontend/src/conversation/Conversation.tsx index 753a3725..4f34c26c 100644 --- a/frontend/src/conversation/Conversation.tsx +++ b/frontend/src/conversation/Conversation.tsx @@ -3,6 +3,7 @@ import { useDropzone } from 'react-dropzone'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; +import SharedAgentCard from '../agents/SharedAgentCard'; import DragFileUpload from '../assets/DragFileUpload.svg'; import MessageInput from '../components/MessageInput'; import { useMediaQuery } from '../hooks'; @@ -193,6 +194,14 @@ export default function Conversation() { handleFeedback={handleFeedback} queries={queries} status={status} + showHeroOnEmpty={selectedAgent ? false : true} + headerContent={ + selectedAgent ? ( +
+ +
+ ) : undefined + } />
From 3b8733e0855be59f3a17e1659856954a5ba44b7a Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Thu, 29 May 2025 10:58:49 +0530 Subject: [PATCH 04/16] feat: add tool details resolution and update SharedAgentCard to display tool names --- application/api/user/routes.py | 19 +++++++++++++++++++ frontend/src/agents/SharedAgentCard.tsx | 10 +++++----- frontend/src/agents/types/index.ts | 7 +++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/application/api/user/routes.py b/application/api/user/routes.py index 32d76fd7..5c9975fb 100644 --- a/application/api/user/routes.py +++ b/application/api/user/routes.py @@ -113,6 +113,20 @@ def ensure_user_doc(user_id): return user_doc +def resolve_tool_details(tool_ids): + tools = user_tools_collection.find( + {"_id": {"$in": [ObjectId(tid) for tid in tool_ids]}} + ) + return [ + { + "id": str(tool["_id"]), + "name": tool.get("name", ""), + "display_name": tool.get("displayName", tool.get("name", "")), + } + for tool in tools + ] + + def get_vector_store(source_id): """ Get the Vector Store @@ -1059,6 +1073,7 @@ class GetAgent(Resource): "retriever": agent.get("retriever", ""), "prompt_id": agent.get("prompt_id", ""), "tools": agent.get("tools", []), + "tool_details": resolve_tool_details(agent.get("tools", [])), "agent_type": agent.get("agent_type", ""), "status": agent.get("status", ""), "created_at": agent.get("createdAt", ""), @@ -1108,6 +1123,7 @@ class GetAgents(Resource): "retriever": agent.get("retriever", ""), "prompt_id": agent.get("prompt_id", ""), "tools": agent.get("tools", []), + "tool_details": resolve_tool_details(agent.get("tools", [])), "agent_type": agent.get("agent_type", ""), "status": agent.get("status", ""), "created_at": agent.get("createdAt", ""), @@ -1511,6 +1527,7 @@ class PinnedAgents(Resource): "retriever": agent.get("retriever", ""), "prompt_id": agent.get("prompt_id", ""), "tools": agent.get("tools", []), + "tool_details": resolve_tool_details(agent.get("tools", [])), "agent_type": agent.get("agent_type", ""), "status": agent.get("status", ""), "created_at": agent.get("createdAt", ""), @@ -1660,6 +1677,7 @@ class SharedAgent(Resource): "name": shared_agent.get("name", ""), "description": shared_agent.get("description", ""), "tools": shared_agent.get("tools", []), + "tool_details": resolve_tool_details(shared_agent.get("tools", [])), "agent_type": shared_agent.get("agent_type", ""), "status": shared_agent.get("status", ""), "created_at": shared_agent.get("createdAt", ""), @@ -1733,6 +1751,7 @@ class SharedAgents(Resource): "name": agent.get("name", ""), "description": agent.get("description", ""), "tools": agent.get("tools", []), + "tool_details": resolve_tool_details(agent.get("tools", [])), "agent_type": agent.get("agent_type", ""), "status": agent.get("status", ""), "created_at": agent.get("createdAt", ""), diff --git a/frontend/src/agents/SharedAgentCard.tsx b/frontend/src/agents/SharedAgentCard.tsx index 9c8160e5..6c778ba4 100644 --- a/frontend/src/agents/SharedAgentCard.tsx +++ b/frontend/src/agents/SharedAgentCard.tsx @@ -37,23 +37,23 @@ export default function SharedAgentCard({ agent }: { agent: Agent }) {

)}
- {agent.tools.length > 0 && ( + {agent.tool_details && agent.tool_details.length > 0 && (

Connected Tools

- {agent.tools.map((tool, index) => ( + {agent.tool_details.map((tool, index) => ( {`${tool}{' '} - {tool} + {tool.name} ))}
diff --git a/frontend/src/agents/types/index.ts b/frontend/src/agents/types/index.ts index fe3cb418..4a1af145 100644 --- a/frontend/src/agents/types/index.ts +++ b/frontend/src/agents/types/index.ts @@ -1,3 +1,9 @@ +export type ToolSummary = { + id: string; + name: string; + display_name: string; +}; + export type Agent = { id?: string; name: string; @@ -8,6 +14,7 @@ export type Agent = { retriever: string; prompt_id: string; tools: string[]; + tool_details?: ToolSummary[]; agent_type: string; status: string; key?: string; From c4e471ac478bfd46e63486c3d2da2d78db1ed9b6 Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Thu, 29 May 2025 11:16:38 +0530 Subject: [PATCH 05/16] fix: ensure shared metadata is displayed only when available in SharedAgentCard --- frontend/src/agents/SharedAgentCard.tsx | 45 ++++++++++++++----------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/frontend/src/agents/SharedAgentCard.tsx b/frontend/src/agents/SharedAgentCard.tsx index 6c778ba4..bf542ca9 100644 --- a/frontend/src/agents/SharedAgentCard.tsx +++ b/frontend/src/agents/SharedAgentCard.tsx @@ -17,26 +17,31 @@ export default function SharedAgentCard({ agent }: { agent: Agent }) {

-
- {agent.shared_metadata?.shared_by && ( -

- by {agent.shared_metadata.shared_by} -

- )} - {agent.shared_metadata?.shared_at && ( -

- Shared on{' '} - {new Date(agent.shared_metadata.shared_at).toLocaleString('en-US', { - month: 'long', - day: 'numeric', - year: 'numeric', - hour: '2-digit', - minute: '2-digit', - hour12: true, - })} -

- )} -
+ {agent.shared_metadata && ( +
+ {agent.shared_metadata?.shared_by && ( +

+ by {agent.shared_metadata.shared_by} +

+ )} + {agent.shared_metadata?.shared_at && ( +

+ Shared on{' '} + {new Date(agent.shared_metadata.shared_at).toLocaleString( + 'en-US', + { + month: 'long', + day: 'numeric', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + hour12: true, + }, + )} +

+ )} +
+ )} {agent.tool_details && agent.tool_details.length > 0 && (

From d31e3a54fd4fe234ea2881dbc4e6b37250c799dd Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 29 May 2025 15:43:00 +0530 Subject: [PATCH 06/16] (feat:layout) tablet sidebar behave like mobile --- frontend/src/App.tsx | 6 +++--- frontend/src/Navigation.tsx | 27 ++++++++++++++++++--------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 1bba5f44..dbdba932 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -29,8 +29,8 @@ function AuthWrapper({ children }: { children: React.ReactNode }) { } function MainLayout() { - const { isMobile } = useMediaQuery(); - const [navOpen, setNavOpen] = useState(!isMobile); + const { isMobile, isTablet } = useMediaQuery(); + const [navOpen, setNavOpen] = useState(!(isMobile || isTablet)); return (

@@ -38,7 +38,7 @@ function MainLayout() {
{ resetConversation(); dispatch(setSelectedAgent(agent)); - if (isMobile) setNavOpen(!navOpen); + if (isMobile || isTablet) setNavOpen(!navOpen); navigate('/'); }; @@ -271,8 +271,8 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { } useEffect(() => { - setNavOpen(!isMobile); - }, [isMobile]); + setNavOpen(!(isMobile || isTablet)); + }, [isMobile, isTablet]); useDefaultDocument(); return ( @@ -352,7 +352,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { { - if (isMobile) { + if (isMobile || isTablet) { setNavOpen(!navOpen); } resetConversation(); @@ -415,7 +415,7 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {

- Manage Agents + {t('manageAgents')}

@@ -456,7 +459,13 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { ) : (
navigate('/agents')} + onClick={() => { + if (isMobile || isTablet) { + setNavOpen(false); + } + dispatch(setSelectedAgent(null)); + navigate('/agents'); + }} >

- Manage Agents + {t('manageAgents')}

)} From 46efb446fbaa50349553753a9e3f607691614d90 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 29 May 2025 15:43:58 +0530 Subject: [PATCH 07/16] (clean:about) purge route --- frontend/src/About.tsx | 99 ------------------------------------------ frontend/src/App.tsx | 3 -- 2 files changed, 102 deletions(-) delete mode 100644 frontend/src/About.tsx diff --git a/frontend/src/About.tsx b/frontend/src/About.tsx deleted file mode 100644 index d2bbaac4..00000000 --- a/frontend/src/About.tsx +++ /dev/null @@ -1,99 +0,0 @@ -//TODO - Add hyperlinks to text -//TODO - Styling -import DocsGPT3 from './assets/cute_docsgpt3.svg'; - -export default function About() { - return ( -
-
-
-

About DocsGPT

- DocsGPT -
-

- Find the information in your documentation through AI-powered - - {' '} - open-source{' '} - - chatbot. Powered by GPT-3, Faiss and LangChain. -

- -
-

- If you want to add your own documentation, please follow the - instruction below: -

-

- 1. Navigate to{' '} - - {' '} - /application - {' '} - folder -

-

- 2. Install dependencies from{' '} - - pip install -r requirements.txt - -

-

- 3. Prepare a{' '} - .env{' '} - file. Copy{' '} - - .env_sample - {' '} - and create{' '} - .env{' '} - with your OpenAI API token -

-

- 4. Run the app with{' '} - - python app.py - -

-
- -

- Currently It uses{' '} - DocsGPT{' '} - documentation, so it will respond to information relevant to{' '} - DocsGPT. If you - want to train it on different documentation - please follow - - {' '} - this guide - - . -

- -

- If you want to launch it on your own server - follow - - {' '} - this guide - - . -

-
-
- ); -} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index dbdba932..0d1166b7 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2,8 +2,6 @@ import './locale/i18n'; import { useState } from 'react'; import { Outlet, Route, Routes } from 'react-router-dom'; - -import About from './About'; import Spinner from './components/Spinner'; import Conversation from './conversation/Conversation'; import { SharedConversation } from './conversation/SharedConversation'; @@ -64,7 +62,6 @@ export default function App() { } > } /> - } /> } /> } /> From b7e1329c138243d0b1bb0e71ff1ab7bdebc0648a Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 29 May 2025 17:15:13 +0530 Subject: [PATCH 08/16] (feat:chunksModal) i18n, use wrapperModal --- frontend/src/locale/en.json | 12 ++ frontend/src/modals/ChunkModal.tsx | 244 ++++++++++++----------------- 2 files changed, 109 insertions(+), 147 deletions(-) diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index d5aa7d85..d2591d46 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -239,6 +239,18 @@ "promptText": "Prompt Text", "save": "Save", "nameExists": "Name already exists" + }, + "chunk": { + "add": "Add Chunk", + "edit": "Edit Chunk", + "title": "Title", + "enterTitle": "Enter title", + "bodyText": "Body text", + "promptText": "Prompt Text", + "update": "Update", + "close": "Close", + "delete": "Delete", + "deleteConfirmation": "Are you sure you want to delete this chunk?" } }, "sharedConv": { diff --git a/frontend/src/modals/ChunkModal.tsx b/frontend/src/modals/ChunkModal.tsx index ab51fdee..4e229980 100644 --- a/frontend/src/modals/ChunkModal.tsx +++ b/frontend/src/modals/ChunkModal.tsx @@ -1,9 +1,10 @@ import React from 'react'; +import { useTranslation } from 'react-i18next'; -import Exit from '../assets/exit.svg'; import Input from '../components/Input'; import { ActiveState } from '../models/misc'; import ConfirmationModal from './ConfirmationModal'; +import WrapperModal from './WrapperModal'; export default function ChunkModal({ type, @@ -22,6 +23,7 @@ export default function ChunkModal({ originalText?: string; handleDelete?: () => void; }) { + const { t } = useTranslation(); const [title, setTitle] = React.useState(''); const [chunkText, setChunkText] = React.useState(''); const [deleteModal, setDeleteModal] = React.useState('INACTIVE'); @@ -30,157 +32,105 @@ export default function ChunkModal({ setTitle(originalTitle || ''); setChunkText(originalText || ''); }, [originalTitle, originalText]); - if (type === 'ADD') { - return ( -
-
-
- -
-

- Add Chunk -

-
- - Title - - setTitle(e.target.value)} - borderVariant="thin" - placeholder={'Enter title'} - labelBgClassName="bg-white dark:bg-charleston-green-2" - > -
-
-
- - Body text - - -
-
-
- - -
-
-
-
+ + if (modalState !== 'ACTIVE') return null; + + const content = ( +
+

+ {t(`modals.chunk.${type === 'ADD' ? 'add' : 'edit'}`)} +

+
+ setTitle(e.target.value)} + borderVariant="thin" + placeholder={t('modals.chunk.title')} + labelBgClassName="bg-white dark:bg-charleston-green-2" + />
- ); - } else { - return ( -
-
-
+
+
+ + {t('modals.chunk.bodyText')} + + +
+
+ + {type === 'ADD' ? ( +
+ + +
+ ) : ( +
+ +
+ -
-

- Edit Chunk -

-
- setTitle(e.target.value)} - borderVariant="thin" - placeholder={'Enter title'} - labelBgClassName="bg-white dark:bg-charleston-green-2" - > -
-
-
- - Body text - - -
-
-
- -
- - -
-
-
-
+
+ )} +
+ ); + + return ( + <> + setModalState('INACTIVE')} + className="sm:w-[620px]" + > + {content} + + + {type === 'EDIT' && ( -
- ); - } + )} + + ); } From 71d3714347f3e3e74c6d70cf7a8f9354b37575a7 Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Thu, 29 May 2025 17:17:29 +0530 Subject: [PATCH 09/16] (fix:nav) tablets behave like mobile, use tailwind breakpoints --- frontend/src/Navigation.tsx | 7 +++++-- frontend/src/hooks/index.ts | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/frontend/src/Navigation.tsx b/frontend/src/Navigation.tsx index 052c3b27..57c5de45 100644 --- a/frontend/src/Navigation.tsx +++ b/frontend/src/Navigation.tsx @@ -197,6 +197,9 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) { query: { conversationId: index }, }), ); + if (isMobile || isTablet) { + setNavOpen(false); + } if (data.agent_id) { if (data.is_shared_usage) { userService @@ -511,8 +514,8 @@ export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
{ - if (isMobile) { - setNavOpen(!navOpen); + if (isMobile || isTablet) { + setNavOpen(false); } resetConversation(); }} diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts index bffcfb5c..1b9f9b87 100644 --- a/frontend/src/hooks/index.ts +++ b/frontend/src/hooks/index.ts @@ -35,8 +35,8 @@ export function useOutsideAlerter( export function useMediaQuery() { const mobileQuery = '(max-width: 768px)'; - const tabletQuery = '(max-width: 1024px)'; // Tablet breakpoint at 1024px - const desktopQuery = '(min-width: 1025px)'; // Desktop starts after tablet + const tabletQuery = '(max-width: 1023px)'; + const desktopQuery = '(min-width: 1024px)'; const [isMobile, setIsMobile] = useState(false); const [isTablet, setIsTablet] = useState(false); const [isDesktop, setIsDesktop] = useState(false); From a393ad8e04127998b9acfa8c7346ba93c4b9126e Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Fri, 30 May 2025 12:50:11 +0530 Subject: [PATCH 10/16] refactor: standardize string quotes and improve retriever type handling in RetrieverCreator --- application/retriever/retriever_creator.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/application/retriever/retriever_creator.py b/application/retriever/retriever_creator.py index 07be373d..26cb41ca 100644 --- a/application/retriever/retriever_creator.py +++ b/application/retriever/retriever_creator.py @@ -3,18 +3,18 @@ from application.retriever.duckduck_search import DuckDuckSearch from application.retriever.brave_search import BraveRetSearch - class RetrieverCreator: retrievers = { - 'classic': ClassicRAG, - 'duckduck_search': DuckDuckSearch, - 'brave_search': BraveRetSearch, - 'default': ClassicRAG + "classic": ClassicRAG, + "duckduck_search": DuckDuckSearch, + "brave_search": BraveRetSearch, + "default": ClassicRAG, } @classmethod def create_retriever(cls, type, *args, **kwargs): - retiever_class = cls.retrievers.get(type.lower()) + retriever_type = (type or "default").lower() + retiever_class = cls.retrievers.get(retriever_type) if not retiever_class: raise ValueError(f"No retievers class found for type {type}") - return retiever_class(*args, **kwargs) \ No newline at end of file + return retiever_class(*args, **kwargs) From 773788fb32ca3abb8b4713fa4da10fb326bfcdd2 Mon Sep 17 00:00:00 2001 From: Siddhant Rai Date: Fri, 30 May 2025 14:30:51 +0530 Subject: [PATCH 11/16] fix: correct vectorstore path and improve file existence checks in FaissStore --- application/vectorstore/faiss.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/application/vectorstore/faiss.py b/application/vectorstore/faiss.py index ce455bd8..541ec17e 100644 --- a/application/vectorstore/faiss.py +++ b/application/vectorstore/faiss.py @@ -11,9 +11,9 @@ from application.storage.storage_creator import StorageCreator def get_vectorstore(path: str) -> str: if path: - vectorstore = f"indexes/{path}" + vectorstore = f"application/indexes/{path}" else: - vectorstore = "indexes" + vectorstore = "application/indexes" return vectorstore @@ -32,22 +32,26 @@ class FaissStore(BaseVectorStore): with tempfile.TemporaryDirectory() as temp_dir: faiss_path = f"{self.path}/index.faiss" pkl_path = f"{self.path}/index.pkl" - - if not self.storage.file_exists(faiss_path) or not self.storage.file_exists(pkl_path): - raise FileNotFoundError(f"Index files not found in storage at {self.path}") - + + if not self.storage.file_exists( + faiss_path + ) or not self.storage.file_exists(pkl_path): + raise FileNotFoundError( + f"Index files not found in storage at {self.path}" + ) + faiss_file = self.storage.get_file(faiss_path) pkl_file = self.storage.get_file(pkl_path) - + local_faiss_path = os.path.join(temp_dir, "index.faiss") local_pkl_path = os.path.join(temp_dir, "index.pkl") - - with open(local_faiss_path, 'wb') as f: + + with open(local_faiss_path, "wb") as f: f.write(faiss_file.read()) - - with open(local_pkl_path, 'wb') as f: + + with open(local_pkl_path, "wb") as f: f.write(pkl_file.read()) - + self.docsearch = FAISS.load_local( temp_dir, self.embeddings, allow_dangerous_deserialization=True ) From 9c28817fba131ce307ec07a6cdb6aa7bd90c4b9a Mon Sep 17 00:00:00 2001 From: ManishMadan2882 Date: Fri, 30 May 2025 19:05:01 +0530 Subject: [PATCH 12/16] (chore:i18n) sync all locales --- frontend/src/components/SourcesPopup.tsx | 4 +-- frontend/src/locale/en.json | 21 ++++++++----- frontend/src/locale/es.json | 35 ++++++++++++++++----- frontend/src/locale/jp.json | 33 ++++++++++++++----- frontend/src/locale/ru.json | 40 ++++++++++++++++++------ frontend/src/locale/zh-TW.json | 34 +++++++++++++++----- frontend/src/locale/zh.json | 36 +++++++++++++++++---- frontend/src/settings/ToolConfig.tsx | 28 ++++++++--------- 8 files changed, 170 insertions(+), 61 deletions(-) diff --git a/frontend/src/components/SourcesPopup.tsx b/frontend/src/components/SourcesPopup.tsx index 83966730..bdfb7538 100644 --- a/frontend/src/components/SourcesPopup.tsx +++ b/frontend/src/components/SourcesPopup.tsx @@ -207,7 +207,7 @@ export default function SourcesPopup({ className="inline-flex items-center gap-2 text-base font-medium text-violets-are-blue" onClick={onClose} > - Go to Documents + {t('settings.documents.goToDocuments')} Redirect
@@ -217,7 +217,7 @@ export default function SourcesPopup({ onClick={handleUploadClick} className="w-auto rounded-full border border-violets-are-blue px-4 py-2 text-[14px] font-medium text-violets-are-blue transition-colors duration-200 hover:bg-violets-are-blue hover:text-white" > - Upload new + {t('settings.documents.uploadNew')} diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json index d2591d46..7fda12c8 100644 --- a/frontend/src/locale/en.json +++ b/frontend/src/locale/en.json @@ -77,7 +77,9 @@ "backToAll": "Back to all documents", "chunks": "Chunks", "noChunks": "No chunks found", - "noChunksAlt": "No chunks found" + "noChunksAlt": "No chunks found", + "goToDocuments": "Go to Documents", + "uploadNew": "Upload new" }, "apiKeys": { "label": "Chatbots", @@ -138,7 +140,7 @@ "addAction": "Add action", "noActionsFound": "No actions found", "url": "URL", - "urlPlaceholder": "Enter url", + "urlPlaceholder": "Enter URL", "method": "Method", "description": "Description", "descriptionPlaceholder": "Enter description", @@ -146,15 +148,20 @@ "queryParameters": "Query Parameters", "body": "Body", "deleteActionWarning": "Are you sure you want to delete the action \"{{name}}\"?", - "backToTools": "Back to Tools", + "backToAllTools": "Back to all tools", "save": "Save", - "name": "Name", - "type": "Type", + "fieldName": "Field Name", + "fieldType": "Field Type", "filledByLLM": "Filled by LLM", + "fieldDescription": "Field description", "value": "Value", "addProperty": "Add property", - "propertyName": "Property name", - "noProperties": "No properties" + "propertyName": "New property key", + "add": "Add", + "cancel": "Cancel", + "addNew": "Add New", + "name": "Name", + "type": "Type" } }, "modals": { diff --git a/frontend/src/locale/es.json b/frontend/src/locale/es.json index 90ce0844..2f0260b0 100644 --- a/frontend/src/locale/es.json +++ b/frontend/src/locale/es.json @@ -11,6 +11,7 @@ "help": "Asistencia", "emailUs": "Envíanos un correo", "documentation": "Documentación", + "manageAgents": "Administrar Agentes", "demo": [ { "header": "Aprende sobre DocsGPT", @@ -48,7 +49,8 @@ "medium": "Medio", "high": "Alto", "unlimited": "Ilimitado", - "default": "Predeterminado" + "default": "Predeterminado", + "addNew": "Añadir Nuevo" }, "documents": { "title": "Esta tabla contiene todos los documentos que están disponibles para ti y los que has subido", @@ -75,7 +77,9 @@ "backToAll": "Volver a todos los documentos", "chunks": "Fragmentos", "noChunks": "No se encontraron fragmentos", - "noChunksAlt": "No se encontraron fragmentos" + "noChunksAlt": "No se encontraron fragmentos", + "goToDocuments": "Ir a Documentos", + "uploadNew": "Subir nuevo" }, "apiKeys": { "label": "Chatbots", @@ -144,15 +148,20 @@ "queryParameters": "Parámetros de Consulta", "body": "Cuerpo", "deleteActionWarning": "¿Estás seguro de que deseas eliminar la acción \"{{name}}\"?", - "backToTools": "Volver a Herramientas", "save": "Guardar", "name": "Nombre", "type": "Tipo", "filledByLLM": "Completado por LLM", "value": "Valor", "addProperty": "Agregar propiedad", - "propertyName": "Nombre de propiedad", - "noProperties": "Sin propiedades" + "propertyName": "Nueva clave de propiedad", + "backToAllTools": "Volver a todas las herramientas", + "fieldName": "Nombre del campo", + "fieldType": "Tipo de campo", + "fieldDescription": "Descripción del campo", + "add": "Añadir", + "cancel": "Cancelar", + "addNew": "Añadir Nuevo" } }, "modals": { @@ -237,6 +246,18 @@ "promptText": "Texto del Prompt", "save": "Guardar", "nameExists": "El nombre ya existe" + }, + "chunk": { + "add": "Agregar Fragmento", + "edit": "Editar Fragmento", + "title": "Título", + "enterTitle": "Ingresar título", + "bodyText": "Texto del cuerpo", + "promptText": "Texto del prompt", + "update": "Actualizar", + "close": "Cerrar", + "delete": "Eliminar", + "deleteConfirmation": "¿Estás seguro de que deseas eliminar este fragmento?" } }, "sharedConv": { @@ -270,9 +291,9 @@ }, "sources": { "title": "Fuentes", - "text": "Texto fuente", "link": "Enlace fuente", - "view_more": "Ver {{count}} más fuentes" + "view_more": "Ver {{count}} más fuentes", + "text": "Elegir tus fuentes" }, "attachments": { "attach": "Adjuntar", diff --git a/frontend/src/locale/jp.json b/frontend/src/locale/jp.json index 18e3bf4f..3c1cb64b 100644 --- a/frontend/src/locale/jp.json +++ b/frontend/src/locale/jp.json @@ -11,6 +11,7 @@ "help": "ヘルプ", "emailUs": "メールを送る", "documentation": "ドキュメント", + "manageAgents": "エージェント管理", "demo": [ { "header": "DocsGPTについて学ぶ", @@ -76,7 +77,9 @@ "backToAll": "すべてのドキュメントに戻る", "chunks": "チャンク", "noChunks": "チャンクが見つかりません", - "noChunksAlt": "チャンクが見つかりません" + "noChunksAlt": "チャンクが見つかりません", + "goToDocuments": "ドキュメントへ移動", + "uploadNew": "新規アップロード" }, "apiKeys": { "label": "チャットボット", @@ -101,7 +104,6 @@ }, "messages": "メッセージ", "tokenUsage": "トークン使用量", - "feedback": "フィードバック", "filterPlaceholder": "フィルター", "none": "なし", "positiveFeedback": "肯定的なフィードバック", @@ -146,15 +148,20 @@ "queryParameters": "クエリパラメータ", "body": "ボディ", "deleteActionWarning": "アクション \"{{name}}\" を削除してもよろしいですか?", - "backToTools": "ツールに戻る", + "backToAllTools": "すべてのツールに戻る", "save": "保存", - "name": "名前", - "type": "タイプ", + "fieldName": "フィールド名", + "fieldType": "フィールドタイプ", "filledByLLM": "LLMによる入力", + "fieldDescription": "フィールドの説明", "value": "値", "addProperty": "プロパティを追加", - "propertyName": "プロパティ名", - "noProperties": "プロパティなし" + "propertyName": "新しいプロパティキー", + "add": "追加", + "cancel": "キャンセル", + "addNew": "新規追加", + "name": "名前", + "type": "タイプ" } }, "modals": { @@ -239,6 +246,18 @@ "promptText": "プロンプトテキスト", "save": "保存", "nameExists": "名前が既に存在します" + }, + "chunk": { + "add": "チャンクを追加", + "edit": "チャンクを編集", + "title": "タイトル", + "enterTitle": "タイトルを入力", + "bodyText": "本文", + "promptText": "プロンプトテキスト", + "update": "更新", + "close": "閉じる", + "delete": "削除", + "deleteConfirmation": "このチャンクを削除してもよろしいですか?" } }, "sharedConv": { diff --git a/frontend/src/locale/ru.json b/frontend/src/locale/ru.json index 1a3b8848..8d62a577 100644 --- a/frontend/src/locale/ru.json +++ b/frontend/src/locale/ru.json @@ -11,6 +11,7 @@ "help": "Помощь", "emailUs": "Напишите нам", "documentation": "Документация", + "manageAgents": "Управление агентами", "demo": [ { "header": "Узнайте о DocsGPT", @@ -76,7 +77,9 @@ "backToAll": "Вернуться ко всем документам", "chunks": "Фрагменты", "noChunks": "Фрагменты не найдены", - "noChunksAlt": "Фрагменты не найдены" + "noChunksAlt": "Фрагменты не найдены", + "goToDocuments": "Перейти к документам", + "uploadNew": "Загрузить новый" }, "apiKeys": { "label": "API ключи", @@ -137,23 +140,28 @@ "addAction": "Добавить действие", "noActionsFound": "Действия не найдены", "url": "URL", - "urlPlaceholder": "Введите url", + "urlPlaceholder": "Введите URL", "method": "Метод", "description": "Описание", "descriptionPlaceholder": "Введите описание", "headers": "Заголовки", "queryParameters": "Параметры запроса", - "body": "Тело", + "body": "Тело запроса", "deleteActionWarning": "Вы уверены, что хотите удалить действие \"{{name}}\"?", - "backToTools": "Вернуться к инструментам", + "backToAllTools": "Вернуться ко всем инструментам", "save": "Сохранить", - "name": "Имя", - "type": "Тип", - "filledByLLM": "Заполнено LLM", + "fieldName": "Имя поля", + "fieldType": "Тип поля", + "filledByLLM": "Заполняется LLM", + "fieldDescription": "Описание поля", "value": "Значение", "addProperty": "Добавить свойство", - "propertyName": "Имя свойства", - "noProperties": "Нет свойств" + "propertyName": "Новый ключ свойства", + "add": "Добавить", + "cancel": "Отмена", + "addNew": "Добавить новое", + "name": "Имя", + "type": "Тип" } }, "modals": { @@ -238,6 +246,18 @@ "promptText": "Текст подсказки", "save": "Сохранить", "nameExists": "Название уже существует" + }, + "chunk": { + "add": "Добавить фрагмент", + "edit": "Редактировать фрагмент", + "title": "Заголовок", + "enterTitle": "Введите заголовок", + "bodyText": "Текст", + "promptText": "Текст подсказки", + "update": "Обновить", + "close": "Закрыть", + "delete": "Удалить", + "deleteConfirmation": "Вы уверены, что хотите удалить этот фрагмент?" } }, "sharedConv": { @@ -271,7 +291,7 @@ }, "sources": { "title": "Источники", - "text": "Текст источника", + "text": "Выберите ваши источники", "link": "Ссылка на источник", "view_more": "ещё {{count}} источников" }, diff --git a/frontend/src/locale/zh-TW.json b/frontend/src/locale/zh-TW.json index f20ade6b..366d0f56 100644 --- a/frontend/src/locale/zh-TW.json +++ b/frontend/src/locale/zh-TW.json @@ -11,6 +11,7 @@ "help": "幫助", "emailUs": "給我們發電郵", "documentation": "文件", + "manageAgents": "管理代理", "demo": [ { "header": "了解 DocsGPT", @@ -76,7 +77,9 @@ "backToAll": "返回所有文件", "chunks": "文本塊", "noChunks": "未找到文本塊", - "noChunksAlt": "未找到文本塊" + "noChunksAlt": "未找到文本塊", + "goToDocuments": "前往文件", + "uploadNew": "上傳新文件" }, "apiKeys": { "label": "聊天機器人", @@ -145,15 +148,20 @@ "queryParameters": "查詢參數", "body": "主體", "deleteActionWarning": "您確定要刪除操作 \"{{name}}\" 嗎?", - "backToTools": "返回工具", + "backToAllTools": "返回所有工具", "save": "儲存", - "name": "名稱", - "type": "類型", - "filledByLLM": "由LLM填寫", + "fieldName": "欄位名稱", + "fieldType": "欄位類型", + "filledByLLM": "由LLM填入", + "fieldDescription": "欄位描述", "value": "值", "addProperty": "新增屬性", - "propertyName": "屬性名稱", - "noProperties": "無屬性" + "propertyName": "新屬性鍵", + "add": "新增", + "cancel": "取消", + "addNew": "新增", + "name": "名稱", + "type": "類型" } }, "modals": { @@ -238,6 +246,18 @@ "promptText": "提示文字", "save": "儲存", "nameExists": "名稱已存在" + }, + "chunk": { + "add": "新增區塊", + "edit": "編輯區塊", + "title": "標題", + "enterTitle": "輸入標題", + "bodyText": "內文", + "promptText": "提示文字", + "update": "更新", + "close": "關閉", + "delete": "刪除", + "deleteConfirmation": "您確定要刪除此區塊嗎?" } }, "sharedConv": { diff --git a/frontend/src/locale/zh.json b/frontend/src/locale/zh.json index 22f144dd..6d4e590c 100644 --- a/frontend/src/locale/zh.json +++ b/frontend/src/locale/zh.json @@ -11,6 +11,7 @@ "help": "帮助", "emailUs": "给我们发邮件", "documentation": "文档", + "manageAgents": "管理代理", "demo": [ { "header": "了解 DocsGPT", @@ -72,7 +73,13 @@ }, "actions": "操作", "view": "查看", - "deleteWarning": "您确定要删除 \"{{name}}\" 吗?" + "deleteWarning": "您确定要删除 \"{{name}}\" 吗?", + "backToAll": "返回所有文档", + "chunks": "文本块", + "noChunks": "未找到文本块", + "noChunksAlt": "未找到文本块", + "goToDocuments": "前往文档", + "uploadNew": "上传新文档" }, "apiKeys": { "label": "聊天机器人", @@ -141,15 +148,20 @@ "queryParameters": "查询参数", "body": "请求体", "deleteActionWarning": "您确定要删除操作 \"{{name}}\" 吗?", - "backToTools": "返回工具", + "backToAllTools": "返回所有工具", "save": "保存", - "name": "名称", - "type": "类型", + "fieldName": "字段名称", + "fieldType": "字段类型", "filledByLLM": "由LLM填充", + "fieldDescription": "字段描述", "value": "值", "addProperty": "添加属性", - "propertyName": "属性名称", - "noProperties": "无属性" + "propertyName": "新属性键", + "add": "添加", + "cancel": "取消", + "addNew": "添加新的", + "name": "名称", + "type": "类型" } }, "modals": { @@ -234,6 +246,18 @@ "promptText": "提示文本", "save": "保存", "nameExists": "名称已存在" + }, + "chunk": { + "add": "添加块", + "edit": "编辑块", + "title": "标题", + "enterTitle": "输入标题", + "bodyText": "正文", + "promptText": "提示文本", + "update": "更新", + "close": "关闭", + "delete": "删除", + "deleteConfirmation": "您确定要删除此块吗?" } }, "sharedConv": { diff --git a/frontend/src/settings/ToolConfig.tsx b/frontend/src/settings/ToolConfig.tsx index 2194f93f..7d738842 100644 --- a/frontend/src/settings/ToolConfig.tsx +++ b/frontend/src/settings/ToolConfig.tsx @@ -169,13 +169,13 @@ export default function ToolConfig({ > left-arrow -

Back to all tools

+

{t('settings.tools.backToAllTools')}

{/* Custom name section */} @@ -282,7 +282,7 @@ export default function ToolConfig({ { setTool({ @@ -305,11 +305,11 @@ export default function ToolConfig({ - - - - - + + + + + @@ -619,7 +619,7 @@ function APIToolConfig({
- Method + {t('settings.tools.method')} @@ -993,15 +993,13 @@ function APIActionTable({ onClick={handleAddProperty} className="mr-1 rounded-full bg-purple-30 px-5 py-[4px] text-sm text-white hover:bg-violets-are-blue" > - {' '} - Add{' '} + {t('settings.tools.add')}
Field NameField TypeFilled by LLMFIeld descriptionValue{t('settings.tools.fieldName')}{t('settings.tools.fieldType')}{t('settings.tools.filledByLLM')}{t('settings.tools.fieldDescription')}{t('settings.tools.value')}
handleAddPropertyStart(section)} className="flex items-start text-nowrap rounded-full border border-solid border-violets-are-blue px-5 py-[4px] text-sm text-violets-are-blue transition-colors hover:bg-violets-are-blue hover:text-white" > - Add New Field + {t('settings.tools.addNew')} Date: Fri, 30 May 2025 19:33:07 +0530 Subject: [PATCH 13/16] (fix/ui) minor adjustments --- frontend/src/preferences/PromptsModal.tsx | 4 ++-- frontend/src/settings/Documents.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/preferences/PromptsModal.tsx b/frontend/src/preferences/PromptsModal.tsx index b5e028bd..f61ba4ee 100644 --- a/frontend/src/preferences/PromptsModal.tsx +++ b/frontend/src/preferences/PromptsModal.tsx @@ -51,7 +51,7 @@ function AddPrompt({