Skip to content
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
36 changes: 34 additions & 2 deletions src/lib/types/generateTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { MiddlewareFactoryOptions } from "./middlewareTypes.js";
import type { JsonValue } from "./common.js";
import type { Content, ImageWithAltText } from "./content.js";
import type { TTSOptions, TTSResult } from "./ttsTypes.js";
import type { PPTOutputOptions, PPTGenerationResult } from "./pptTypes.js";
import type {
VideoOutputOptions,
VideoGenerationResult,
Expand Down Expand Up @@ -76,13 +77,19 @@ export type GenerateOptions = {
* Output mode - determines the type of content generated
* - "text": Standard text generation (default)
* - "video": Video generation using models like Veo 3.1
* - "ppt": PowerPoint presentation generation
*/
mode?: "text" | "video";
mode?: "text" | "video" | "ppt";
/**
* Video generation configuration (used when mode is "video")
* Requires an input image and text prompt
*/
video?: VideoOutputOptions;
/**
* PowerPoint generation configuration (used when mode is "ppt")
* Generates slides based on text prompt
*/
ppt?: PPTOutputOptions;
};

// CSV processing options
Expand Down Expand Up @@ -339,6 +346,24 @@ export type GenerateResult = {
* ```
*/
video?: VideoGenerationResult;
/**
* PowerPoint generation result (present when output.mode is "ppt")
*
* @example
* ```typescript
* const result = await neurolink.generate({
* input: { text: "Introducing Our New Product" },
* model: "gemini-pro",
* output: { mode: "ppt", ppt: { pages: 10, theme: "modern" } }
* });
*
* if (result.ppt) {
* console.log(`Generated ${result.ppt.slides.length} slides`);
* console.log(`Title: ${result.ppt.slides[0].title}`);
* }
* ```
*/
ppt?: PPTGenerationResult;
Comment on lines +349 to +366

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

JSDoc example references non-existent slides.
PPTGenerationResult exposes filePath and totalSlides, not slides. Update the example to avoid confusion.

📝 Suggested doc fix
- * if (result.ppt) {
- *   console.log(`Generated ${result.ppt.slides.length} slides`);
- *   console.log(`Title: ${result.ppt.slides[0].title}`);
- * }
+ * if (result.ppt) {
+ *   console.log(`Presentation saved: ${result.ppt.filePath}`);
+ *   console.log(`Total slides: ${result.ppt.totalSlides}`);
+ * }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* PowerPoint generation result (present when output.mode is "ppt")
*
* @example
* ```typescript
* const result = await neurolink.generate({
* input: { text: "Introducing Our New Product" },
* model: "gemini-pro",
* output: { mode: "ppt", ppt: { pages: 10, theme: "modern" } }
* });
*
* if (result.ppt) {
* console.log(`Generated ${result.ppt.slides.length} slides`);
* console.log(`Title: ${result.ppt.slides[0].title}`);
* }
* ```
*/
ppt?: PPTGenerationResult;
/**
* PowerPoint generation result (present when output.mode is "ppt")
*
* `@example`
*
🤖 Prompt for AI Agents
In `@src/lib/types/generateTypes.ts` around lines 349 - 366, The JSDoc example
incorrectly references a non-existent slides array on PPTGenerationResult;
update the example under the ppt?: PPTGenerationResult docblock to use the
actual properties (e.g., result.ppt.filePath and result.ppt.totalSlides) and any
appropriate access pattern (such as logging the file path and totalSlides) so
the sample matches the PPTGenerationResult shape.

imageOutput?: { base64: string } | null; // Standard format for image generation

// Provider information
Expand Down Expand Up @@ -478,12 +503,17 @@ export type TextGenerationOptions = {
* Output mode - determines the type of content generated
* - "text": Standard text generation (default)
* - "video": Video generation using models like Veo 3.1
* - "ppt": PowerPoint presentation generation
*/
mode?: "text" | "video";
mode?: "text" | "video" | "ppt";
/**
* Video generation configuration (used when mode is "video")
*/
video?: VideoOutputOptions;
/**
* PowerPoint generation configuration (used when mode is "ppt")
*/
ppt?: PPTOutputOptions;
};
tools?: Record<string, Tool>; // Enable MCP tools integration
timeout?: number | string; // Optional timeout (e.g., 30000, '30s', '2m', '1h')
Expand Down Expand Up @@ -676,6 +706,8 @@ export type TextGenerationResult = {
audio?: TTSResult;
/** Video generation result */
video?: VideoGenerationResult;
/** PowerPoint generation result */
ppt?: PPTGenerationResult;
/** Image generation output */
imageOutput?: { base64: string } | null;
};
Expand Down
74 changes: 74 additions & 0 deletions src/lib/types/pptTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { ImageWithAltText } from "./content.js";

type ThemeOption = "modern" | "corporate" | "creative" | "minimal" | "dark";

type AudienceOption = "business" | "students" | "technical" | "general";

type ToneOption = "professional" | "casual" | "educational" | "persuasive";

type OutputFormatOption = "pptx";

type AspectRatioOption = "16:9" | "4:3";

export type PPTOutputOptions = {
/** Number of slides to generate (required, range: 5-50) */
pages: number;
/** Output format - only PPTX supported currently (default: "pptx") */
format?: OutputFormatOption;
/** Presentation theme/style (default: "modern") */
theme?: ThemeOption;
/** Target audience for content customization */
audience?: AudienceOption;
/** Presentation tone/style */
tone?: ToneOption;
/** Whether to generate AI images for slides (default: true) */
includeImages?: boolean;
/** Custom output file path (default: auto-generated in ./output/) */
outputPath?: string;
/** Aspect ratio for slides (default: "16:9") */
aspectRatio?: AspectRatioOption;
/** Path to logo image to include in slides */
logoPath?: Buffer | string | ImageWithAltText;
};
Comment thread
Tafheem-Ahemad-Juspay marked this conversation as resolved.
/**
* Result type for generated presentation content
*
* Returned in `GenerateResult.ppt` when presentation generation is successful.
* Contains the file path and metadata about the generated presentation.
*
* @example
* ```typescript
* const result = await neurolink.generate({
* input: { text: "Introducing Our New Product" },
* provider: "vertex",
* output: { mode: "ppt", ppt: { pages: 10, theme: "modern" } }
* });
*
* if (result.ppt) {
* console.log(`Presentation saved: ${result.ppt.filePath}`);
* console.log(`Total slides: ${result.ppt.totalSlides}`);
* console.log(`Theme: ${result.ppt.metadata?.theme}`);
* }
* ```
*/
export type PPTGenerationResult = {
/** Path to the generated PPTX file */
filePath: string;
/** Total number of slides in the presentation */
totalSlides: number;
/** Output format (always "pptx" currently) */
format: OutputFormatOption;
/** Presentation metadata */
metadata?: {
/** Theme/style used */
theme?: string;
/** Target audience */
audience?: string;
/** Presentation tone */
tone?: string;
/** Model used for image generation */
imageModel?: string;
/** File size in bytes */
fileSize?: number;
};
};
212 changes: 211 additions & 1 deletion src/lib/utils/errorHandling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Robust Error Handling Utilities for NeuroLink
* Provides structured error management for tool execution and system operations
*/

import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
import type { StructuredError } from "../types/utilities.js";
import { logger } from "./logger.js";
Expand Down Expand Up @@ -49,6 +48,17 @@ export const ERROR_CODES = {
IMAGE_TOO_LARGE: "IMAGE_TOO_LARGE",
IMAGE_TOO_SMALL: "IMAGE_TOO_SMALL",
INVALID_IMAGE_FORMAT: "INVALID_IMAGE_FORMAT",

// PPT validation errors
MISSING_PPT_PROPERTIES: "MISSING_PPT_PROPERTIES",
INVALID_PPT_PAGES: "INVALID_PPT_PAGES",
INVALID_PPT_FORMAT: "INVALID_PPT_FORMAT",
INVALID_PPT_PROVIDER: "INVALID_PPT_PROVIDER",
INVALID_PPT_OUTPUT_OPTIONS: "INVALID_PPT_OUTPUT_OPTIONS",
INVALID_PPT_OUTPUT_PATH: "INVALID_PPT_OUTPUT_PATH",
INVALID_PPT_LOGO_PATH: "INVALID_PPT_LOGO_PATH",
INVALID_PPT_MODE: "INVALID_PPT_MODE",
INVALID_PPT_PROMPT: "INVALID_PPT_PROMPT",
} as const;

/**
Expand Down Expand Up @@ -537,6 +547,206 @@ export class ErrorFactory {
},
});
}

// ============================================================================
// PPT VALIDATION ERRORS
// ============================================================================

/**
* Create a generic missing PPT property error
*/
static missingPPTProperty(
field: string,
suggestions?: string[],
): NeuroLinkError {
const defaultSuggestions = [`Provide the required '${field}' field`];

return new NeuroLinkError({
code: ERROR_CODES.MISSING_PPT_PROPERTIES,
message: `PPT generation requires '${field}' field`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field,
suggestions: suggestions || defaultSuggestions,
},
});
}

/**
* Create an invalid PPT pages error
*/
static invalidPPTPages(pages: unknown, reason: string): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_PAGES,
message: `Invalid pages value '${pages}': ${reason}`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "output.ppt.pages",
providedValue: pages,
suggestions: [
"Use a number between 5 and 50",
"For longer presentations, consider breaking into multiple decks",
],
},
});
}

/**
* Create an invalid PPT format error
*/
static invalidPPTFormat(format: string): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_FORMAT,
message: `Invalid format '${format}'. Only 'pptx' is supported`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "output.ppt.format",
providedValue: format,
suggestions: ["Use format: 'pptx' or omit (defaults to 'pptx')"],
},
});
}

/**
* Create a generic invalid PPT output options error
*/
static invalidPPTOutputOptions(
field: string,
value: unknown,
validOptions?: string[],
): NeuroLinkError {
const suggestions = validOptions
? validOptions.map((opt) => `Use '${opt}'`)
: ["Check the documentation for valid options"];

return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_OUTPUT_OPTIONS,
message: `Invalid ${field} value '${value}'`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: `output.ppt.${field}`,
providedValue: value,
suggestions,
},
});
}

/**
* Create an invalid PPT output path error
*/
static invalidPPTOutputPath(path: unknown, reason: string): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_OUTPUT_PATH,
message: `Invalid outputPath '${path}': ${reason}`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "output.ppt.outputPath",
providedValue: path,
suggestions: [
"Provide a valid file path string",
"Example: './presentations/my-deck.pptx'",
"Omit to use auto-generated path",
],
},
});
}

/**
* Create an invalid PPT mode error
*/
static invalidPPTMode(): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_MODE,
message: "Presentation generation requires output.mode to be 'ppt'",
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "output.mode",
suggestions: [
"Set output: { mode: 'ppt' } for presentation generation",
],
},
});
}

/**
* Create an invalid PPT prompt error
*/
static invalidPPTPrompt(reason: string): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_PROMPT,
message: `Invalid PPT prompt: ${reason}`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "input.text",
suggestions: [
"Provide a non-empty text prompt",
"Keep the prompt under 1000 characters",
"Focus on key topics and structure for the presentation",
],
},
});
}

/**
* Create an invalid PPT logo path error
*/
static invalidPPTLogoPath(path: unknown, reason: string): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_LOGO_PATH,
message: `Invalid logoPath '${path}': ${reason}`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "output.ppt.logoPath",
providedValue: path,
suggestions: [
"Provide a valid file path string",
"Example: './assets/logo.png'",
"Omit to skip logo inclusion",
],
},
});
}

/**
* Create an invalid PPT provider error
*/
static invalidPPTProvider(provider: unknown): NeuroLinkError {
return new NeuroLinkError({
code: ERROR_CODES.INVALID_PPT_PROVIDER,
message: `Invalid provider '${provider}' for PPT generation. Supported providers: vertex, openai, azure, anthropic, google-ai, bedrock`,
category: ErrorCategory.VALIDATION,
severity: ErrorSeverity.MEDIUM,
retriable: false,
context: {
field: "provider",
providedValue: provider,
suggestions: [
"Use 'vertex' for Google Vertex AI (Gemini)",
"Use 'openai' for OpenAI GPT models",
"Use 'azure' for Azure OpenAI",
"Use 'anthropic' for Anthropic Claude models",
"Use 'google-ai' for Google AI Studio (Gemini)",
"Use 'bedrock' for AWS Bedrock (Claude, Llama, Nova, etc.)",
],
},
});
}
}

/**
Expand Down
Loading
Loading