From 01ed2eda18261cb0fb4387e1d2acdebb054a3d71 Mon Sep 17 00:00:00 2001 From: arkml Date: Mon, 25 Aug 2025 20:16:02 +0530 Subject: [PATCH 1/8] use env variable for showing pre-built cards --- apps/rowboat/app/lib/feature_flags.ts | 1 - .../app/projects/components/build-assistant-section.tsx | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rowboat/app/lib/feature_flags.ts b/apps/rowboat/app/lib/feature_flags.ts index f2ddd7bd..0634c83a 100644 --- a/apps/rowboat/app/lib/feature_flags.ts +++ b/apps/rowboat/app/lib/feature_flags.ts @@ -18,4 +18,3 @@ export const SHOW_COPILOT_MARQUEE = false; export const SHOW_PROMPTS_SECTION = true; export const SHOW_DARK_MODE_TOGGLE = false; export const SHOW_VISUALIZATION = false; -export const SHOW_PREBUILT_CARDS = false; \ No newline at end of file diff --git a/apps/rowboat/app/projects/components/build-assistant-section.tsx b/apps/rowboat/app/projects/components/build-assistant-section.tsx index 50809578..94200964 100644 --- a/apps/rowboat/app/projects/components/build-assistant-section.tsx +++ b/apps/rowboat/app/projects/components/build-assistant-section.tsx @@ -16,7 +16,8 @@ import { Tabs, Tab } from "@/components/ui/tabs"; import { Project } from "@/src/entities/models/project"; import { z } from "zod"; import Link from 'next/link'; -import { SHOW_PREBUILT_CARDS } from '@/app/lib/feature_flags'; + +const SHOW_PREBUILT_CARDS = process.env.NEXT_PUBLIC_SHOW_PREBUILT_CARDS === 'true'; From fbd0d7fae2da4b8a73e9316c5fcb50c62bb23b7a Mon Sep 17 00:00:00 2001 From: arkml Date: Mon, 25 Aug 2025 20:22:08 +0530 Subject: [PATCH 2/8] remove direct rag tool mentions from copilot --- apps/rowboat/src/application/lib/copilot/copilot_multi_agent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/rowboat/src/application/lib/copilot/copilot_multi_agent.ts b/apps/rowboat/src/application/lib/copilot/copilot_multi_agent.ts index b363c072..3b98903e 100644 --- a/apps/rowboat/src/application/lib/copilot/copilot_multi_agent.ts +++ b/apps/rowboat/src/application/lib/copilot/copilot_multi_agent.ts @@ -172,7 +172,7 @@ You should use the name and description to understand the data source, and use t 'ragDataSources' = ["6822e76aa1358752955a455e"] -Once you add the datasource ID to the agent, add a section to the agent instructions called RAG. Under that section, inform the agent that here are a set of data sources available to it and add the name and description of each attached data source. Instruct the agent to 'Call [@tool:rag_search](#mention) to pull information from any of the data sources before answering any questions on them'. +Once you add the datasource ID to the agent, add a section to the agent instructions called RAG. Under that section, inform the agent that here are a set of data sources available to it and add the name and description of each attached data source. Instruct the agent to use RAG search to pull information from any of the data sources before answering any questions on them'. Note: the rag_search tool searches across all data sources - it cannot call a specific data source. From b73f3aa73224101fd4f058a6ce380166464ec414 Mon Sep 17 00:00:00 2001 From: akhisud3195 Date: Tue, 26 Aug 2025 17:07:29 +0530 Subject: [PATCH 3/8] Add toolkit logos for composio tool copilot cards --- .../copilot/components/actions.tsx | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx b/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx index e67ca589..94f8126f 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx @@ -8,6 +8,7 @@ import { PreviewModalProvider, usePreviewModal } from '../../workflow/preview-mo import { getAppliedChangeKey } from "../app"; import { AlertTriangleIcon, CheckCheckIcon, CheckIcon, ChevronsDownIcon, ChevronsUpIcon, EyeIcon, PencilIcon, PlusIcon } from "lucide-react"; import { Spinner } from "@heroui/react"; +import { PictureImg } from "@/components/ui/picture-img"; const ActionContext = createContext<{ msgIndex: number; @@ -158,6 +159,33 @@ export function Action({ ); } + // Determine composio toolkit logo for tools + const toolkitLogo = (() => { + if (action.config_type !== 'tool') return undefined; + const getLogo = (o: any): string | undefined => { + return ( + o?.composioData?.logo || + o?.composioData?.logoUrl || + o?.composio?.logo || + o?.toolkit?.logo || + o?.composio_tool?.toolkit?.logo || + o?.logo || + undefined + ); + }; + // Try various shapes the action might use + const a: any = action as any; + return ( + getLogo(a.config_changes) || + getLogo(a) || + getLogo(a.config_changes?.tool) || + getLogo(a.config_changes?.composio_tool) || + getLogo(a.tool) || + (workflow.tools.find(t => t.name === action.name) as any)?.composioData?.logo || + undefined + ); + })(); + return
- {/* Small colored icon for type */} + {/* Small colored icon for type; show composio toolkit logo for tools when available */} - {action.config_type === 'agent' ? 'πŸ§‘β€πŸ’Ό' : action.config_type === 'tool' ? 'πŸ› οΈ' : action.config_type === 'pipeline' ? 'βš™οΈ' : action.config_type === 'start_agent' ? '🏁' : action.config_type === 'prompt' ? 'πŸ’¬' : 'πŸ’¬'} + {action.config_type === 'tool' && toolkitLogo ? ( + + ) : ( + action.config_type === 'agent' ? 'πŸ§‘β€πŸ’Ό' : action.config_type === 'tool' ? 'πŸ› οΈ' : action.config_type === 'pipeline' ? 'βš™οΈ' : action.config_type === 'start_agent' ? '🏁' : action.config_type === 'prompt' ? 'πŸ’¬' : 'πŸ’¬' + )} {action.action === 'create_new' ? 'Add' : action.action === 'edit' ? 'Edit' : 'Delete'} {action.config_type}: {action.name} From 1cf8bd01def19f0e3f4b97ee268b36106cd0ec70 Mon Sep 17 00:00:00 2001 From: akhisud3195 Date: Tue, 26 Aug 2025 22:07:12 +0530 Subject: [PATCH 4/8] Update copilot loading states --- .../app/projects/[projectId]/copilot/app.tsx | 12 ++---------- .../copilot/components/messages.tsx | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/apps/rowboat/app/projects/[projectId]/copilot/app.tsx b/apps/rowboat/app/projects/[projectId]/copilot/app.tsx index 2e901e7f..b3704a15 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/app.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/app.tsx @@ -265,18 +265,10 @@ const App = forwardRef<{ handleCopyChat: () => void; handleUserMessage: (message workflow={workflowRef.current} dispatch={dispatch} onStatusBarChange={handleStatusBarChange} + toolCalling={toolCalling} + toolQuery={toolQuery} />
- {toolCalling && ( -
-
- - - Searching for tools{toolQuery ? ` to ${toolQuery}` : '...'} - -
-
- )}
{responseError && (
diff --git a/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx b/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx index c0e9865c..08db50cd 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/components/messages.tsx @@ -507,7 +507,9 @@ export function Messages({ loadingResponse, workflow, dispatch, - onStatusBarChange + onStatusBarChange, + toolCalling, + toolQuery }: { messages: z.infer[]; streamingResponse: string; @@ -515,6 +517,8 @@ export function Messages({ workflow: z.infer; dispatch: (action: any) => void; onStatusBarChange?: (status: any) => void; + toolCalling?: boolean; + toolQuery?: string | null; }) { const messagesEndRef = useRef(null); const [displayMessages, setDisplayMessages] = useState(messages); @@ -582,11 +586,15 @@ export function Messages({ {renderMessage(message, index)}
))} - {loadingResponse && ( -
- + {!streamingResponse && (toolCalling ? ( +
+ Searching for tools{toolQuery ? ` to ${toolQuery}` : ''}...
- )} + ) : loadingResponse ? ( +
+ Thinking... +
+ ) : null)}
From ec408732129466e454a624da7d176b5189927684 Mon Sep 17 00:00:00 2001 From: akhisud3195 Date: Tue, 26 Aug 2025 22:27:58 +0530 Subject: [PATCH 5/8] Update copilot action cards loading states --- .../copilot/components/actions.tsx | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx b/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx index 94f8126f..62eb2237 100644 --- a/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx +++ b/apps/rowboat/app/projects/[projectId]/copilot/components/actions.tsx @@ -1,5 +1,5 @@ 'use client'; -import { createContext, useContext, useRef, useState } from "react"; +import { createContext, useContext, useRef, useState, useEffect } from "react"; import clsx from "clsx"; import { z } from "zod"; import { CopilotAssistantMessageActionPart } from "../../../../../src/entities/models/copilot"; @@ -384,6 +384,17 @@ export function StreamingAction({ }; loading: boolean; }) { + const [loadingStage, setLoadingStage] = useState<'fetching' | 'configuring'>('fetching'); + + // After 3 seconds, switch to "configuring" stage + useEffect(() => { + const timer = setTimeout(() => { + setLoadingStage('configuring'); + }, 3000); + + return () => clearTimeout(timer); + }, []); + // Use the same card container and header style as Action return (
- Loading... + + {loadingStage === 'fetching' + ? (action.config_type === 'agent' + ? `Creating agent...` + : action.config_type === 'pipeline' + ? `Creating pipeline...` + : `Fetching ${action.config_type} definition...`) + : (action.config_type === 'agent' + ? `Configuring agent...` + : action.config_type === 'pipeline' + ? `Configuring pipeline...` + : `Configuring ${action.config_type}...`) + } +
); From 463630cc0a256a9652c6d84bab817190e77a9c37 Mon Sep 17 00:00:00 2001 From: akhisud3195 Date: Wed, 27 Aug 2025 20:52:31 +0530 Subject: [PATCH 6/8] Upgrade composio package and update no_auth logic --- apps/rowboat/package-lock.json | 229 +----------------- apps/rowboat/package.json | 2 +- .../src/application/lib/composio/composio.ts | 104 +++++++- 3 files changed, 114 insertions(+), 221 deletions(-) diff --git a/apps/rowboat/package-lock.json b/apps/rowboat/package-lock.json index 020e1b98..5e92e600 100644 --- a/apps/rowboat/package-lock.json +++ b/apps/rowboat/package-lock.json @@ -12,7 +12,7 @@ "@auth0/nextjs-auth0": "^4.7.0", "@aws-sdk/client-s3": "^3.743.0", "@aws-sdk/s3-request-presigner": "^3.743.0", - "@composio/core": "^0.1.40", + "@composio/core": "^0.1.48", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", @@ -1447,16 +1447,16 @@ "license": "Apache-2.0" }, "node_modules/@composio/core": { - "version": "0.1.41", - "resolved": "https://registry.npmjs.org/@composio/core/-/core-0.1.41.tgz", - "integrity": "sha512-wodFzWduAZ+7i08exCRDj5/0uDrQbNNrTA36EdBZE6T6+gzxH9GMnZmGXcg9WvU8dQSx/hWiJAyjp1IF4gGMtA==", + "version": "0.1.48", + "resolved": "https://registry.npmjs.org/@composio/core/-/core-0.1.48.tgz", + "integrity": "sha512-zTzxrdaOlzlBjjolJ+n/5xGBDrBP3Qr4lwgq37CZjTmJQ5T2Ypk6uvcNV1HkYq7cAXNGU+ojzFryNDkkNCfT3A==", "license": "ISC", "dependencies": { "@composio/client": "0.1.0-alpha.31", - "@composio/json-schema-to-zod": "0.1.11", + "@composio/json-schema-to-zod": "0.1.13", "@types/json-schema": "^7.0.15", "chalk": "^4.1.2", - "openai": "^4.94.0", + "openai": "^5.16.0", "pusher-js": "^8.4.0", "semver": "^7.7.2", "uuid": "^11.1.0", @@ -1478,9 +1478,9 @@ } }, "node_modules/@composio/json-schema-to-zod": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@composio/json-schema-to-zod/-/json-schema-to-zod-0.1.11.tgz", - "integrity": "sha512-6gcCof9xqLhmmHSCvWLW/E16PKr5C1dWJ9AOk4FJU8JA7gSt8JEdFHBwx80dyprBJdwPF6R54nlkmpXrEwApzg==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/@composio/json-schema-to-zod/-/json-schema-to-zod-0.1.13.tgz", + "integrity": "sha512-M/pppyhshlWB/5S6hjocFYYFCm9sFK1y9dTm70MpYl2EGJtpYDgwUeS9cFIzml+Iw/MUebr0wCJ0c+jOYeDU/A==", "license": "ISC", "dependencies": { "@types/json-schema": "^7.0.15", @@ -4445,26 +4445,6 @@ } } }, - "node_modules/@openai/agents-core/node_modules/openai": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-5.12.2.tgz", - "integrity": "sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/@openai/agents-extensions": { "version": "0.0.15", "resolved": "https://registry.npmjs.org/@openai/agents-extensions/-/agents-extensions-0.0.15.tgz", @@ -4491,26 +4471,6 @@ "openai": "^5.10.1" } }, - "node_modules/@openai/agents-openai/node_modules/openai": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-5.12.2.tgz", - "integrity": "sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/@openai/agents-realtime": { "version": "0.0.15", "resolved": "https://registry.npmjs.org/@openai/agents-realtime/-/agents-realtime-0.0.15.tgz", @@ -4523,26 +4483,6 @@ "ws": "^8.18.1" } }, - "node_modules/@openai/agents/node_modules/openai": { - "version": "5.12.2", - "resolved": "https://registry.npmjs.org/openai/-/openai-5.12.2.tgz", - "integrity": "sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==", - "bin": { - "openai": "bin/cli" - }, - "peerDependencies": { - "ws": "^8.18.0", - "zod": "^3.23.8" - }, - "peerDependenciesMeta": { - "ws": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/@openai/zod": { "name": "zod", "version": "3.25.67", @@ -7606,15 +7546,6 @@ "undici-types": "~5.26.4" } }, - "node_modules/@types/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.0" - } - }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -8005,17 +7936,6 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -8079,17 +7999,6 @@ "node": ">= 6.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/ai": { "version": "4.3.13", "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.13.tgz", @@ -10605,14 +10514,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", @@ -11004,23 +10905,6 @@ "node": ">= 6" } }, - "node_modules/form-data-encoder": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", - "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" - }, - "node_modules/formdata-node": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", - "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", - "dependencies": { - "node-domexception": "1.0.0", - "web-streams-polyfill": "4.0.0-beta.3" - }, - "engines": { - "node": ">= 12.20" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -11465,14 +11349,6 @@ "node": ">= 6" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", @@ -14587,62 +14463,6 @@ "tslib": "^2.0.3" } }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -14795,19 +14615,10 @@ } }, "node_modules/openai": { - "version": "4.104.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz", - "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-5.16.0.tgz", + "integrity": "sha512-hoEH8ZNvg1HXjU9mp88L/ZH8O082Z8r6FHCXGiWAzVRrEv443aI57qhch4snu07yQydj+AUAWLenAiBXhu89Tw==", "license": "Apache-2.0", - "dependencies": { - "@types/node": "^18.11.18", - "@types/node-fetch": "^2.6.4", - "abort-controller": "^3.0.0", - "agentkeepalive": "^4.2.1", - "form-data-encoder": "1.7.2", - "formdata-node": "^4.3.2", - "node-fetch": "^2.6.7" - }, "bin": { "openai": "bin/cli" }, @@ -14824,14 +14635,6 @@ } } }, - "node_modules/openai/node_modules/@types/node": { - "version": "18.19.54", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.54.tgz", - "integrity": "sha512-+BRgt0G5gYjTvdLac9sIeE0iZcJxi4Jc4PV5EUzqi+88jmQLr+fRZdv2tCTV7IHKSGxM6SaLoOXQWWUiLUItMw==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -17274,14 +17077,6 @@ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" }, - "node_modules/web-streams-polyfill": { - "version": "4.0.0-beta.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", - "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", - "engines": { - "node": ">= 14" - } - }, "node_modules/web-vitals": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", diff --git a/apps/rowboat/package.json b/apps/rowboat/package.json index ff5d8f61..5df95733 100644 --- a/apps/rowboat/package.json +++ b/apps/rowboat/package.json @@ -20,7 +20,7 @@ "@auth0/nextjs-auth0": "^4.7.0", "@aws-sdk/client-s3": "^3.743.0", "@aws-sdk/s3-request-presigner": "^3.743.0", - "@composio/core": "^0.1.40", + "@composio/core": "^0.1.48", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", diff --git a/apps/rowboat/src/application/lib/composio/composio.ts b/apps/rowboat/src/application/lib/composio/composio.ts index 057a14cc..d18ba8ff 100644 --- a/apps/rowboat/src/application/lib/composio/composio.ts +++ b/apps/rowboat/src/application/lib/composio/composio.ts @@ -74,13 +74,111 @@ export async function listTools(toolkitSlug: string, searchQuery: string | null url.searchParams.set("cursor", cursor); } - // fetch - return composioApiCall(ZListResponse(ZTool), url.toString()); + // First get the tools list response + const toolsResponse = await fetch(url.toString(), { + headers: { + "x-api-key": COMPOSIO_API_KEY, + }, + }); + + if (!toolsResponse.ok) { + throw new Error(`Failed to fetch tools list: ${toolsResponse.status} ${toolsResponse.statusText}`); + } + + const toolsData = await toolsResponse.json(); + + // Check for error response + if ('error' in toolsData) { + const response = ZErrorResponse.parse(toolsData); + throw new Error(`(code: ${response.error.error_code}): ${response.error.message}: ${response.error.suggested_fix}: ${response.error.errors?.join(', ')}`); + } + + // Get toolkit data to compute no_auth for all tools + const toolkitUrl = new URL(`${BASE_URL}/toolkits/${toolkitSlug}`); + const toolkitResponse = await fetch(toolkitUrl.toString(), { + headers: { + "x-api-key": COMPOSIO_API_KEY, + }, + }); + + if (!toolkitResponse.ok) { + throw new Error(`Failed to fetch toolkit: ${toolkitResponse.status} ${toolkitResponse.statusText}`); + } + + const toolkitData = await toolkitResponse.json(); + + // Compute no_auth from toolkit data + const no_auth = toolkitData.composio_managed_auth_schemes?.includes('NO_AUTH') || + toolkitData.auth_config_details?.some((config: any) => config.mode === 'NO_AUTH') || + false; + + // Enrich all tools in the list with computed no_auth + const enrichedToolsData = { + ...toolsData, + items: toolsData.items.map((tool: any) => ({ + ...tool, + no_auth + })) + }; + + // Now parse with our schema + return ZListResponse(ZTool).parse(enrichedToolsData); } export async function getTool(toolSlug: string): Promise> { const url = new URL(`${BASE_URL}/tools/${toolSlug}`); - return composioApiCall(ZTool, url.toString()); + + // First get the tool response + const toolResponse = await fetch(url.toString(), { + headers: { + "x-api-key": COMPOSIO_API_KEY, + }, + }); + + if (!toolResponse.ok) { + throw new Error(`Failed to fetch tool: ${toolResponse.status} ${toolResponse.statusText}`); + } + + const toolData = await toolResponse.json(); + + // Check for error response + if ('error' in toolData) { + const response = ZErrorResponse.parse(toolData); + throw new Error(`(code: ${response.error.error_code}): ${response.error.message}: ${response.error.suggested_fix}: ${response.error.errors?.join(', ')}`); + } + + // Get toolkit data to compute no_auth + const toolkitSlug = toolData.toolkit?.slug; + if (!toolkitSlug) { + throw new Error(`Tool response missing toolkit slug: ${JSON.stringify(toolData)}`); + } + + const toolkitUrl = new URL(`${BASE_URL}/toolkits/${toolkitSlug}`); + const toolkitResponse = await fetch(toolkitUrl.toString(), { + headers: { + "x-api-key": COMPOSIO_API_KEY, + }, + }); + + if (!toolkitResponse.ok) { + throw new Error(`Failed to fetch toolkit: ${toolkitResponse.status} ${toolkitResponse.statusText}`); + } + + const toolkitData = await toolkitResponse.json(); + + // Compute no_auth from toolkit data + const no_auth = toolkitData.composio_managed_auth_schemes?.includes('NO_AUTH') || + toolkitData.auth_config_details?.some((config: any) => config.mode === 'NO_AUTH') || + false; + + // Inject computed no_auth into tool data + const enrichedToolData = { + ...toolData, + no_auth + }; + + // Now parse with our schema + return ZTool.parse(enrichedToolData); } export async function listAuthConfigs(toolkitSlug: string, cursor: string | null = null, managedOnly: boolean = false): Promise>>> { From 82982eaec83c8ca5b19a6d640fcb8cf0187582f1 Mon Sep 17 00:00:00 2001 From: Tushar <47842976+tusharmagar@users.noreply.github.com> Date: Thu, 28 Aug 2025 12:22:13 +0530 Subject: [PATCH 7/8] docs: improve documentation content (#223) --- apps/docs/docs.json | 2 +- apps/docs/docs/api-sdk/using_the_sdk.mdx | 134 ++++++++---------- .../docs/development/contribution-guide.mdx | 2 +- .../docs/getting-started/introduction.mdx | 10 +- apps/docs/docs/getting-started/quickstart.mdx | 2 +- apps/docs/docs/index.md | 2 +- apps/docs/docs/using-rowboat/tools.mdx | 10 +- 7 files changed, 80 insertions(+), 82 deletions(-) diff --git a/apps/docs/docs.json b/apps/docs/docs.json index 206579f0..6dc8d714 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -68,7 +68,7 @@ "socials": { "github": "https://github.com/rowboatlabs/rowboat", "linkedin": "https://www.linkedin.com/company/rowboat-labs", - "discord": "https://discord.gg/PCkH9TWC" + "discord": "https://discord.gg/rxB8pzHxaS" } }, "contextual": { diff --git a/apps/docs/docs/api-sdk/using_the_sdk.mdx b/apps/docs/docs/api-sdk/using_the_sdk.mdx index 56a61f99..0909224f 100644 --- a/apps/docs/docs/api-sdk/using_the_sdk.mdx +++ b/apps/docs/docs/api-sdk/using_the_sdk.mdx @@ -15,87 +15,77 @@ icon: "toolbox" ## Usage -### Basic Usage with StatefulChat +### Basic Usage -The easiest way to interact with Rowboat is using the `StatefulChat` class, which maintains conversation state automatically: - -```python -from rowboat import Client, StatefulChat - -# Initialize the client -client = Client( - host="", - project_id="", - api_key="" -) - -# Create a stateful chat session -chat = StatefulChat(client) - -# Have a conversation -response = chat.run("What is the capital of France?") -print(response) -# The capital of France is Paris. - -# Continue the conversation - the context is maintained automatically -response = chat.run("What other major cities are in that country?") -print(response) -# Other major cities in France include Lyon, Marseille, Toulouse, and Nice. - -response = chat.run("What's the population of the first city you mentioned?") -print(response) -# Lyon has a population of approximately 513,000 in the city proper. -``` - -### Advanced Usage - -#### Using a specific workflow - -You can specify a workflow ID to use a particular conversation configuration: - -```python -chat = StatefulChat( - client, - workflow_id="" -) -``` - -#### Using a test profile - -You can specify a test profile ID to use a specific test configuration: - -```python -chat = StatefulChat( - client, - test_profile_id="" -) -``` - -### Low-Level Usage - -For more control over the conversation, you can use the `Client` class directly: +The main way to interact with Rowboat is using the `Client` class, which provides a stateless chat API. You can manage conversation state using the `conversationId` returned in each response. ```python +from rowboat.client import Client from rowboat.schema import UserMessage # Initialize the client client = Client( host="", - project_id="", - api_key="" + projectId="", + apiKey="" ) -# Create messages -messages = [ - UserMessage(role='user', content="Hello, how are you?") -] +# Start a new conversation +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What is the capital of France?") + ] +) +print(result.turn.output[-1].content) +# The capital of France is Paris. -# Get response -response = client.chat(messages=messages) -print(response.messages[-1].content) +print("Conversation ID:", result.conversationId) -# For subsequent messages, you need to manage the message history and state manually -messages.extend(response.messages) -messages.append(UserMessage(role='user', content="What's your name?")) -response = client.chat(messages=messages, state=response.state) -``` \ No newline at end of file +# Continue the conversation by passing the conversationId +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What other major cities are in that country?") + ], + conversationId=result.conversationId +) +print(result.turn.output[-1].content) +# Other major cities in France include Lyon, Marseille, Toulouse, and Nice. + +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What's the population of the first city you mentioned?") + ], + conversationId=result.conversationId +) +print(result.turn.output[-1].content) +# Lyon has a population of approximately 513,000 in the city proper. +``` + +### Using Tool Overrides (Mock Tools) + +You can provide tool override instructions to test a specific configuration using the `mockTools` argument: + +```python +result = client.run_turn( + messages=[ + UserMessage(role='user', content="What's the weather?") + ], + mockTools={ + "weather_lookup": "The weather in any city is sunny and 25Β°C.", + "calculator": "The result of any calculation is 42." + } +) +print(result.turn.output[-1].content) +``` + +### Message Types + +You can use different message types as defined in `rowboat.schema`, such as `UserMessage`, `SystemMessage`, `AssistantMessage`, etc. See `schema.py` for all available message types. + +### Error Handling + +If the API returns a non-200 status code, a `ValueError` will be raised with the error details. + +--- + +For more advanced usage, see the docstrings in `client.py` and the message schemas in `schema.py`. \ No newline at end of file diff --git a/apps/docs/docs/development/contribution-guide.mdx b/apps/docs/docs/development/contribution-guide.mdx index ce65e4bd..94d0f46c 100644 --- a/apps/docs/docs/development/contribution-guide.mdx +++ b/apps/docs/docs/development/contribution-guide.mdx @@ -21,7 +21,7 @@ We're building Rowboat as an open-source, community-powered platform β€” and we' Browse our [GitHub Issues](https://github.com/rowboatlabs/rowboat/issues) for tags like `good first issue`, `help wanted`, or `bug` to find a spot that fits your skillset. - **Join the Community** - Our [Discord](https://discord.gg/PCkH9TWC) is the go-to hub for brainstorming, feedback, and finding contributors for bigger efforts. + Our [Discord](https://discord.gg/rxB8pzHxaS) is the go-to hub for brainstorming, feedback, and finding contributors for bigger efforts. - **Propose Something New** Have a new tool integration idea or found a bug? Open an issue and let’s discuss it! diff --git a/apps/docs/docs/getting-started/introduction.mdx b/apps/docs/docs/getting-started/introduction.mdx index f2e138b8..8fde54db 100644 --- a/apps/docs/docs/getting-started/introduction.mdx +++ b/apps/docs/docs/getting-started/introduction.mdx @@ -1,6 +1,6 @@ --- title: "Introduction" -description: "Welcome to the official Rowboat documentation! Rowboat is a low-code AI IDE to build MCP tools connected multi-agent assistants. Rowboat copilot builds the agents for you based on your requirements with the option do everything manually as well." +description: "Welcome to the official Rowboat documentation! Rowboat is a low-code AI IDE to build tool connected multi-agent assistants. Rowboat copilot builds the agents for you based on your requirements with the option do everything manually as well." icon: "book-open" --- @@ -11,9 +11,9 @@ icon: "book-open" ## What is RowBoat? **RowBoat is a state-of-art platform to build multi-agent AI systems in a visual interface, with the help of a copilot.** -RowBoat enables you to build, manage and deploy user-facing assistants. An assistant is made up of multiple agents, each having access to a set of tools and working together to interact with the user as a single assistant. You can connect any MCP tools to the agents. +RowBoat enables you to build, manage and deploy user-facing assistants. An assistant is made up of multiple agents, each having access to a set of tools and working together to interact with the user as a single assistant. You can connect any tool to the agents. -For example, you can build a *credit card assistant*, where each agent handles a workflow such as *outstanding payments*, *balance inquiries* and *transaction disputes*. You can equip agents with tools to carry out tasks such as *fetching payment options*, *checking outstanding balance* and *updating user information*. The assistant would help your end-users their credit card-related needs without having to talk to a human agent on your end. +For example, you can build a *meeting prep assistant* that helps you prepare for upcoming meetings. One agent can access your Google Calendar to see your scheduled meetings, another agent can research the meeting attendees (such as finding their LinkedIn profiles or recent news), and a third agent can compile this research and send it to your email before the meeting. This way, you get automated, personalized meeting prep without manual effort. --- @@ -34,12 +34,12 @@ There are key components that you will work with: ### RowBoat Chat API & SDK - [RowBoat Chat API](/docs/api-sdk/using_the_api) is a stateless HTTP API to interface with the assistant created on RowBoat Studio. You can use the API to drive end-user facing conversations in your app or website. -- [RowBoat Chat SDK](/docs/api-sdk/using_the_sdk) is a simple SDK (currently available in Python) which wraps the HTTP API under the hood. It offers both stateful and stateless (OpenAI-style) implementations. +- [RowBoat Chat SDK](/docs/api-sdk/using_the_sdk) is a simple Python SDK which wraps the HTTP API under the hood. It provides a clean interface for managing conversations using conversation IDs for state management. --- ## Why RowBoat? -Rowboat is the fastest way to build and deploy MCP connected multi-agents +Rowboat is the fastest way to build and deploy multi-agent assistants. diff --git a/apps/docs/docs/getting-started/quickstart.mdx b/apps/docs/docs/getting-started/quickstart.mdx index 6350830f..04fc761b 100644 --- a/apps/docs/docs/getting-started/quickstart.mdx +++ b/apps/docs/docs/getting-started/quickstart.mdx @@ -41,7 +41,7 @@ Using the open-source version of Rowboat requires more technical skill to set up ```bash git clone git@github.com:rowboatlabs/rowboat.git cd rowboat - docker-compose up --build + ./start.sh ``` diff --git a/apps/docs/docs/index.md b/apps/docs/docs/index.md index 89626228..21954713 100644 --- a/apps/docs/docs/index.md +++ b/apps/docs/docs/index.md @@ -5,7 +5,7 @@ Rowboat is a low-code AI IDE to build MCP tools connected multi-agent assistants **Note:** These docs are intended for developers who would like to use our [open-source code](https://github.com/rowboatlabs/rowboat/). - Our source code is on GitHub at [@rowboatlabs/rowboat](https://github.com/rowboatlabs/rowboat/) -- Join us on [discord](https://discord.gg/jHhUKkKHn8) +- Join us on [discord](https://discord.gg/rxB8pzHxaS) - Email us at [founders@rowboatlabs.com](mailto:founders@rowboatlabs.com) - Visit our [website](https://www.rowboatlabs.com/) diff --git a/apps/docs/docs/using-rowboat/tools.mdx b/apps/docs/docs/using-rowboat/tools.mdx index fec92609..7a116d63 100644 --- a/apps/docs/docs/using-rowboat/tools.mdx +++ b/apps/docs/docs/using-rowboat/tools.mdx @@ -26,9 +26,17 @@ The Tools page in Rowboat lets you add and configure tools that your agents can - Browse a library of 500+ toolkits from popular services - With 3000+ tools to choose from! - Click on a service to see available tools and add them to your workflow -- Users must create a Composio account and add their API key +- Users must create a [Composio](https://composio.dev/) account and add their API key - Tools require authorization to work properly +### Setting up Composio API Key + +To use Composio tools, get a Composio key and export it as an environment variable: + +```bash +export COMPOSIO_API_KEY=your_api_key_here +``` + Users can visit [Composio's toolkit documentation](https://docs.composio.dev/toolkits/introduction) for a deep dive into all the tools available. ## Custom MCP Servers From 49e67115e6eca1a293dbe15b1c12a0e1aff966d8 Mon Sep 17 00:00:00 2001 From: Tushar <47842976+tusharmagar@users.noreply.github.com> Date: Mon, 1 Sep 2025 16:13:45 +0530 Subject: [PATCH 8/8] Fix copiot pipeline workflow editor (#226) * Fix copiot pipeline workflow editor * added the defaultModel usage --- .../[projectId]/workflow/workflow_editor.tsx | 103 ++++++++++++------ 1 file changed, 69 insertions(+), 34 deletions(-) diff --git a/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx b/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx index 1e1c6268..a1ab84fd 100644 --- a/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx +++ b/apps/rowboat/app/projects/[projectId]/workflow/workflow_editor.tsx @@ -91,6 +91,7 @@ export type Action = { } | { type: "add_pipeline"; pipeline: Partial>; + defaultModel?: string; } | { type: "select_agent"; name: string; @@ -437,50 +438,84 @@ function reducer(state: State, action: Action): State { draft.chatKey++; break; } + // TODO: parameterize this instead of writing if else based on pipeline length (pipelineAgents.length) case "add_pipeline": { if (isLive) { break; } - let newPipelineName = "New pipeline"; - if (draft.workflow?.pipelines?.some((pipeline) => pipeline.name === newPipelineName)) { - newPipelineName = `New pipeline ${(draft.workflow?.pipelines?.filter((pipeline) => - pipeline.name.startsWith("New pipeline")).length || 0) + 1}`; - } + if (!draft.workflow.pipelines) { draft.workflow.pipelines = []; } - // Create the first agent for this pipeline - const firstAgentName = `${action.pipeline.name || newPipelineName} Step 1`; - draft.workflow.agents.push({ - name: firstAgentName, - type: "pipeline", - description: "", - disabled: false, - instructions: "", - model: "gpt-4o", - locked: false, - toggleAble: true, - ragReturnType: "chunks", - ragK: 3, - controlType: "relinquish_to_parent", - outputVisibility: "internal", - maxCallsPerParentAgent: 3, - }); + // 1. βœ… Create the pipeline definition FIRST with the action data + const pipelineName = action.pipeline.name || "New pipeline"; + const pipelineDescription = action.pipeline.description || ""; + let pipelineAgents = action.pipeline.agents || []; - // Create the pipeline with the first agent + // 2. βœ… Handle manual creation (no agents provided) vs copilot creation (agents provided) + if (pipelineAgents.length === 0) { + // Manual creation: create a default first agent to prevent 0-step pipelines + const defaultAgentName = `${pipelineName} Step 1`; + pipelineAgents = [defaultAgentName]; + + // Create the default agent + draft.workflow.agents.push({ + name: defaultAgentName, + type: "pipeline", + description: `Default agent for ${pipelineName} pipeline`, + disabled: false, + instructions: `You are the first step in the ${pipelineName} pipeline. Focus on your specific role.`, + model: action.defaultModel || "gpt-4.1", + locked: false, + toggleAble: true, + ragReturnType: "chunks", + ragK: 3, + controlType: "relinquish_to_parent", + outputVisibility: "internal", + maxCallsPerParentAgent: 3, + }); + } else { + // Copilot creation: ensure all referenced agents exist + for (const agentName of pipelineAgents) { + const existingAgent = draft.workflow.agents.find(a => a.name === agentName); + if (!existingAgent) { + // Create the agent with proper pipeline type + draft.workflow.agents.push({ + name: agentName, + type: "pipeline", + description: `Agent for ${pipelineName} pipeline`, + disabled: false, + instructions: `You are part of the ${pipelineName} pipeline. Focus on your specific role.`, + model: action.defaultModel || "gpt-4.1", + locked: false, + toggleAble: true, + ragReturnType: "chunks", + ragK: 3, + controlType: "relinquish_to_parent", + outputVisibility: "internal", + maxCallsPerParentAgent: 3, + }); + } + } + } + + // 3. βœ… Create the pipeline with the agents draft.workflow.pipelines.push({ - name: newPipelineName, - description: "", - agents: [firstAgentName], + name: pipelineName, + description: pipelineDescription, + agents: pipelineAgents, ...action.pipeline }); - // Select the newly created agent to open it in agent_config - draft.selection = { - type: "agent", - name: firstAgentName - }; + // 4. βœ… Select the first agent for configuration + if (pipelineAgents.length > 0) { + draft.selection = { + type: "agent", + name: pipelineAgents[0] + }; + } + draft.pendingChanges = true; draft.chatKey++; break; @@ -1056,7 +1091,7 @@ export function WorkflowEditor({ function handleAddAgent(agent: Partial> = {}) { const agentWithModel = { ...agent, - model: agent.model || defaultModel || "gpt-4o" + model: agent.model || defaultModel || "gpt-4.1" }; dispatch({ type: "add_agent", agent: agentWithModel }); } @@ -1074,7 +1109,7 @@ export function WorkflowEditor({ } function handleAddPipeline(pipeline: Partial> = {}) { - dispatch({ type: "add_pipeline", pipeline }); + dispatch({ type: "add_pipeline", pipeline, defaultModel }); } function handleDeletePipeline(name: string) { @@ -1091,7 +1126,7 @@ export function WorkflowEditor({ name: newAgentName, type: 'pipeline' as const, outputVisibility: 'internal' as const, - model: defaultModel || "gpt-4o" + model: defaultModel || "gpt-4.1" }; // First add the agent