Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
37aa6e3
feat: add tracing middleware for agent execution logging
VISHWAJ33T Jul 11, 2025
af8a0af
feat: add TypeScript definitions for PackageInfo and related types us…
VISHWAJ33T Jul 11, 2025
a957c81
feat: add utility function to get project root directory
VISHWAJ33T Jul 11, 2025
3ac917c
chore: update TypeScript documentation link in next-env.d.ts
VISHWAJ33T Jul 11, 2025
18e4fd5
refactor: remove unused orchestrator and middleware files
VISHWAJ33T Jul 11, 2025
3fa48e3
feat: add middleware for retrieving package documentation and informa…
VISHWAJ33T Jul 11, 2025
2ca7301
refactor: reorganize imports and clean up code structure in SLS Fox a…
VISHWAJ33T Jul 11, 2025
99dc3aa
feat: implement orchestrator agent for generating and executing step-…
VISHWAJ33T Jul 11, 2025
5dd4bcc
chore: update TypeScript documentation link in next-env.d.ts
VISHWAJ33T Jul 11, 2025
889dca5
feat: replace orchestrator agent with receptionist agent for improved…
VISHWAJ33T Jul 11, 2025
81900b2
refactor: update agents to use unified routing and improve error hand…
VISHWAJ33T Jul 11, 2025
08ffbea
refactor: update agents to extract packageName and functionName from …
VISHWAJ33T Jul 11, 2025
21d3aba
refactor: streamline request handling by extracting packageName
VISHWAJ33T Jul 11, 2025
545d158
chore: add aws-lambda and @types/aws-lambda dependencies to package.txt
VISHWAJ33T Jul 11, 2025
68a875d
refactor: enhance package middleware to handle missing packageName in…
VISHWAJ33T Jul 11, 2025
2fbdf9c
feat: implement receptionist agent to analyze user prompts and route …
VISHWAJ33T Jul 11, 2025
7731e9b
refactor: update import path for receptionist agent to improve code o…
VISHWAJ33T Jul 11, 2025
9417c86
feat: enhance slsFox agent to support natural language queries
VISHWAJ33T Jul 11, 2025
2a9156f
feat: add genFullSls agent to generate complete serverless structure …
VISHWAJ33T Jul 11, 2025
78b8592
refactor: update agents to use generic types for improved type safety
VISHWAJ33T Jul 11, 2025
019e7bf
refactor: update getProjectRoot function to support async execution
VISHWAJ33T Jul 11, 2025
1a76c86
chore: update commander and zod dependencies to latest versions
VISHWAJ33T Jul 11, 2025
409a2f5
feat: add findProjectRoot utility to locate the project root directory
VISHWAJ33T Jul 11, 2025
53a4335
feat: add code command to run Next.js server and interact with the co…
VISHWAJ33T Jul 11, 2025
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
22 changes: 11 additions & 11 deletions apps/code/app/api/agent/[[...slug]]/route.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import { AiRouter } from '@microfox/ai-router';
import { tracingMiddleware } from '@/lib/middleware';
import { slsfoxAgent } from '@/lib/agents/slsFox';
import { tracingMiddleware } from '@/lib/middlewares/tracingAgents';
import { receptionistAgent } from '@/lib/agents';

// This router will handle direct calls to individual agents.
const agentRouter = new AiRouter();

// Apply the tracing middleware to all agents mounted on this router.
agentRouter.use('*', tracingMiddleware);

// Mount the individual agent routers here.
agentRouter.agent('/slsfox', slsfoxAgent);
agentRouter.agent('/', receptionistAgent);

// We will export a POST handler that processes all incoming requests.
// The `[[...slug]]` in the filename makes this a catch-all route under /agent.
export async function POST(request: Request, { params }: { params: { slug: string[] } }) {
// Determine the path from the URL slug.
const path = `/${(params.slug || []).join('/')}`;

const body = await request.json();
const { messages, ...restOfBody } = body;
console.log("body", body)
console.log("messages", messages)
console.log("path", path)

const body = await request.json()

console.log("body", body, path)

// Let the AiRouter handle the request and generate a response.
// We add an empty 'messages' array to the request to satisfy the router's type.
const response = agentRouter.handle(path, {
request: {
...body,
messages: []
...restOfBody,
messages: messages || []
}
});

Expand Down
27 changes: 0 additions & 27 deletions apps/code/app/api/orchestrate/route.ts

This file was deleted.

10 changes: 0 additions & 10 deletions apps/code/helpers/utils.ts

This file was deleted.

47 changes: 32 additions & 15 deletions apps/code/lib/agents/code.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,61 @@
import { AiRouter } from '@microfox/ai-router';
import { generateCodeV2 } from '@microfox/ai-code';
import { google } from '@ai-sdk/google';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import * as path from 'path';

export const codeAgent = new AiRouter();

const codeSchema = z.object({
// Input comes from the context.
prompt: z.string().describe('The detailed prompt or description for the code to be generated.'),
});

codeAgent
.actAsTool('/code', {
description: 'Generates code based on documentation from the context.',
.actAsTool('/', {
description: 'Generates code from a prompt or description.',
inputSchema: codeSchema as any,
})
.agent('/code', async ({ state, response }: any) => {
const taskContext = state;
const prompt = taskContext.documentation || taskContext.initialPrompt;
.agent('/', async (ctx) => {
const prompt = ctx.request.params?.prompt as string

if (!prompt) {
const errorMsg = 'Error: No prompt for code generation found in the context.';
response.write({ type: 'text', text: errorMsg });
taskContext.finalOutput = errorMsg;
const errorMsg = 'Error: No prompt for code generation provided.';
ctx.response.write({ type: 'text', text: errorMsg });
return;
}

try {
let isFirstChunk = true;
await generateCodeV2({
model: google('gemini-2.5-pro-preview-06-05'),
model: anthropic('claude-4-opus-20250514'),
submodel: google('gemini-2.5-pro-preview-06-05'),
systemPrompt: 'You are an expert programmer. Generate the code for the file as requested.',
userPrompt: prompt,
dir: process.cwd(),
verbose: true,
onChunkSubmit: async ({ chunk, filePlan }) => {
if (isFirstChunk) {
const fullFileName = `${filePlan.fileName}.${filePlan.fileExtension}`;
const finalPath = path.join(filePlan.path, fullFileName);
ctx.response.write({
type: 'data-metadata',
data: {
filePath: finalPath,
fileName: fullFileName,
},
});
isFirstChunk = false;
}
ctx.response.write({ type: 'text', text: chunk });
},
onFileSubmit: async (filePath: string, code: string) => {
taskContext.code = code;
taskContext.finalOutput = code;
response.write({ type: 'text', text: code });
ctx.response.write({ type: 'text', text: '\n[GENERATION COMPLETE]' });
console.log(`File generation complete for ${filePath}. Total length: ${code.length}`);
},
});
} catch (error: any) {
const errorMessage = `Error generating code: ${error.message}`;
taskContext.finalOutput = errorMessage;
response.write({ type: 'text', text: errorMessage });
ctx.response.write({ type: 'text', text: errorMessage });
}
});
27 changes: 14 additions & 13 deletions apps/code/lib/agents/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,31 @@ import { z } from 'zod';
export const docsAgent = new AiRouter();

const docsSchema = z.object({
// Input comes from the context.
topic: z.string().describe('The topic to generate documentation for.'),
context: z.any().describe('The context to generate documentation for.').optional()
});

docsAgent
.actAsTool('/docs', {
description: 'Generates documentation based on a summary or topic from the context.',
.actAsTool('/', {
description: 'Generates documentation for a topic. Provide the topic and the context if available.',
inputSchema: docsSchema as any,
})
.agent('/docs', async ({ state, response }: any) => {
const taskContext = state;
// This agent can build on the work of the previous one.
const topic = taskContext.summary || taskContext.initialPrompt;
.agent('/', async (ctx) => {
const topic = ctx.request.params?.topic as string
const context = ctx.request.params?.context as any

if (!topic) {
response.write({ type: 'text', text: 'Error: No topic for documentation found in the context.' });
ctx.response.write({ type: 'text', text: 'Error: No topic for documentation provided.' });
return;
}

const { text: documentation } = await generateText({
model: google('gemini-2.5-pro-preview-06-05'),
prompt: `Please generate technical documentation based on the following: ${topic}`,
prompt: `Please generate technical documentation based on the following: ${topic}

context: ${JSON.stringify(context)}
`,
});

// Write the result back to the shared context and the response.
taskContext.documentation = documentation;
response.write({ type: 'text', text: documentation });
});
ctx.response.write({ type: 'text', text: documentation });
});
50 changes: 50 additions & 0 deletions apps/code/lib/agents/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { AiRouter } from '@microfox/ai-router';
import { generateText } from 'ai';
import { google } from '@ai-sdk/google';
import { z } from 'zod';
import { codeAgent } from '@/lib/agents/code';
import { docsAgent } from '@/lib/agents/docs';
import { summarizeAgent } from '@/lib/agents/summarize';
import { slsfoxAgent } from '@/lib/agents/slsFox';

export const receptionistAgent = new AiRouter<any, any, any>();

const receptionistInput = z.object({
prompt: z.string().describe('The user a high-level goal to accomplish.'),
});

receptionistAgent
.actAsTool('/', {
description: 'Analyzes a user prompt and calls the appropriate agent.',
inputSchema: receptionistInput as any,
})
.agent('/', async (ctx) => {
const { prompt } = ctx.request

ctx.response.write({ type: 'text', text: 'Finding the right agent for the job...\n' });

const { toolCalls } = await generateText({
model: google('gemini-2.5-pro-preview-06-05'),
prompt: `You are a highly intelligent routing system. Your purpose is to deeply analyze a user's request to understand its fundamental intent. From this analysis, you will determine the single most appropriate specialized function to execute.

Analyze the following user prompt:
---
${prompt}
---

Now, determine the core task the user wants to accomplish and invoke the corresponding function.`,
tools: {
slsfox: ctx.next.agentAsTool("/slsfox"),
summarize: ctx.next.agentAsTool("/summarize"),
docs: ctx.next.agentAsTool("/docs"),
code: ctx.next.agentAsTool("/code"),
}
});

ctx.response.write({ type: 'text', text: `\nExecution complete. Tool Calls:\n${toolCalls}` });
});

receptionistAgent.agent('/slsfox', slsfoxAgent);
receptionistAgent.agent('/code', codeAgent);
receptionistAgent.agent('/docs', docsAgent);
receptionistAgent.agent('/summarize', summarizeAgent);
64 changes: 0 additions & 64 deletions apps/code/lib/agents/orchestrator.ts

This file was deleted.

42 changes: 42 additions & 0 deletions apps/code/lib/agents/slsFox/genFullSls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { AiRouter } from '@microfox/ai-router';
import { z } from 'zod';
import { generateObject } from 'ai';
import path from 'path';
import * as fs from 'fs';
import { anthropic } from '@ai-sdk/anthropic';
import { PackageInfo } from '@/lib/types/PackageInfo';
import { copyDirectory, updateTemplateFiles } from './template';

export const genFullSlsAgent = new AiRouter<any, any, any>();

const fullSlsSchema = z.object({
packageName: z.string().describe('The name of the package for which to generate the full structure.'),
});

genFullSlsAgent
.actAsTool('/', {
description: 'Generates the complete sls structure for a package.',
inputSchema: fullSlsSchema as any
})
.agent('/', async (ctx) => {
const packageName = ctx.request.params?.packageName as string
ctx.response.write({ type: 'text', text: `Generating full SLS structure for ${packageName}...\n` });

try {
const templateDir = path.join(process.cwd(), 'lib', 'agents', 'slsFox', 'template');
if (fs.existsSync(ctx.state[packageName].slsDir)) {
fs.rmSync(ctx.state[packageName].slsDir, { recursive: true, force: true });
}
copyDirectory(templateDir, ctx.state[packageName].slsDir);
updateTemplateFiles(ctx.state[packageName].slsDir, packageName, ctx.state[packageName].packageInfo.description);

await ctx.next.callAgent('@/slsfox/genSdkMap', { packageName });
await ctx.next.callAgent('@/slsfox/genOpenApi', { packageName });
await ctx.next.callAgent('@/slsfox/genOpenApiMd', { packageName });

ctx.response.write({ type: 'text', text: `Successfully generated serverless structure for ${packageName}.\n` });

} catch (error: any) {
ctx.response.write({ type: 'text', text: `Error generating serverless structure: ${error.message}` });
}
});
Loading