Skip to content
Draft
Show file tree
Hide file tree
Changes from 8 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
4 changes: 4 additions & 0 deletions agent-docs/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TUTORIAL_API_URL=http://localhost:3201
VECTOR_STORE_NAME=docs
# Run `agentuity auth` -- this will be populated in .env
AGENTUITY_SDK_KEY=
10 changes: 8 additions & 2 deletions app/api/tutorials/[id]/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { join } from 'path';
import { parseTutorialMDXCached } from '@/lib/tutorial/mdx-parser';
import { TutorialIdParamsSchema } from '@/lib/tutorial/schemas';
import { getTutorialFilePath } from '@/lib/tutorial';

interface RouteParams {
params: Promise<{ id: string }>;
Expand All @@ -21,7 +21,13 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
}

const { id } = validationResult.data;
const filePath = join(process.cwd(), 'content', 'Tutorial', `${id}.mdx`);
const filePath = await getTutorialFilePath(id);
if (!filePath) {
return NextResponse.json(
{ success: false, error: 'Tutorial not found' },
{ status: 404 }
);
}

const parsed = await parseTutorialMDXCached(filePath);

Expand Down
21 changes: 13 additions & 8 deletions app/api/tutorials/[id]/steps/[stepNumber]/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NextRequest, NextResponse } from 'next/server';
import { join } from 'path';
import { parseTutorialMDXCached } from '@/lib/tutorial/mdx-parser';
import { StepParamsSchema } from '@/lib/tutorial/schemas';
import { getTutorialFilePath } from '@/lib/tutorial';

interface RouteParams {
params: Promise<{ id: string; stepNumber: string }>;
Expand All @@ -10,29 +10,34 @@ interface RouteParams {
export async function GET(request: NextRequest, { params }: RouteParams) {
try {
const rawParams = await params;

// Validate and transform parameters with Zod

const validationResult = StepParamsSchema.safeParse(rawParams);
if (!validationResult.success) {
return NextResponse.json(
{ success: false, error: 'Invalid parameters', details: validationResult.error.format() },
{ status: 400 }
);
}

const { id, stepNumber: stepNum } = validationResult.data;

const filePath = join(process.cwd(), 'content', 'Tutorial', `${id}.mdx`);

const filePath = await getTutorialFilePath(id);
if (!filePath) {
return NextResponse.json(
{ success: false, error: 'Tutorial not found' },
{ status: 404 }
);
}
const parsed = await parseTutorialMDXCached(filePath);

const step = parsed.steps.find(s => s.stepNumber === stepNum);
if (!step) {
return NextResponse.json(
{ success: false, error: 'Step not found' },
{ status: 404 }
);
}

return NextResponse.json({
success: true,
data: {
Expand Down
43 changes: 16 additions & 27 deletions app/api/tutorials/route.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,46 @@
import { NextResponse } from 'next/server';
import { readdir } from 'fs/promises';
import { join } from 'path';
import { parseTutorialMDXCached } from '@/lib/tutorial/mdx-parser';
import { TutorialListItemSchema, type TutorialListItem } from '@/lib/tutorial/schemas';
import { getTutorialsConfig } from '@/lib/tutorial';

export async function GET() {
try {
const tutorialsDir = join(process.cwd(), 'content', 'Tutorial');

// Check if Tutorial directory exists, if not create it for future use
let entries: string[];
try {
entries = await readdir(tutorialsDir);
} catch (error) {
// Return empty array if Tutorial directory doesn't exist yet
return NextResponse.json([]);
}

const mdxFiles = entries.filter(file => file.endsWith('.mdx'));

const config = await getTutorialsConfig();

const tutorials = await Promise.all(
mdxFiles.map(async (file): Promise<TutorialListItem | null> => {
config.tutorials.map(async (tutorialMeta): Promise<TutorialListItem | null> => {
try {
const filePath = join(tutorialsDir, file);
const filePath = join(process.cwd(), 'content', tutorialMeta.path);
const parsed = await parseTutorialMDXCached(filePath);

const tutorialItem = {
id: file.replace('.mdx', ''),
title: parsed.metadata.title,
description: parsed.metadata.description,
totalSteps: parsed.metadata.totalSteps,
difficulty: parsed.metadata.difficulty,
estimatedTime: parsed.metadata.estimatedTime,
id: tutorialMeta.id,
title: tutorialMeta.title,
description: tutorialMeta.description,
totalSteps: parsed.metadata.totalSteps || parsed.steps.length,
difficulty: tutorialMeta.difficulty,
estimatedTime: tutorialMeta.estimatedTime,
};

// Validate the tutorial list item
const validationResult = TutorialListItemSchema.safeParse(tutorialItem);
if (!validationResult.success) {
console.warn(`Invalid tutorial item ${file}:`, validationResult.error.message);
console.warn(`Invalid tutorial item ${tutorialMeta.id}:`, validationResult.error.message);
return null;
}

return validationResult.data;
} catch (error) {
console.warn(`Failed to parse tutorial ${file}:`, error);
console.warn(`Failed to parse tutorial ${tutorialMeta.id} at ${tutorialMeta.path}:`, error);
return null;
}
})
);

// Filter out failed tutorials
const validTutorials = tutorials.filter(tutorial => tutorial !== null);

return NextResponse.json(validTutorials);
} catch (error) {
console.error('Failed to load tutorials:', error);
Expand Down
Loading