Initial commit

This commit is contained in:
root
2026-01-26 08:34:48 +01:00
commit 387314581f
216 changed files with 81204 additions and 0 deletions
+189
View File
@@ -0,0 +1,189 @@
/**
* Bot API Routes
*
* POST /api/bots - Create a new bot
* GET /api/bots - List user's bots
*
* Requirements: 1.1, 1.3
*/
import { NextResponse } from 'next/server';
import { requireAuth } from '@/lib/auth';
import { z } from 'zod';
import {
createBot,
getBotsByUser,
BotLimitExceededError,
BotHandleTakenError,
BotValidationError,
} from '@/lib/bots/botManager';
// Schema for creating a bot
const createBotSchema = z.object({
name: z.string().min(1).max(100),
handle: z.string().min(3).max(30).regex(/^[a-zA-Z0-9_]+$/, 'Handle must be alphanumeric and underscores only'),
bio: z.string().max(500).optional(),
avatarUrl: z.string().url().optional(),
headerUrl: z.string().url().optional(),
personality: z.object({
systemPrompt: z.string().min(1).max(10000),
temperature: z.number().min(0).max(2),
maxTokens: z.number().int().min(1).max(100000),
responseStyle: z.string().optional(),
}),
llmProvider: z.enum(['openrouter', 'openai', 'anthropic']),
llmModel: z.string().min(1),
llmApiKey: z.string().min(1),
schedule: z.object({
type: z.enum(['interval', 'times', 'cron']),
intervalMinutes: z.number().int().min(5).optional(),
times: z.array(z.string().regex(/^([01][0-9]|2[0-3]):[0-5][0-9]$/)).optional(),
cronExpression: z.string().optional(),
timezone: z.string().optional(),
}).optional(),
autonomousMode: z.boolean().optional(),
});
/**
* POST /api/bots - Create a new bot
*
* Requires authentication.
* Creates a new bot linked to the authenticated user's account.
*
* Validates: Requirements 1.1, 1.2
*/
export async function POST(request: Request) {
try {
const user = await requireAuth();
const body = await request.json();
const data = createBotSchema.parse(body);
const bot = await createBot(user.id, {
name: data.name,
handle: data.handle,
bio: data.bio,
avatarUrl: data.avatarUrl,
headerUrl: data.headerUrl,
personality: data.personality,
llmProvider: data.llmProvider,
llmModel: data.llmModel,
llmApiKey: data.llmApiKey,
schedule: data.schedule,
autonomousMode: data.autonomousMode,
});
// Return bot without sensitive data
return NextResponse.json({
success: true,
bot: {
id: bot.id,
userId: bot.userId,
name: bot.name,
handle: bot.handle,
bio: bot.bio,
avatarUrl: bot.avatarUrl,
personalityConfig: bot.personalityConfig,
llmProvider: bot.llmProvider,
llmModel: bot.llmModel,
scheduleConfig: bot.scheduleConfig,
autonomousMode: bot.autonomousMode,
isActive: bot.isActive,
isSuspended: bot.isSuspended,
lastPostAt: bot.lastPostAt,
createdAt: bot.createdAt,
updatedAt: bot.updatedAt,
},
}, { status: 201 });
} catch (error) {
console.error('Create bot error:', error);
if (error instanceof z.ZodError) {
return NextResponse.json(
{ error: 'Invalid input', details: error.issues },
{ status: 400 }
);
}
if (error instanceof Error && error.message === 'Authentication required') {
return NextResponse.json({ error: 'Authentication required' }, { status: 401 });
}
if (error instanceof BotLimitExceededError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{ status: 403 }
);
}
if (error instanceof BotHandleTakenError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{ status: 409 }
);
}
if (error instanceof BotValidationError) {
return NextResponse.json(
{ error: error.message, code: error.code },
{ status: 400 }
);
}
return NextResponse.json(
{ error: 'Failed to create bot' },
{ status: 500 }
);
}
}
/**
* GET /api/bots - List user's bots
*
* Requires authentication.
* Returns all bots belonging to the authenticated user.
*
* Validates: Requirements 1.3
*/
export async function GET() {
try {
const user = await requireAuth();
const userBots = await getBotsByUser(user.id);
// Return bots without sensitive data
const sanitizedBots = userBots.map(bot => ({
id: bot.id,
userId: bot.userId,
name: bot.name,
handle: bot.handle,
bio: bot.bio,
avatarUrl: bot.avatarUrl,
personalityConfig: bot.personalityConfig,
llmProvider: bot.llmProvider,
llmModel: bot.llmModel,
scheduleConfig: bot.scheduleConfig,
autonomousMode: bot.autonomousMode,
isActive: bot.isActive,
isSuspended: bot.isSuspended,
suspensionReason: bot.suspensionReason,
lastPostAt: bot.lastPostAt,
createdAt: bot.createdAt,
updatedAt: bot.updatedAt,
}));
return NextResponse.json({
success: true,
bots: sanitizedBots,
});
} catch (error) {
console.error('List bots error:', error);
if (error instanceof Error && error.message === 'Authentication required') {
return NextResponse.json({ error: 'Authentication required' }, { status: 401 });
}
return NextResponse.json(
{ error: 'Failed to list bots' },
{ status: 500 }
);
}
}