diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..e69de29b diff --git a/apps/rowboat/app/globals.css b/apps/rowboat/app/globals.css index 25bf132f..d7b5d1bb 100644 --- a/apps/rowboat/app/globals.css +++ b/apps/rowboat/app/globals.css @@ -7,6 +7,32 @@ .text-balance { text-wrap: balance; } + .custom-scrollbar { + scrollbar-width: thin; + scrollbar-color: #E4E4E7 transparent; + } + + .custom-scrollbar::-webkit-scrollbar { + width: 6px; + } + + .custom-scrollbar::-webkit-scrollbar-track { + background: transparent; + } + + .custom-scrollbar::-webkit-scrollbar-thumb { + background-color: #E4E4E7; + border-radius: 3px; + } + + /* Dark mode */ + .dark .custom-scrollbar { + scrollbar-color: #3F3F46 transparent; + } + + .dark .custom-scrollbar::-webkit-scrollbar-thumb { + background-color: #3F3F46; + } } html, body { @@ -67,6 +93,27 @@ html, body { --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; } + /* Define a card class that will be used for all card-like components */ + .card { + @apply rounded-xl border p-4 + border-[#E5E7EB] dark:border-[#2E2E30] + bg-white dark:bg-[#1C1C1E] + shadow-[0_2px_8px_rgba(0,0,0,0.04)] + transition-all duration-200 ease-in-out; + } + + .card:hover { + @apply shadow-[0_4px_12px_rgba(0,0,0,0.06)] + transform translate-y-[-1px]; + } + + /* Update input styles */ + input, textarea, select { + @apply rounded-lg border-[#E5E7EB] dark:border-[#2E2E30] + bg-[#F3F4F6] dark:bg-[#2A2A2D] + focus:ring-2 focus:ring-indigo-500 focus:ring-opacity-50 + transition-all duration-200; + } } @layer base { @@ -88,6 +135,20 @@ html, body { .border-subtle { @apply border-border dark:border-border/50; } + + /* Apply rounded corners to common interactive elements by default */ + button, + input, + textarea, + select, + [role="button"], + .card, + .input, + .select, + .textarea, + .button { + @apply !rounded-lg; + } } * { @@ -97,4 +158,27 @@ html, body { * { @apply transition-colors duration-200; -} \ No newline at end of file +} + +/* Add Inter font */ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap'); + +/* Set base font */ +html { + font-family: 'Inter', system-ui, -apple-system, sans-serif; +} + +@keyframes slideUpAndFade { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-slideUpAndFade { + animation: slideUpAndFade 0.2s ease-out forwards; +} \ No newline at end of file diff --git a/apps/rowboat/app/lib/components/copy-button.tsx b/apps/rowboat/app/lib/components/copy-button.tsx deleted file mode 100644 index 28108d18..00000000 --- a/apps/rowboat/app/lib/components/copy-button.tsx +++ /dev/null @@ -1,32 +0,0 @@ -'use client'; -import { CopyIcon, CheckIcon } from "lucide-react"; -import { useState } from "react"; - -export function CopyButton({ - onCopy, - label, - successLabel, -}: { - onCopy: () => void; - label: string; - successLabel: string; -}) { - const [showCopySuccess, setShowCopySuccess] = useState(false); - const handleCopy = () => { - onCopy(); - setShowCopySuccess(true); - setTimeout(() => { - setShowCopySuccess(false); - }, 500); - } - return -} \ No newline at end of file diff --git a/apps/rowboat/app/lib/components/form-status-button-old.tsx b/apps/rowboat/app/lib/components/form-status-button-old.tsx new file mode 100644 index 00000000..8a2eee2e --- /dev/null +++ b/apps/rowboat/app/lib/components/form-status-button-old.tsx @@ -0,0 +1,14 @@ +'use client'; + +import { useFormStatus } from "react-dom"; +import { Button, ButtonProps } from "@heroui/react"; + +export function FormStatusButton({ + props +}: { + props: ButtonProps; +}) { + const { pending } = useFormStatus(); + + return - ) -} \ No newline at end of file diff --git a/apps/rowboat/app/lib/project_templates.ts b/apps/rowboat/app/lib/project_templates.ts index 56e1d234..beebcae2 100644 --- a/apps/rowboat/app/lib/project_templates.ts +++ b/apps/rowboat/app/lib/project_templates.ts @@ -5,7 +5,7 @@ export const templates: { [key: string]: z.infer } = { // Default template 'default': { name: 'Blank Template', - description: 'A blank canvas to build your support agents.', + description: 'A blank canvas to build your agents.', startAgent: "Example Agent", agents: [ { @@ -82,270 +82,6 @@ You are an helpful customer support assistant } ], tools: [], - }, - - // single agent - "single_agent": { - "name": "Example Single Agent", - "description": "With tool calls and escalation.", - "startAgent": "Account Balance Checker", - "agents": [ - { - "name": "Post process", - "type": "post_process", - "description": "Minimal post processing", - "instructions": "- Avoid adding any additional phrases such as 'Let me know if you need anything else!' or similar.", - "model": "gpt-4o", - "toggleAble": true, - "locked": true, - "global": true, - "ragReturnType": "chunks", - "ragK": 3, - "controlType": "relinquish_to_parent" - }, - { - "name": "Escalation", - "type": "escalation", - "description": "Escalation agent", - "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nHandle scenarios where the system needs to escalate a request to a human representative.\n\n---\n## āš™ļø Steps to Follow:\n1. Inform the user that their details are being escalated to a human agent.\n2. Call [@tool:close_chat](#mention) to close the chat session.\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Escalating issues to human agents\n- Closing chat sessions\n\nāŒ Out of Scope:\n- Handling queries that do not require escalation\n- Providing solutions without escalation\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Clearly inform the user about the escalation.\n- Ensure the chat is closed after escalation.\n\n🚫 Don'ts:\n- Attempt to resolve issues without escalation.\n- Leave the chat open after informing the user about escalation.\n", - "model": "gpt-4o", - "locked": true, - "toggleAble": false, - "ragReturnType": "chunks", - "ragK": 3, - "controlType": "retain", - "examples": "- **User** : I need help with something urgent.\n - **Agent response**: Your request is being escalated to a human agent.\n - **Agent actions**: Call [@tool:close_chat](#mention)\n\n- **User** : Can you escalate this issue?\n - **Agent response**: Your details are being escalated to a human agent.\n - **Agent actions**: Call [@tool:close_chat](#mention)" - }, - { - "name": "Account Balance Checker", - "type": "conversation", - "description": "Agent to check the user's account balance.", - "disabled": false, - "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nAssist users in checking their account balance.\n\n---\n## āš™ļø Steps to Follow:\n1. Greet them with 'Hello, welcome to RowBoat Bank.'\n2. If the user hasn't provided their request yet, ask 'How may I help you today?'\n3. If the request is related to checking account balance, proceed with the following steps:\n - Ask the user to confirm the last 4 digits of their debit card.\n - Use [@tool:get_account_balance](#mention) to fetch the account balance.\n - Inform the user of their account balance based on the output of [@tool:get_account_balance](#mention) \n4. If the user requests to talk to a human, call [@agent:Escalation](#mention) .\n5. If the request is not related to checking account balance, inform the user: 'Sorry, I can only help you with account balance.'\n\n---\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Fetching and providing account balance\n- Escalating to human agents upon request\n\nāŒ Out of Scope:\n- Handling queries unrelated to account balance\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Always call get_account_balance to fetch the user's account balance\n- Be clear and concise in communication.\n- Call the Escalation agent if the user requests to speak with a human.\n\n🚫 Don'ts:\n- Extend the conversation beyond account balance checking.\n", - "model": "gpt-4o", - "locked": false, - "toggleAble": true, - "ragReturnType": "chunks", - "ragK": 3, - "controlType": "retain", - "examples": "- **User** : Can you tell me my account balance?\n - **Agent response**: Sure, can you confirm the last 4 digits of your debit card?\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n\n- **User** : The last 4 digits are 1234.\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n - **Agent response**: Your account balance is $500.\n\n- **User** : What's my balance?\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n - **Agent response**: Your account balance is $500.\n\n- **User** : I need help with my credit card.\n - **Agent response**: Sorry, I can only help you with account balance.\n\n- **User** : I need to know my balance, please.\n - **Agent response**: Of course, please provide the last 4 digits of your debit card.\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n\n- **User** : How much money do I have in my account?\n - **Agent response**: Please confirm the last 4 digits of your debit card to proceed.\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n\n- **User** : My card ends in 5678.\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n - **Agent response**: Your account balance is $500.\n\n- **User** : Can you check my balance?\n - **Agent response**: Certainly, could you provide the last 4 digits of your debit card?\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n\n- **User** : I want to know my account balance.\n - **Agent response**: Sure, please confirm the last 4 digits of your debit card.\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n\n- **User** : The last 4 digits are 9876.\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n - **Agent response**: Your account balance is $500.\n\n- **User** : Hi\n - **Agent response**: Hello, welcome to RowBoat Bank. How may I help you today?\n\n- **User** : Hi, I want to check my balance\n - **Agent response**: Hello, welcome to RowBoat Bank. Sure, can you confirm the last 4 digits of your debit card?\n - **Agent actions**: Call [@tool:get_account_balance](#mention)\n\n- **User** : Who are you?\n - **Agent response**: I'm a friendly RowBoat Bank assistant, how can I help you today?\n\n- **User** : Who built you?\n - **Agent response**: I was created by the RowBoat Bank team to assist you with your banking needs. How may I help you today?\n\n- **User** : How are you?\n - **Agent response**: I'm here to help you with your banking queries. How can I assist you today?\n\n- **User** : I want to talk to a human.\n - **Agent actions**: Call [@agent:Escalation](#mention)\n - **Agent response**: Your request is being escalated to a human agent." - } - ], - "prompts": [ - { - "name": "Style prompt", - "type": "style_prompt", - "prompt": "You should be empathetic and helpful." - }, - { - "name": "Greeting", - "type": "greeting", - "prompt": "Hello! How can I help you?" - } - ], - "tools": [ - { - "name": "get_account_balance", - "description": "Return account balance typically around $15000 for the user.", - "parameters": { - "type": "object", - "properties": { - "user_id": { - "type": "string", - "description": "The unique identifier for the user whose account balance is being queried." - } - }, - "required": [ - "user_id" - ] - }, - "mockTool": true, - "autoSubmitMockedResponse": true - }, - { - "name": "close_chat", - "description": "return 'The chat is now closed'", - "parameters": { - "type": "object", - "properties": { - "param1": { - "type": "string", - "description": "" - } - }, - "required": [ - "param1" - ] - }, - "mockTool": true, - "autoSubmitMockedResponse": true - } - ], - }, - - // Scooter Subscription - 'multi_agent': { - "name": "Example Multi-Agent", - "description": "With tool calls, escalation, structured output, post processing, and prompt organization.", - "startAgent": "Main agent", - "agents": [ - { - "name": "Main agent", - "type": "conversation", - "disabled": false, - "instructions": "## šŸ§‘ā€šŸ’¼ Role:\nYou are a customer support agent for ScootUp scooters. Your main responsibility is to orchestrate conversations and delegate them to specialized worker agents for efficient query handling.\n\n---\n## āš™ļø Steps to Follow:\n1. Engage in basic small talk to build rapport. Stick to the specified examples for such interactions.\n2. When a specific query arises, pass control to the relevant worker agent immediately, such as [@agent:Product info agent](#mention) or [@agent:Delivery info agent](#mention) .\n3. For follow-up questions on the same topic, direct them back to the same worker agent who handled the initial query.\n4. If the query is out-of-scope, call [@agent:Escalation agent](#mention)\n\n---\n## šŸŽÆ Scope:\n\nāœ… In Scope:\n- Initial query handling and passing control to specific agents\n\nāŒ Out of Scope:\n- Detailed product or service resolutions\n- Technical troubleshooting or detailed assistance beyond initial query reading\n- General knowledge related questions\n\n---\n## šŸ“‹ Guidelines:\nāœ”ļø Dos:\n- Ensure smooth conversational flow while transferring queries to respective agents.\n- Engage only in light rapport-building or disambiguating discussions.\n\n🚫 Don'ts:\n- Avoid engaging in detailed support discussions or troubleshooting at length.\n- Do not address queries beyond initial understanding beyond relaying them to appropriate agents.\n- Do not answer out-of-scope questions; instead, direct them to the [@agent:Escalation agent](#mention) .\n- Do not talk about other agents or about transferring to them.\n\nFollow [@prompt:Style prompt](#mention)Ā . Also keep in mind [@prompt:self_support_prompt](#mention) .\n", - "model": "gpt-4o", - "locked": false, - "toggleAble": true, - "ragReturnType": "chunks", - "ragK": 3, - "ragDataSources": [], - "description": "The Main agent orchestrates interactions between various specialized worker agents to ensure efficient handling of user queries and support needs.", - "controlType": "retain", - "examples": "- **User**: \"hi\"\n - **Agent response**: \"Hello! How can I help you with your ScootUp scooter today? I can assist with product information or check on your delivery. Let me know how I can help!\"\n\n- **User**: \"How are you?\"\n - **Agent response**: \"I'm doing well, thank you. How can I help you with ScootUp today?\"\n\n- **User**: \"What can you do?\"\n - **Agent response**: \"I can help with customer support-related issues for ScootUp scooters. Let me know if you have any questions.\"\n\n- **User**: \"What's your role here?\"\n - **Agent response**: \"I'm here to assist you with any ScootUp scooter inquiries. Feel free to ask me anything!\"\n\n- **User**: \"Do you have a favorite scooter?\"\n - **Agent response**: \"I think all ScootUp scooters are great! What interests you about them?\"\n\n- **User**: \"What's your favorite season for scooter rides?\"\n - **Agent response**: \"Each season has its charm for a ride! How about you?\"\n\n- **User**: \"Tell me a fun fact about scooters.\"\n - **Agent response**: \"Did you know that ScootUp scooters can now be found in almost every major city as a part of shared transportation services?\"\n\n- **User**: \"Do you enjoy scooter rides too?\"\n - **Agent response**: \"I think riding scooters can be a lot of fun and a great way to explore the city!\"\n\n- **User**: \"What's a good way to spend a weekend?\"\n - **Agent response**: \"Exploring new places on a scooter could be very exciting! What do you think?\"\n\n- **User**: \"Do you follow any sports?\"\n - **Agent response**: \"I'm focused on supporting ScootUp-related inquiries, but I'd love to hear if you have a favorite sport!\"\n\n- **User**: \"Tell me something interesting.\"\n - **Agent response**: \"ScootUp scooters are known for their dual motors, which provide extra power for smooth rides.\"\n\n- **User**: \"Tell me about the product features.\"\n - **Agent actions**: \"Call [@agent:Product info agent](#mention)\"\n\n- **User**: \"Where is my scooter?\"\n - **Agent actions**: \"Call [@agent:Delivery info agent](#mention)\"\n\n- **User**: \"Can I get details about shipping and delivery times?\"\n - **Agent actions**: \"Call [@agent:Delivery info agent](#mention)\"\n\n- **User**: \"What is the battery life of the scooter?\"\n - **Agent actions**: \"Call [@agent:Product info agent](#mention)\"\n\n- **User**: \"I have a broken scooter part, can I get a replacement?\"\n - **Agent actions**: \"Call [@agent:Product info agent](#mention)\"\n\n- **User**: \"What are ScootUp scooters?\"\n - **Agent actions**: \"Call [@agent:Product info agent](#mention)\"" - }, - { - "name": "Post process", - "type": "post_process", - "disabled": false, - "instructions": "- Extract the response_to_user field from the provided structured JSON and ensure that this is the only content you use for the final output.\n- Ensure that the agent response covers all the details the user asked for.\n- Use bullet points only when providing lengthy or detailed information that benefits from such formatting.\n- Generally, aim to keep responses concise and focused on key details. You can summarize the info to around 5 sentences.\n- Focus specifically on the response_to_user field in its input.", - "model": "gpt-4o", - "locked": true, - "toggleAble": true, - "ragReturnType": "chunks", - "ragK": 3, - "ragDataSources": [], - "description": "", - "controlType": "retain" - }, - { - "name": "Product info agent", - "type": "conversation", - "disabled": false, - "instructions": "šŸ§‘ā€šŸ’¼ Role:\nYou are a product information agent for ScootUp scooters. Your job is to search for the right article and answer questions strictly based on the article about ScootUp products. Feel free to ask the user clarification questions if needed.\n\n---\n\nšŸ“œ Instructions:\n- Call [@tool:retrieve_snippet](#mention) to get the relevant information and answer questions strictly based on that\n\nāœ… In Scope:\n- Answer questions strictly about ScootUp product information.\n\nāŒ Out of Scope:\n- Questions about delivery, returns, and subscriptions.\n- Any topic unrelated to ScootUp products.\n- If a question is out of scope, call give_up_control and do not attempt to answer it.\n\n---\n## šŸ“‹ Guidelines:\n\nāœ”ļø Dos:\n- Stick to the facts provided in the articles.\n- Provide complete and direct answers to the user's questions.\n\n---\n\n🚫 Don'ts:\n- Do not partially answer questions or direct users to a URL for more information.\n- Do not provide information outside of the given context.\n\n", - "model": "gpt-4o", - "locked": false, - "toggleAble": true, - "ragReturnType": "content", - "ragK": 3, - "ragDataSources": [], - "description": "You assist with product-related questions by retrieving relevant articles and information.", - "controlType": "relinquish_to_parent", - "examples": "- **User**: \"What is the maximum speed of the ScootUp E500?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"The maximum speed of the E500 is .\"\n\n- **User**: \"How long does it take to charge a ScootUp scooter fully?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"A full charge requires hours.\"\n\n- **User**: \"Can you tell me about the weight-carrying capacity of ScootUp scooters?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"It supports up to .\"\n\n- **User**: \"What are the differences between the E250 and E500 models?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"Here are the differences: .\"\n\n- **User**: \"How far can I travel on a single charge with the E500?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"You can typically travel up to miles.\"\n\n- **User**: \"Is the scooter waterproof?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"Its waterproof capabilities are: .\"\n\n- **User**: \"Does the scooter have any safety features?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"These safety features are: .\"\n\n- **User**: \"What materials are used to make ScootUp scooters?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"The materials used are: .\"\n\n- **User**: \"Can the scooter be used off-road?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"Regarding off-road use, .\"\n\n- **User**: \"Are spare parts available for purchase?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"Spare parts availability is .\"\n\n- **User**: \"What is the status of my order delivery?\"\n - **Agent actions**: Call give_up_control\n\n- **User**: \"How do I process a return?\"\n - **Agent actions**: Call give_up_control\n\n- **User**: \"Can you tell me more about the subscription plans?\"\n - **Agent actions**: Call give_up_control\n\n- **User**: \"Are there any promotions or discounts?\"\n - **Agent actions**: Call give_up_control\n\n- **User**: \"Who won the last election?\"\n - **Agent actions**: Call give_up_control" - }, - { - "name": "Delivery info agent", - "type": "conversation", - "disabled": false, - "instructions": "## šŸ§‘ā€šŸ’¼ Role:\n\nYou are responsible for providing delivery information to the user.\n\n---\n\n## āš™ļø Steps to Follow:\n\n1. Check if the orderId is available:\n - If not available, politely ask the user for their orderId.\n - Once the user provides the orderId, call the [@tool:validate_entity](#mention) tool to check if it's valid.\n - If 'validated', proceed to Step 2.\n - If 'not validated', ask the user to re-check or provide a corrected orderId. Provide a reason on why it is invalid only if the validations tool returns that information.\n2. Fetch the delivery details using the function: [@tool:get_delivery_details](#mention) once the valid orderId is available.\n3. Answer the user's question based on the fetched delivery details.\n4. If the user asks a general delivery question, call [@tool:retrieve_snippet](#mention) and provide an answer only based on it.\n5. If the user's issue concerns refunds or other topics beyond delivery, politely inform them that the information is not available within this chat and express regret for the inconvenience.\n\n---\n## šŸŽÆ Scope\n\nāœ… In Scope:\n- Questions about delivery status, shipping timelines, and delivery processes.\n- Generic delivery/shipping-related questions where answers can be sourced from articles.\n\nāŒ Out of Scope:\n- Questions unrelated to delivery or shipping.\n- Questions about product features, returns, subscriptions, or promotions.\n- If a question is out of scope, politely inform the user and avoid providing an answer.\n\n---\n\n## šŸ“‹ Guidelines\n\nāœ”ļø Dos:\n- Use validations to verify orderId.\n- Use get_shipping_details to fetch accurate delivery information.\n- Promptly ask for orderId if not available.\n- Provide complete and clear answers based on the delivery details.\n- For generic delivery questions, strictly refer to retrieved snippets. Stick to factual information when answering.\n\n🚫 Don'ts:\n- Do not mention or describe how you are fetching the information behind the scenes.\n- Do not provide answers without fetching delivery details when required.\n- Do not leave the user with partial information.\n- Refrain from phrases like 'please contact support'; instead, relay information limitations gracefully.\n", - "model": "gpt-4o", - "locked": false, - "toggleAble": true, - "ragReturnType": "chunks", - "ragK": 3, - "ragDataSources": [], - "description": "You are responsible for providing accurate delivery status and shipping details for orders.", - "controlType": "retain", - "examples": "- **User**: \"What is the status of my delivery?\"\n - **Agent actions**: Call [@tool:get_delivery_details](#mention)\n - **Agent response**: \"Could you please provide your order ID so I can check your delivery status?\"\n\n- **User**: \"Can you explain the delivery process?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"Here's some information on the delivery process: .\"\n\n- **User**: \"I have a question about product features such as range, durability etc.\"\n - **Agent actions**: give_up_control\n\n- **User**: \"I want to know when my scooter shipped.\"\n - **Agent actions**: Call [@tool:get_delivery_details](#mention)\n - **Agent response**: \"May I have your order ID, please?\"\n\n- **User**: \"Which shipping carrier do you use?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"We typically use as our shipping carrier.\"\n\n- **User**: \"Where can I find my orderId?\"\n - **Agent actions**: Call [@tool:retrieve_snippet](#mention)\n - **Agent response**: \"\"\n\n- **User**: \"My orderId is 123456.\"\n - **Agent actions**: Call [@tool:validate_entity](#mention)\n - **Agent actions**: Call [@tool:get_delivery_details](#mention)\n - **Agent response**: \"Your scooter is expected to arrive by .\"\n\n- **User**: \"My orderId is abcxyz.\"\n - **Agent actions**: Call [@tool:validate_entity](#mention)\n - **Agent response**: \"It seems your order ID is invalid . Could you please double-check and provide a correct orderId?\"" - }, - { - "name": "Escalation agent", - "type": "escalation", - "description": "Handles situations where user queries cannot be addressed by existing agents and require escalation.", - "disabled": false, - "instructions": "\n## šŸ§‘ā€šŸ’¼ Role:\nYou handle situations where escalation is necessary because the current agents cannot fulfill the user's request.\n\n---\n\n## āš™ļø Steps to Follow:\n1. Tell the user you will setup a callback with the team. \n\n---\n\n## šŸŽÆ Scope:\nāœ… In Scope:\n- Escalating unresolvable queries, notifying users of escalation, and logging escalation activities.\n\nāŒ Out of Scope:\n- Providing responses to general or specialized topics already handled by other agents.\n\n---\n\n## šŸ“‹ Guidelines:\nāœ”ļø Dos: \n- Respond empathetically to the user, inform them about the escalation, and ensure necessary actions are taken.\n\n🚫 Don'ts: \n- Do not attempt to resolve issues not within your scope.\n", - "model": "gpt-4o", - "locked": false, - "toggleAble": true, - "ragReturnType": "chunks", - "ragK": 3, - "controlType": "retain", - "examples": "- **User**: \"I've tried everything, but no one can resolve my issue. I demand further assistance!\"\n - **Agent actions**: N/A\n - **Agent response**: \"I'm sorry about your experience. I'll set up a callback with our support team so we can thoroughly resolve your issue. We appreciate your patience, and we'll be in touch soon.\"\n\n- **User**: \"Could you escalate this? I've been waiting for days without a resolution.\"\n - **Agent actions**: N/A\n - **Agent response**: \"I'm sorry about your experience. I'll set up a callback with our support team so we can thoroughly resolve your issue. We appreciate your patience, and we'll be in touch soon.\"\n\n- **User**: \"I want a manager to handle my case personally. This is unacceptable.\"\n - **Agent actions**: N/A\n - **Agent response**: \"I'm sorry about your experience. I'll set up a callback with our support team so we can thoroughly resolve your issue. We appreciate your patience, and we'll be in touch soon.\"\n\n- **User**: \"None of the agents so far have fixed my problem. How do I escalate this?\"\n - **Agent actions**: N/A\n - **Agent response**: \"I'm sorry about your experience. I'll set up a callback with our support team so we can thoroughly resolve your issue. We appreciate your patience, and we'll be in touch soon.\"\n\n- **User**: \"I'm tired of repeating myself. I need upper management involved now.\"\n - **Agent actions**: N/A\n - **Agent response**: \"I'm sorry about your experience. I'll set up a callback with our support team so we can thoroughly resolve your issue. We appreciate your patience, and we'll be in touch soon.\"" - } - ], - "prompts": [ - { - "name": "Style prompt", - "type": "style_prompt", - "prompt": "---\n\nmake this more friendly. Keep it to 5-7 sentences. Use these as example references:\n\n---" - }, - { - "name": "Greeting", - "type": "greeting", - "prompt": "Hello! How can I help you?" - }, - { - "name": "structured_output", - "type": "base_prompt", - "prompt": "Provide your output in the following structured JSON format:\n```\n{\n \"steps_completed\": ,\n \"current_step\": ,\n \"reasoning\": \"\",\n \"error_count\": ,\n \"response_to_user\": \"\"\n}\n```\nAlways ensure that all pertinent details, including tables or structured lists, are contained within the response_to_user field to maintain clarity and a comprehensive response for the user." - }, - { - "name": "rag_article_prompt", - "type": "base_prompt", - "prompt": "Retrieval instructions:\n\nIn every turn, retrieve a relevant article and use the information from that article to answer the user's question." - }, - { - "name": "self_support_prompt", - "type": "base_prompt", - "prompt": "Self Support Guidance:\n\nThe bot should not suggest phrases like 'let me connect you to support' or 'you can reach out to support'. Instead, the agent is the customer support. It can say 'I apologize, but I don't have the right information'." - } - ], - "tools": [ - { - "name": "get_delivery_details", - "description": "Return a estimated delivery date for the unagi scooter.", - "parameters": { - "type": "object", - "properties": { - "orderId": { - "type": "string", - "description": "the user's ID" - } - }, - "required": [ - "orderId" - ] - }, - "mockTool": true, - "autoSubmitMockedResponse": true - }, - { - "name": "retrieve_snippet", - "description": "This is a mock RAG service. Always return 2 paragraphs about a fictional scooter rental product, based on the query. Be verbose.", - "mockTool": true, - "autoSubmitMockedResponse": true, - "parameters": { - "type": "object", - "properties": { - "param1": { - "type": "string", - "description": "" - } - }, - "required": [ - "param1" - ] - } - }, - { - "name": "validate_entity", - "description": "orderId should contain only numbers. If the provided orderId is correct, return 'validated' else return 'not validated; '", - "parameters": { - "type": "object", - "properties": { - "orderId": { - "type": "string", - "description": "" - } - }, - "required": [ - "orderId" - ] - }, - "mockTool": true, - "autoSubmitMockedResponse": true - } - ], } } diff --git a/apps/rowboat/app/projects/[projectId]/config/app.tsx b/apps/rowboat/app/projects/[projectId]/config/app.tsx index 2d341763..e78d8855 100644 --- a/apps/rowboat/app/projects/[projectId]/config/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/config/app.tsx @@ -5,7 +5,7 @@ import { Spinner, Textarea, Button, Dropdown, DropdownMenu, DropdownItem, Dropdo import { ReactNode, useEffect, useState, useCallback, useMemo } from "react"; import { getProjectConfig, updateProjectName, updateWebhookUrl, createApiKey, deleteApiKey, listApiKeys, deleteProject, rotateSecret } from "../../../actions/project_actions"; import { updateMcpServers } from "../../../actions/mcp_actions"; -import { CopyButton } from "../../../lib/components/copy-button"; +import { CopyButton } from "../../../../components/common/copy-button"; import { EditableField } from "../../../lib/components/editable-field"; import { EyeIcon, EyeOffIcon, CopyIcon, MoreVerticalIcon, PlusIcon, EllipsisVerticalIcon, CheckCircleIcon, XCircleIcon } from "lucide-react"; import { WithStringId } from "../../../lib/types/types"; @@ -21,7 +21,12 @@ import { ResizablePanel, ResizablePanelGroup, } from "../../../../components/ui/resizable" -import { VoiceSection } from './voice'; +import { VoiceSection } from './components/voice'; +import { ProjectSection } from './components/project'; +import { ToolsSection } from './components/tools'; +import { Panel } from "@/components/common/panel-common"; +import { Settings, Wrench, Phone } from "lucide-react"; +import { clsx } from "clsx"; export const metadata: Metadata = { title: "Project config", @@ -791,19 +796,46 @@ function NavigationMenu({ selected: string; onSelect: (page: string) => void; }) { - const items = ['Project', 'Tools', 'Voice']; + const items = [ + { id: 'Project', icon: }, + { id: 'Tools', icon: }, + { id: 'Voice', icon: } + ]; return ( - - {items.map((item) => ( - onSelect(item)} - /> - ))} - + + + Settings + + } + > +
+
+ {items.map((item) => ( +
+ +
+ ))} +
+
+
); } @@ -822,26 +854,60 @@ export function ConfigApp({ switch (selectedPage) { case 'Project': return ( -
- - - - - - {useChatWidget && } - +
+ + + Project Settings +
+ } + > +
+ +
+
); case 'Tools': return (
- + + + Tools Configuration +
+ } + > +
+ +
+ ); case 'Voice': return (
- + + + Voice Configuration +
+ } + > +
+ +
+ ); default: @@ -851,13 +917,13 @@ export function ConfigApp({ return ( - + - + {renderContent()} diff --git a/apps/rowboat/app/projects/[projectId]/config/components/project.tsx b/apps/rowboat/app/projects/[projectId]/config/components/project.tsx new file mode 100644 index 00000000..18781eac --- /dev/null +++ b/apps/rowboat/app/projects/[projectId]/config/components/project.tsx @@ -0,0 +1,527 @@ +'use client'; + +import { ReactNode, useEffect, useState, useCallback } from "react"; +import { Spinner, Dropdown, Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Input, useDisclosure } from "@heroui/react"; +import { Button } from "@/components/ui/button"; +import { Textarea } from "@/components/ui/textarea"; +import { getProjectConfig, updateProjectName, createApiKey, deleteApiKey, listApiKeys, deleteProject, rotateSecret } from "../../../../actions/project_actions"; +import { CopyButton } from "../../../../../components/common/copy-button"; +import { EyeIcon, EyeOffIcon, PlusIcon, Trash2Icon } from "lucide-react"; +import { WithStringId } from "../../../../lib/types/types"; +import { ApiKey } from "../../../../lib/types/project_types"; +import { z } from "zod"; +import { RelativeTime } from "@primer/react"; +import { Label } from "../../../../lib/components/label"; +import { sectionHeaderStyles, sectionDescriptionStyles } from './shared-styles'; +import { clsx } from "clsx"; + +export function Section({ + title, + children, + description, +}: { + title: string; + children: React.ReactNode; + description?: string; +}) { + return ( +
+
+

{title}

+ {description && ( +

{description}

+ )} +
+
{children}
+
+ ); +} + +export function SectionRow({ + children, +}: { + children: ReactNode; +}) { + return
{children}
; +} + +export function LeftLabel({ + label, +}: { + label: string; +}) { + return