Skip to content
This repository was archived by the owner on Feb 19, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions app/(chat)/api/chat/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,26 @@ export async function POST(request: Request) {

const stream = createDataStream({
execute: async (dataStream) => {
// Log enabled toolkits with connection status
console.log(
'Enabled toolkits with connection status:',
enabledToolkits,
);

// Extract just the slugs for the getComposioTools function
const toolkitSlugs = enabledToolkits?.map((t) => t.slug) || [];

// Fetch Composio tools if toolkits are enabled
const composioTools = await getComposioTools(
session.user.id,
enabledToolkits || [],
toolkitSlugs,
);

const result = streamText({
model: myProvider.languageModel(selectedChatModel),
system: systemPrompt({ selectedChatModel, requestHints }),
messages,
maxSteps: 5,
experimental_activeTools:
selectedChatModel === 'chat-model-reasoning' ? [] : ['getWeather'],
experimental_transform: smoothStream({ chunking: 'word' }),
experimental_generateMessageId: generateUUID,
tools: {
Expand Down
9 changes: 8 additions & 1 deletion app/(chat)/api/chat/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,14 @@ export const postRequestBodySchema = z.object({
}),
selectedChatModel: z.enum(['chat-model', 'chat-model-reasoning']),
selectedVisibilityType: z.enum(['public', 'private']),
enabledToolkits: z.array(z.string()).optional(),
enabledToolkits: z
.array(
z.object({
slug: z.string(),
isConnected: z.boolean(),
}),
)
.optional(),
});

export type PostRequestBody = z.infer<typeof postRequestBodySchema>;
44 changes: 44 additions & 0 deletions app/api/connections/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { NextResponse } from 'next/server';
import { auth } from '@/app/(auth)/auth';
import composio from '@/lib/services/composio';
import { ChatSDKError } from '@/lib/errors';

export async function DELETE(request: Request) {
const session = await auth();

if (!session?.user?.id) {
return new ChatSDKError('unauthorized:chat').toResponse();
}

const { searchParams } = new URL(request.url);
const connectionId = searchParams.get('connectionId');

if (!connectionId) {
return new ChatSDKError(
'bad_request:api',
'Connection ID is required',
).toResponse();
}

try {
// Delete the connection
await composio.connectedAccounts.delete(connectionId);

return NextResponse.json({
success: true,
message: 'Connection deleted successfully',
});
} catch (error) {
console.error('Failed to delete connection:', error);

if (error instanceof Error && 'code' in error) {
// Handle Composio specific errors
return NextResponse.json({ error: error.message }, { status: 400 });
}

return NextResponse.json(
{ error: 'Failed to delete connection' },
{ status: 500 },
);
}
}
17 changes: 12 additions & 5 deletions app/api/toolkits/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,20 @@ export async function GET() {

try {
// Fetch connected accounts for the user
const connectedToolkitSlugs: Set<string> = new Set();
const connectedToolkitMap: Map<string, string> = new Map(); // slug -> connectionId

try {
const connectedAccounts = await composio.connectedAccounts.list({
userIds: [session.user.id],
});

// Extract toolkit slugs from connected accounts
// Extract toolkit slugs and connection IDs from connected accounts
connectedAccounts.items.forEach((account: ConnectedAccount) => {
if (account.toolkit?.slug) {
connectedToolkitSlugs.add(account.toolkit.slug.toUpperCase());
if (account.toolkit?.slug && account.id) {
connectedToolkitMap.set(
account.toolkit.slug.toUpperCase(),
account.id,
);
}
});
} catch (error) {
Expand All @@ -65,13 +68,17 @@ export async function GET() {
const toolkitPromises = SUPPORTED_TOOLKITS.map(async (slug) => {
try {
const toolkit = (await composio.toolkits.get(slug)) as ToolkitResponse;
const upperSlug = slug.toUpperCase();
const connectionId = connectedToolkitMap.get(upperSlug);

return {
name: toolkit.name,
slug: toolkit.slug,
description: toolkit.meta?.description,
logo: toolkit.meta?.logo,
categories: toolkit.meta?.categories,
isConnected: connectedToolkitSlugs.has(slug.toUpperCase()),
isConnected: !!connectionId,
connectionId: connectionId || undefined,
};
} catch (error) {
console.error(`Failed to fetch toolkit ${slug}:`, error);
Expand Down
4 changes: 3 additions & 1 deletion components/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ export function Chat({
message: body.messages.at(-1),
selectedChatModel: initialChatModel,
selectedVisibilityType: visibilityType,
enabledToolkits: Array.from(toolbarState.enabledTools),
enabledToolkits: Array.from(
toolbarState.enabledToolkitsWithStatus.entries(),
).map(([slug, isConnected]) => ({ slug, isConnected })),
}),
onFinish: () => {
mutate(unstable_serialize(getChatHistoryPaginationKey));
Expand Down
Loading
Loading