Skip to content

feat: add GenAI implementation guide and demo ask flows - #27

Open
RitikWeb22 wants to merge 2 commits into
ankurdotio:mainfrom
RitikWeb22:gen-Ai-implementation
Open

feat: add GenAI implementation guide and demo ask flows#27
RitikWeb22 wants to merge 2 commits into
ankurdotio:mainfrom
RitikWeb22:gen-Ai-implementation

Conversation

@RitikWeb22

Copy link
Copy Markdown

Summary
This PR introduces a complete GenAI implementation feature with beginner-friendly guidance and runnable demo endpoints. It also improves startup stability by making OAuth, payment, and email integrations safe when credentials are not configured.

What was added
New GenAI Implementation Guide:

Overview and implementation path.

Step-by-step process for setup, environment, safety, and rollout.

Mode-wise details for Single Agent, Multi-Agent, and LangGraph.

Beginner-friendly code snippets.

New Runnable Demo Endpoints:

POST /api/v1/gen-ai-implementation/single/ask

POST /api/v1/gen-ai-implementation/multi/ask

POST /api/v1/gen-ai-implementation/langgraph/ask

Input Validation for Ask Flows:

Mandatory question field and length validation.

Consistent error responses for invalid inputs.

Reliability and Startup Hardening:

Conditional Google OAuth strategy registration.

Controlled 503 responses for OAuth routes when not configured.

Guarded Razorpay client initialization to avoid crashes.

Graceful failure for Email transporter if env values are missing.

Config freezing restricted to production only.

Testing
Added/Updated tests for guide and ask endpoints.

Covered success and validation failure scenarios.

Test Command: npx jest gen-ai-implementation.test.js --runInBand (Passed ✅)

Impact
Existing API behavior remains unchanged.

App no longer crashes at startup in missing-credential environments.

GenAI feature is now usable for documentation and flow visualization.

Notes
The new ask endpoints currently return deterministic demo-style outputs for implementation guidance. Real LLM execution can be enabled in a follow-up PR by wiring provider keys and LangChain/LangGraph calls.

Checklist
[x] Feature implemented within existing project structure.

[x] Tests added and passing.

[x] Error handling added for optional integrations.

[x] No startup regression in unconfigured local environments.

Copilot AI review requested due to automatic review settings April 4, 2026 20:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “GenAI implementation” guide + demo ask flows to the API, and hardens startup/runtime behavior when optional integrations (Google OAuth, Razorpay, email) are not configured.

Changes:

  • Introduces /api/v1/gen-ai-implementation guide endpoint plus three runnable demo ask endpoints (single/multi/langgraph) with input validation and tests.
  • Makes Google OAuth strategy + routes conditional and returns a controlled 503 when OAuth isn’t configured.
  • Guards Razorpay and email transporter initialization so missing credentials don’t crash the app.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/services/payment.service.js Make Razorpay optional; add a 503 guard when credentials are missing.
src/services/gen-ai-implementation.service.js Adds structured “implementation guide” content + demo response builders + question validation.
src/controllers/gen-ai-implementation.controller.js Adds controller methods for guide + demo ask endpoints.
src/routes/gen-ai-implementation.routes.js Wires the new guide + ask routes.
src/app.js Registers the new GenAI implementation routes.
src/tests/gen-ai-implementation.test.js Adds coverage for guide retrieval, demo ask responses, and validation failures.
src/routes/auth.routes.js Makes Google OAuth routes conditional; returns 503 when disabled.
src/config/passport.js Conditionally registers Google strategy and exports googleOAuthEnabled.
src/config/email.config.js Moves OAuth2 client creation inside createTransporter and throws 503 if not configured.
src/config/config.js Freezes config only in production (keeps mutable for dev/testing).
readme.md Documents the new GenAI guide endpoint.
package-lock.json Lockfile update (removes gcp-metadata subtree).
Comments suppressed due to low confidence (1)

src/services/payment.service.js:475

  • In handleWebhook, the catch block always wraps errors into a new AppError(..., 500), which overrides earlier AppErrors thrown in the try (e.g., invalid webhook signature should stay 400; missing Razorpay credentials should stay 503). Preserve existing AppError instances (rethrow them) and only wrap unknown errors as 500 so the correct status codes reach clients/webhook senders.
  async handleWebhook(signature, payload) {
    try {
      this.ensureRazorpayConfigured();

      // Verify webhook signature
      const expectedSignature = crypto
        .createHmac('sha256', config.razorpay.keySecret)
        .update(JSON.stringify(payload))
        .digest('hex');

      if (signature !== expectedSignature) {
        throw new AppError('Invalid webhook signature', 400);
      }

      const { event, payload: eventPayload } = payload;

      switch (event) {
        case 'payment.captured':
          await this.handlePaymentCaptured(eventPayload.payment.entity);
          break;
        case 'payment.failed':
          await this.handlePaymentFailed(eventPayload.payment.entity);
          break;
        case 'refund.processed':
          await this.handleRefundProcessed(eventPayload.refund.entity);
          break;
        default:
          logger.info(`Unhandled webhook event: ${event}`);
      }

      return { success: true, message: 'Webhook processed successfully' };
    } catch (error) {
      logger.error('Webhook processing error:', error);
      throw new AppError(`Webhook processing failed: ${error.message}`, 500);
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5 to +67
/**
* Get the GenAI implementation guide.
* @route GET /api/v1/gen-ai-implementation
* @access Public
*/
getGuide = asyncHandler(async (req, res) => {
const mode = req.query.mode || 'all';
const guide = genAiImplementationService.buildGuide(mode);

res.status(200).json({
success: true,
message: 'GenAI implementation guide retrieved successfully',
data: guide,
});
});

/**
* Run single-agent demo flow.
* @route POST /api/v1/gen-ai-implementation/single/ask
* @access Public
*/
askSingle = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runSingleAgentDemo(question);

res.status(200).json({
success: true,
message: 'Single-agent demo response generated successfully',
data: result,
});
});

/**
* Run multi-agent demo flow.
* @route POST /api/v1/gen-ai-implementation/multi/ask
* @access Public
*/
askMulti = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runMultiAgentDemo(question);

res.status(200).json({
success: true,
message: 'Multi-agent demo response generated successfully',
data: result,
});
});

/**
* Run LangGraph demo flow.
* @route POST /api/v1/gen-ai-implementation/langgraph/ask
* @access Public
*/
askLangGraph = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runLangGraphDemo(question);

res.status(200).json({
success: true,
message: 'LangGraph demo response generated successfully',
data: result,
});
});

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new controller file is indented with 4 spaces, while existing controllers use 2-space indentation (e.g., src/controllers/auth.controller.js). Running the formatter (Prettier) / aligning indentation will keep code style consistent across the repo and reduce diff churn in future edits.

Suggested change
/**
* Get the GenAI implementation guide.
* @route GET /api/v1/gen-ai-implementation
* @access Public
*/
getGuide = asyncHandler(async (req, res) => {
const mode = req.query.mode || 'all';
const guide = genAiImplementationService.buildGuide(mode);
res.status(200).json({
success: true,
message: 'GenAI implementation guide retrieved successfully',
data: guide,
});
});
/**
* Run single-agent demo flow.
* @route POST /api/v1/gen-ai-implementation/single/ask
* @access Public
*/
askSingle = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runSingleAgentDemo(question);
res.status(200).json({
success: true,
message: 'Single-agent demo response generated successfully',
data: result,
});
});
/**
* Run multi-agent demo flow.
* @route POST /api/v1/gen-ai-implementation/multi/ask
* @access Public
*/
askMulti = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runMultiAgentDemo(question);
res.status(200).json({
success: true,
message: 'Multi-agent demo response generated successfully',
data: result,
});
});
/**
* Run LangGraph demo flow.
* @route POST /api/v1/gen-ai-implementation/langgraph/ask
* @access Public
*/
askLangGraph = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runLangGraphDemo(question);
res.status(200).json({
success: true,
message: 'LangGraph demo response generated successfully',
data: result,
});
});
/**
* Get the GenAI implementation guide.
* @route GET /api/v1/gen-ai-implementation
* @access Public
*/
getGuide = asyncHandler(async (req, res) => {
const mode = req.query.mode || 'all';
const guide = genAiImplementationService.buildGuide(mode);
res.status(200).json({
success: true,
message: 'GenAI implementation guide retrieved successfully',
data: guide,
});
});
/**
* Run single-agent demo flow.
* @route POST /api/v1/gen-ai-implementation/single/ask
* @access Public
*/
askSingle = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runSingleAgentDemo(question);
res.status(200).json({
success: true,
message: 'Single-agent demo response generated successfully',
data: result,
});
});
/**
* Run multi-agent demo flow.
* @route POST /api/v1/gen-ai-implementation/multi/ask
* @access Public
*/
askMulti = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runMultiAgentDemo(question);
res.status(200).json({
success: true,
message: 'Multi-agent demo response generated successfully',
data: result,
});
});
/**
* Run LangGraph demo flow.
* @route POST /api/v1/gen-ai-implementation/langgraph/ask
* @access Public
*/
askLangGraph = asyncHandler(async (req, res) => {
const { question } = req.body;
const result = genAiImplementationService.runLangGraphDemo(question);
res.status(200).json({
success: true,
message: 'LangGraph demo response generated successfully',
data: result,
});
});

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +83
name: 'Midnight Graph',
mode: 'dark',
palette: {
background: '#08111f',
surface: '#111a2e',
surfaceAlt: '#16233d',
primary: '#7c9cff',
secondary: '#6be7c8',
text: '#e8eefc',
muted: '#9bb0d0',
border: '#243354',
},
layout: 'card-grid',
};

const implementationProcess = {
prerequisites: [
'Node.js 18+ and npm installed',
'Working Express server with controller/service pattern',
'One LLM provider key (for example OpenAI)',
],
installCommands: [
'npm i langchain @langchain/openai @langchain/langgraph dotenv',
],
envSetup: [
'Add OPENAI_API_KEY in your .env file',
'Load environment variables once in server bootstrap',
'Never hardcode API keys inside services',
],
folderIntegration: [
'Create src/services/gen-ai-single-agent.service.js for single-agent flow',
'Create src/services/gen-ai-langgraph.service.js for graph orchestration flow',
'Use existing src/controllers/gen-ai-implementation.controller.js to call service methods',
'Expose POST endpoints from src/routes/gen-ai-implementation.routes.js for runnable demos',
'Keep GET /api/v1/gen-ai-implementation as a documentation/guide endpoint',
],
validationAndSafety: [
'Validate question input before calling model',
'Use short system prompts with clear output format',
'Add request timeout and retry policy at service layer',
'Log only request metadata, do not log secrets',
],
rolloutPlan: [
'Phase 1: Ship single-agent first',
'Phase 2: Add specialist agents for research/writer split',
'Phase 3: Move to LangGraph for branching, retries, and checkpoints',
],
};

const implementationModes = {
single: {
slug: 'single',
title: 'Single-Agent LangChain',
summary:
'Use one orchestrator when the task has a clear path, a limited toolset, and predictable handoffs.',
whenToUse: [
'FAQ answering and support automation',
'Simple retrieval augmented generation flows',
'One model plus a few tools or retrievers',
],
architecture: [
'User request enters one agent loop',
'Agent selects tools or retrievers',
'Model synthesizes the final answer',
'Response is formatted for the client UI',
],
implementationSteps: [
'Install LangChain core packages and choose a model provider.',
'Define a system prompt with the expected output format.',
'Attach tools for search, database lookup, or API calls.',
'Wrap the agent in a service method and expose it through a controller.',
'Return structured JSON so the frontend can render cards, steps, and code snippets.',
],
processFlow: [
'Receive user question in controller',
'Validate and sanitize input',
'Build prompt template and invoke one LLM',
'Return final structured answer',
],
codeSnippet: `import 'dotenv/config';

Copilot AI Apr 4, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gen-ai-implementation.service.js is formatted with 4-space indentation, whereas the rest of the codebase appears to use 2 spaces. Please run the repo formatter (Prettier) or adjust indentation to match the established style, to keep the new service readable and consistent.

Suggested change
name: 'Midnight Graph',
mode: 'dark',
palette: {
background: '#08111f',
surface: '#111a2e',
surfaceAlt: '#16233d',
primary: '#7c9cff',
secondary: '#6be7c8',
text: '#e8eefc',
muted: '#9bb0d0',
border: '#243354',
},
layout: 'card-grid',
};
const implementationProcess = {
prerequisites: [
'Node.js 18+ and npm installed',
'Working Express server with controller/service pattern',
'One LLM provider key (for example OpenAI)',
],
installCommands: [
'npm i langchain @langchain/openai @langchain/langgraph dotenv',
],
envSetup: [
'Add OPENAI_API_KEY in your .env file',
'Load environment variables once in server bootstrap',
'Never hardcode API keys inside services',
],
folderIntegration: [
'Create src/services/gen-ai-single-agent.service.js for single-agent flow',
'Create src/services/gen-ai-langgraph.service.js for graph orchestration flow',
'Use existing src/controllers/gen-ai-implementation.controller.js to call service methods',
'Expose POST endpoints from src/routes/gen-ai-implementation.routes.js for runnable demos',
'Keep GET /api/v1/gen-ai-implementation as a documentation/guide endpoint',
],
validationAndSafety: [
'Validate question input before calling model',
'Use short system prompts with clear output format',
'Add request timeout and retry policy at service layer',
'Log only request metadata, do not log secrets',
],
rolloutPlan: [
'Phase 1: Ship single-agent first',
'Phase 2: Add specialist agents for research/writer split',
'Phase 3: Move to LangGraph for branching, retries, and checkpoints',
],
};
const implementationModes = {
single: {
slug: 'single',
title: 'Single-Agent LangChain',
summary:
'Use one orchestrator when the task has a clear path, a limited toolset, and predictable handoffs.',
whenToUse: [
'FAQ answering and support automation',
'Simple retrieval augmented generation flows',
'One model plus a few tools or retrievers',
],
architecture: [
'User request enters one agent loop',
'Agent selects tools or retrievers',
'Model synthesizes the final answer',
'Response is formatted for the client UI',
],
implementationSteps: [
'Install LangChain core packages and choose a model provider.',
'Define a system prompt with the expected output format.',
'Attach tools for search, database lookup, or API calls.',
'Wrap the agent in a service method and expose it through a controller.',
'Return structured JSON so the frontend can render cards, steps, and code snippets.',
],
processFlow: [
'Receive user question in controller',
'Validate and sanitize input',
'Build prompt template and invoke one LLM',
'Return final structured answer',
],
codeSnippet: `import 'dotenv/config';
name: 'Midnight Graph',
mode: 'dark',
palette: {
background: '#08111f',
surface: '#111a2e',
surfaceAlt: '#16233d',
primary: '#7c9cff',
secondary: '#6be7c8',
text: '#e8eefc',
muted: '#9bb0d0',
border: '#243354',
},
layout: 'card-grid',
};
const implementationProcess = {
prerequisites: [
'Node.js 18+ and npm installed',
'Working Express server with controller/service pattern',
'One LLM provider key (for example OpenAI)',
],
installCommands: [
'npm i langchain @langchain/openai @langchain/langgraph dotenv',
],
envSetup: [
'Add OPENAI_API_KEY in your .env file',
'Load environment variables once in server bootstrap',
'Never hardcode API keys inside services',
],
folderIntegration: [
'Create src/services/gen-ai-single-agent.service.js for single-agent flow',
'Create src/services/gen-ai-langgraph.service.js for graph orchestration flow',
'Use existing src/controllers/gen-ai-implementation.controller.js to call service methods',
'Expose POST endpoints from src/routes/gen-ai-implementation.routes.js for runnable demos',
'Keep GET /api/v1/gen-ai-implementation as a documentation/guide endpoint',
],
validationAndSafety: [
'Validate question input before calling model',
'Use short system prompts with clear output format',
'Add request timeout and retry policy at service layer',
'Log only request metadata, do not log secrets',
],
rolloutPlan: [
'Phase 1: Ship single-agent first',
'Phase 2: Add specialist agents for research/writer split',
'Phase 3: Move to LangGraph for branching, retries, and checkpoints',
],
};
const implementationModes = {
single: {
slug: 'single',
title: 'Single-Agent LangChain',
summary:
'Use one orchestrator when the task has a clear path, a limited toolset, and predictable handoffs.',
whenToUse: [
'FAQ answering and support automation',
'Simple retrieval augmented generation flows',
'One model plus a few tools or retrievers',
],
architecture: [
'User request enters one agent loop',
'Agent selects tools or retrievers',
'Model synthesizes the final answer',
'Response is formatted for the client UI',
],
implementationSteps: [
'Install LangChain core packages and choose a model provider.',
'Define a system prompt with the expected output format.',
'Attach tools for search, database lookup, or API calls.',
'Wrap the agent in a service method and expose it through a controller.',
'Return structured JSON so the frontend can render cards, steps, and code snippets.',
],
processFlow: [
'Receive user question in controller',
'Validate and sanitize input',
'Build prompt template and invoke one LLM',
'Return final structured answer',
],
codeSnippet: `import 'dotenv/config';

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants