Skip to content

Implement OpenAITTSHandler.synthesize() for text-to-speech synthesis - #619

Closed
adarsh02125 with Copilot wants to merge 2 commits into
releasefrom
copilot/implement-openaittshandler-synthesize
Closed

adarsh02125 with Copilot wants to merge 2 commits into
releasefrom
copilot/implement-openaittshandler-synthesize

Conversation

Copilot AI commented Dec 4, 2025 •

Copy link
Copy Markdown
Contributor

Pull Request

Description

Implements core text-to-speech synthesis via OpenAI's TTS API. Adds OpenAITTSHandler class with synthesize() method supporting all OpenAI TTS models, voices, formats, and speed controls. The implementation extends and integrates with existing TTS type infrastructure from the release branch for consistency and maintainability.

Type of Change

  • 🐛 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📚 Documentation update
  • 🧹 Code refactoring (no functional changes)
  • 🧪 Test coverage improvement

Related Issues

Implements TTS-008

Changes Made

Core Implementation

  • src/lib/types/ttsTypes.ts: Extended existing TTS type system with OpenAI-specific types
    • Extended AudioFormat to include all 7 OpenAI formats: "mp3" | "wav" | "ogg" | "opus" | "aac" | "flac" | "pcm"
    • Updated VALID_AUDIO_FORMATS array to include all supported formats
    • Added OpenAITTSVoice type for OpenAI voices (alloy, echo, fable, onyx, nova, shimmer)
    • Added ITTSHandler type (not interface) for TTS provider implementations following codebase conventions
    • Added text field to TTSOptions type for synthesis operations
    • Reused existing TTSOptions and TTSResult types for consistency
  • src/lib/adapters/tts/openaiTTSHandler.ts: Full OpenAI TTS handler (200+ lines)
    • Model selection: tts-1-hd for HD quality, tts-1 for standard
    • Voice defaults to alloy, supports all 6 OpenAI voices
    • Supports all formats: mp3, opus, aac, flac, wav, pcm
    • Speed control: 0.25x to 4.0x with validation
    • Calls client.audio.speech.create(), converts ArrayBuffer to Buffer
    • Returns flat TTSResult structure matching existing type system: { buffer, format, size, duration, voice, sampleRate }
    • Comprehensive input validation and error handling
    • Early validation for required text field with clear error messages

Type System Integration

  • Merged with release branch to integrate with existing TTS infrastructure
  • Removed duplicate src/lib/types/tts.ts in favor of extending existing ttsTypes.ts
  • Implemented flat TTSResult structure (not nested metadata) matching type definition
  • Changed from custom TTSSynthesisOptions to standard TTSOptions type
  • Converted ITTSHandler from interface to type to follow codebase convention of using types over interfaces
  • Fixed import paths from non-existent types/tts.js to correct types/ttsTypes.js
  • Updated all type references to use standardized names: TTSOptions and AudioFormat

Dependency & Package Configuration

  • package.json: Added openai@^6.10.0 dependency (upgraded from v4 for latest security patches and features)
    • Fixed CI workflow failures caused by missing OpenAI SDK package
    • Added "./adapters/tts" export mapping to enable proper module resolution for consumers
    • Ensures backward-compatible TTS API while providing access to v6 improvements

Testing & Documentation

  • test/unit/adapters/openaiTTSHandler.test.ts: Comprehensive test suite with 39 unit tests
    • Added proper OpenAI client mocking using vi.mock() to enable testing without API key
    • Successful synthesis tests covering all options (voices, formats, quality, speed)
    • Model selection validation (tts-1 vs tts-1-hd)
    • Duration estimation and speed-adjusted calculation tests
    • TTSResult structure validation tests
    • Error handling tests (API errors, network failures)
    • All validation tests for text, voice, format, and speed parameters
    • Tests no longer require OpenAI API key or make real API calls
  • src/lib/adapters/tts/README.md: Usage examples updated to use flat TTSResult structure
    • All examples show correct field access: result.size, result.duration, result.voice
    • Updated "Metadata" section to "Result Structure" to reflect flat structure

Example Usage

import { OpenAITTSHandler } from "@juspay/neurolink/adapters/tts";

const handler = new OpenAITTSHandler();

const result = await handler.synthesize({
  text: "Welcome to our application",
  voice: "nova",
  format: "mp3",
  quality: "hd",
  speed: 0.95
});

// result.buffer - audio Buffer
// result.format - audio format
// result.size - buffer size in bytes
// result.duration - estimated duration in seconds
// result.voice - voice used
// result.sampleRate - sample rate (undefined for OpenAI)

AI Provider Impact

  • OpenAI
  • Anthropic
  • Google AI/Vertex
  • AWS Bedrock
  • Azure OpenAI
  • Hugging Face
  • Ollama
  • Mistral
  • All providers
  • No provider-specific changes

Component Impact

  • CLI
  • SDK
  • MCP Integration
  • Streaming
  • Tool Calling
  • Configuration
  • Documentation
  • Tests

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • E2E tests added/updated
  • Manual testing performed
  • All existing tests pass

Test Environment

  • OS: Linux
  • Node.js version: Latest LTS
  • Package manager: npm

Performance Impact

  • No performance impact
  • Performance improvement
  • Minor performance impact (acceptable)
  • Significant performance impact (needs discussion)

Breaking Changes

None. Additive feature only. The OpenAI v6 upgrade maintains full backward compatibility with existing TTS API. Implementation uses existing TTS type system for consistency across the codebase.

Screenshots/Demo

N/A

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Additional Notes

Follows existing adapter patterns (similar to providerImageAdapter.ts). Reuses logger utility. Type-safe with full TypeScript coverage. Ready for integration into provider-level TTS features (TTS-003, TTS-020).

CI Fix: Added missing openai npm package dependency that was causing TypeScript compilation errors in CI workflows. The TTS implementation requires the official OpenAI SDK.

Code Review Updates: Addressed CodeRabbit feedback by:

  1. Upgrading OpenAI SDK from v4.104.0 to v6.10.0 for latest security patches and features (backward compatible)
  2. Adding proper package.json export for "./adapters/tts" subpath to fix module resolution for consumers using the documented import path

Merge Conflict Resolution: Successfully merged with release branch and integrated with existing TTS infrastructure:

  1. Reused existing ttsTypes.ts instead of maintaining duplicate type definitions
  2. Extended existing types (AudioFormat, TTSOptions, TTSResult) rather than creating new ones
  3. Adapted implementation to use flat TTSResult structure matching existing codebase patterns
  4. Removed duplicate src/lib/types/tts.ts file
  5. Maintained single source of truth for TTS types across the codebase

Type System Refinement: Followed codebase convention by:

  1. Converting ITTSHandler from interface to type definition (export type ITTSHandler = { ... })
  2. Added missing text field to TTSOptions type for synthesis operations
  3. Maintains backward compatibility - classes can still implement the type in TypeScript

Import Path Corrections: Fixed build failures by:

  1. Correcting import paths from non-existent types/tts.js to types/ttsTypes.js
  2. Updating type names: TTSSynthesisOptions → TTSOptions, TTSAudioFormat → AudioFormat
  3. Added early validation for options.text to ensure type safety
  4. Applied corrections to both handler implementation and test files

Rebase Resolution: Fixed issues from bad rebase by:

  1. Extended AudioFormat type to include all OpenAI formats (aac, flac, pcm) in type definition
  2. Fixed TTSResult structure - changed from nested metadata object to flat structure matching type definition: { buffer, format, size, duration, voice, sampleRate }
  3. Updated VALID_AUDIO_FORMATS array to include all 7 supported formats
  4. Updated all README examples to use flat structure (result.size vs result.metadata.size)
  5. Ensured complete type consistency between handler implementation and type definitions

Test Enhancement: Significantly improved test coverage and quality:

  1. Added proper OpenAI client mocking with vi.mock() - tests no longer require API key
  2. Expanded from 14 to 39 comprehensive tests (+178% increase)
  3. Added successful synthesis test scenarios (previously only had validation tests)
  4. Added tests for all options: voices, formats, quality levels, speed control
  5. Added duration estimation and speed-adjusted duration tests
  6. Added TTSResult structure validation tests
  7. Added error handling tests for API and network failures
  8. Improved test organization with clear describe blocks
  9. Tests now run instantly without external API dependencies
  10. Better assertions using expect.arrayContaining() and array immutability checks

All 39 TTS unit tests pass with OpenAI v6, confirming backward compatibility, proper integration with existing type system, and comprehensive validation of all functionality.

Original prompt

This section details on the original issue you should resolve

<issue_title>TTS-008: Implement OpenAITTSHandler.synthesize()</issue_title>
<issue_description>## Summary
Implement the core synthesis method in OpenAITTSHandler that calls OpenAI's TTS API.

Technical Details

  • File(s): src/lib/adapters/tts/openaiTTSHandler.ts
  • Effort: 3h

Acceptance Criteria

  • Implemented synthesize() method in OpenAITTSHandler
  • Model selection: use tts-1-hd if quality is hd, else tts-1
  • Voice selection: default to alloy if not specified
  • Support all 6 OpenAI voices (alloy, echo, fable, onyx, nova, shimmer)
  • Support all OpenAI formats (mp3, opus, aac, flac, wav, pcm)
  • Speed control: 0.25x to 4.0x
  • Call client.audio.speech.create() API
  • Convert response ArrayBuffer to Buffer
  • Return TTSResult with buffer, format, metadata
  • Add duration estimation
  • Error handling for API failures
  • Track latency in metadata

Dependencies

  • Depends on: TTS-001, TTS-007
  • Blocks: TTS-003, TTS-020

Priority: high | Effort: 3h | Complexity: moderate</issue_description>

<agent_instructions>senior level implementation, reuse existing stuff, minimal changes implemenrtation
</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Summary by CodeRabbit

  • New Features

    • Added Text-to-Speech functionality with OpenAI integration
    • Support for six voices and six audio formats (mp3, opus, aac, flac, wav, pcm)
    • Configurable quality levels and speed control with input validation
  • Documentation

    • Added comprehensive TTS usage guide with practical examples and expected result structures
  • Tests

    • Added unit tests covering TTS handler functionality, validation, and supported options

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 4, 2025 •

Copy link
Copy Markdown

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The PR adds an OpenAI text-to-speech handler implementation with the OpenAITTSHandler class supporting six voices and audio formats, speed control, quality selection, comprehensive input validation, error handling, and logging, alongside type definitions, package exports, documentation, and unit tests.

Changes

Cohort / File(s) Summary
TTS Handler Implementation
src/lib/adapters/tts/openaiTTSHandler.ts, src/lib/adapters/tts/index.ts
New OpenAITTSHandler class implementing ITTSHandler with synthesize() method; validates text (4096 char limit), voice, format, and speed (0.25–4.0x); selects tts-1 or tts-1-hd model based on quality; calls OpenAI audio.speech.create API; converts response to Buffer; estimates duration; logs latency. Includes getSupportedVoices() and getSupportedFormats() helpers.
Types & Package Exports
src/lib/types/ttsTypes.ts, package.json
Extended AudioFormat union to include aac, flac, pcm; added optional text field to TTSOptions; introduced OpenAITTSVoice and ITTSHandler types; added openai runtime dependency; exported new public path ./adapters/tts with types and implementation mappings.
Documentation
src/lib/adapters/tts/README.md
Added comprehensive usage guide covering basic usage, supported voices/formats/quality levels, speed control, complete example, error handling, result structure inspection, and supported options retrieval with TypeScript code snippets.
Tests
test/unit/adapters/openaiTTSHandler.test.ts
New unit test suite validating constructor behavior, getSupportedVoices/getSupportedFormats outputs, input validation boundaries (text length, voice/format support, speed range 0.25–4.0), and error messages.

Sequence Diagram(s)

sequenceDiagram
    participant App as Client/App
    participant Handler as OpenAITTSHandler
    participant Validation as Input Validator
    participant OpenAI as OpenAI API
    participant Converter as Buffer Converter
    
    App->>Handler: synthesize(options)
    Handler->>Validation: validateInputs(text, voice, format, speed)
    alt Validation Failed
        Validation-->>Handler: throw ValidationError
        Handler-->>App: Promise<Error>
    else Validation Passed
        Validation-->>Handler: ✓ valid
        Handler->>Handler: selectModel(quality)
        Note over Handler: tts-1 or tts-1-hd
        Handler->>OpenAI: audio.speech.create({model, voice, input, response_format, speed})
        OpenAI-->>Handler: ArrayBuffer
        Handler->>Converter: convert(ArrayBuffer)
        Converter-->>Handler: Buffer
        Handler->>Handler: estimateDuration(text, speed)
        Note over Handler: Calculate latency & duration
        Handler-->>App: TTSResult {buffer, format, size, duration, voice, sampleRate}
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • openaiTTSHandler.ts: Core implementation contains validation logic, API integration, buffer conversion, and duration estimation—requires careful review of error handling, boundary conditions (text length 4096, speed 0.25–4.0), and API response handling.
  • Unit tests: Comprehensive coverage of validation scenarios and edge cases—verify test assertions align with implementation logic.
  • Type definitions: New ITTSHandler interface and OpenAITTSVoice union type should be checked for completeness and compatibility with package exports.

Possibly related PRs

Poem

🐰 Whiskers twitching, ears held high,
A voice adapter near and nigh,
OpenAI's melodies now ring,
Buffer bursts and formats sing—
TTS magic takes its flight! ✨

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: implementing the synthesize() method for OpenAI TTS handler, which is the core feature delivered in this PR.
Linked Issues check ✅ Passed All acceptance criteria from issue #479 are met: synthesize() method implemented with model selection, voice/format support, speed control (0.25-4.0x), API integration, ArrayBuffer-to-Buffer conversion, TTSResult return, duration estimation, error handling, and latency tracking.
Out of Scope Changes check ✅ Passed All changes directly support the TTS synthesis feature: openai dependency, type extensions, handler implementation, index exports, README documentation, and comprehensive unit tests are all within scope.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI changed the title [WIP] Implement OpenAITTSHandler.synthesize method Implement OpenAITTSHandler.synthesize() for text-to-speech synthesis Dec 4, 2025
Copilot AI requested a review from adarsh02125 December 4, 2025 11:00
@adarsh02125
adarsh02125 marked this pull request as ready for review December 5, 2025 02:56
Copilot AI review requested due to automatic review settings December 5, 2025 02:56

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

This PR implements text-to-speech synthesis functionality using OpenAI's TTS API. It introduces a new OpenAITTSHandler class that provides a type-safe interface for generating speech from text with support for multiple voices, formats, and quality levels.

  • Adds comprehensive TTS type system with interfaces for handlers, options, and results
  • Implements OpenAI TTS handler with full validation, error handling, and metadata tracking
  • Provides 14 unit tests covering edge cases and validation scenarios

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/lib/types/tts.ts Defines TTS type system including ITTSHandler interface, audio format types, and synthesis options/results
src/lib/types/index.ts Exports new TTS types from the main types module
src/lib/adapters/tts/openaiTTSHandler.ts Implements OpenAI TTS handler with model selection, voice support, format conversion, speed control, and comprehensive validation
src/lib/adapters/tts/index.ts Exports the OpenAI TTS handler for public API access
src/lib/adapters/tts/README.md Provides usage documentation with examples for all features and options
test/unit/adapters/openaiTTSHandler.test.ts Adds 14 unit tests covering constructor, voice/format support, and input validation including edge cases

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

@adarsh02125
adarsh02125 force-pushed the copilot/implement-openaittshandler-synthesize branch from 0acb251 to a6abf33 Compare December 5, 2025 02:59
@github-actions

github-actions Bot commented Dec 5, 2025 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: 3cd8e2617c45636d104995473a20f9db2cbbf1df
  • Message: feat(tts): Implement OpenAITTSHandler.synthesize() with all requirements
  • Author: Adarsh B A

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@github-actions

github-actions Bot commented Dec 5, 2025

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@adarsh02125

Copy link
Copy Markdown

@copilot workflows have failed, verify the details and implement the fix for the same

Copilot AI commented Dec 5, 2025 •

Copy link
Copy Markdown
Contributor Author

@copilot workflows have failed, verify the details and implement the fix for the same

Fixed the workflow failures. The issue was a missing openai package dependency in package.json.

Root cause: The OpenAITTSHandler implementation imports the official OpenAI SDK, but only @ai-sdk/openai was present in dependencies.

Fix applied (commit e69be7c):

  • Added openai@^4.104.0 to package.json dependencies

Verification:

  • ✅ TypeScript compilation: No errors
  • ✅ Full build: SDK and CLI build successfully
  • ✅ All 14 TTS unit tests passing
  • ✅ TTS files correctly generated in dist/

The CI workflows should now pass.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.openai.com
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --conditions development --conditions node /home/REDACTED/work/neurolink/neurolink/node_modules/tinypool/dist/entry/process.js -j ACCEPT (dns block)
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --conditions development --conditions node /home/REDACTED/work/neurolink/neurolink/node_modules/tinypool/dist/entry/process.js (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from adarsh02125 December 5, 2025 03:16
@adarsh02125
adarsh02125 force-pushed the copilot/implement-openaittshandler-synthesize branch from 5cc00a6 to 8b6a368 Compare December 5, 2025 03:19
@github-actions

github-actions Bot commented Dec 5, 2025

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@adarsh02125

Copy link
Copy Markdown

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Dec 5, 2025

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🧹 Nitpick comments (4)
test/unit/adapters/openaiTTSHandler.test.ts (2)

12-16: Clean up environment variable after test to prevent pollution.

Setting process.env.OPENAI_API_KEY persists across tests and could affect other test files. Consider using beforeEach/afterEach or Vitest's environment mocking.

+  describe("constructor", () => {
+    const originalEnv = process.env.OPENAI_API_KEY;
+
+    afterEach(() => {
+      process.env.OPENAI_API_KEY = originalEnv;
+    });
+
     it("should create handler with provided API key", () => {
       const handler = new OpenAITTSHandler("custom-key");
       expect(handler).toBeInstanceOf(OpenAITTSHandler);
     });
 
     it("should create handler with env var API key", () => {
       process.env.OPENAI_API_KEY = "env-key";
       const handler = new OpenAITTSHandler();
       expect(handler).toBeInstanceOf(OpenAITTSHandler);
     });
   });

77-90: Consider mocking the OpenAI client for cleaner tests.

The current approach works but relies on distinguishing validation errors from API errors by message content. Mocking the OpenAI client would make these tests more reliable and faster.

Example with Vitest mocking:

import { vi } from "vitest";
vi.mock("openai", () => ({
  default: vi.fn().mockImplementation(() => ({
    audio: {
      speech: {
        create: vi.fn().mockResolvedValue({
          arrayBuffer: () => Promise.resolve(new ArrayBuffer(100)),
        }),
      },
    },
  })),
}));
src/lib/types/tts.ts (2)

34-68: Consider provider-specific typing or generics for voice/model and handler methods

TTSSynthesisOptions.voice/model and ITTSHandler.getSupportedVoices() are typed as plain string, even though you have OpenAITTSVoice and provider-specific model sets.

If you later want stronger compile-time guarantees per provider, consider either:

  • defining provider-specific option types (e.g., OpenAITTSSynthesisOptions with voice?: OpenAITTSVoice), or
  • making ITTSHandler generic, e.g. ITTSHandler<TVoice extends string = string> and threading that through TTSSynthesisOptions.

Not urgent for this PR, but could improve ergonomics and type safety as more providers are added.

Based on learnings, this aligns with the goal of strict, domain-organized TypeScript types.

Also applies to: 128-147


73-123: Node-specific Buffer in public TTSResult may limit non-Node runtimes

Typing TTSResult.buffer as Buffer is fine if this SDK is explicitly Node-only, but it constrains you if you later want browser/edge support.

If multi-runtime support is a goal, consider:

  • using a more neutral type (e.g., Uint8Array), or
  • introducing an alias like export type TTSAudioBuffer = Buffer | Uint8Array; and using that in TTSResult.

That way adapters can still return Buffer in Node while keeping the public type surface more portable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a696cf and 8b6a368.

📒 Files selected for processing (7)
  • package.json (1 hunks)
  • src/lib/adapters/tts/README.md (1 hunks)
  • src/lib/adapters/tts/index.ts (1 hunks)
  • src/lib/adapters/tts/openaiTTSHandler.ts (1 hunks)
  • src/lib/types/index.ts (1 hunks)
  • src/lib/types/tts.ts (1 hunks)
  • test/unit/adapters/openaiTTSHandler.test.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: vigneshJuspay
Repo: juspay/neurolink PR: 237
File: memory-bank/tts-provider-implementation-plan.md:92-106
Timestamp: 2025-11-17T13:53:20.209Z
Learning: In PR 237's TTS modality implementation approach, TTS functionality uses GOOGLE_AI_API_KEY (not GOOGLE_TTS_API_KEY) when using the google-ai provider. TTS is implemented as an output modality that leverages the existing google-ai provider authentication.
📚 Learning: 2025-11-17T13:53:20.209Z
Learnt from: vigneshJuspay
Repo: juspay/neurolink PR: 237
File: memory-bank/tts-provider-implementation-plan.md:92-106
Timestamp: 2025-11-17T13:53:20.209Z
Learning: In PR 237's TTS modality implementation approach, TTS functionality uses GOOGLE_AI_API_KEY (not GOOGLE_TTS_API_KEY) when using the google-ai provider. TTS is implemented as an output modality that leverages the existing google-ai provider authentication.

Applied to files:

  • src/lib/adapters/tts/README.md
  • src/lib/types/tts.ts
  • src/lib/adapters/tts/openaiTTSHandler.ts
📚 Learning: 2025-12-01T08:39:22.794Z
Learnt from: CR
Repo: juspay/neurolink PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T08:39:22.794Z
Learning: Maintain strict TypeScript type safety across all modules and organize types by domain (providers, generation, streaming, MCP, etc.) to avoid circular dependencies

Applied to files:

  • src/lib/types/tts.ts
📚 Learning: 2025-09-17T17:55:15.261Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 173
File: src/lib/index.ts:16-16
Timestamp: 2025-09-17T17:55:15.261Z
Learning: In src/lib/types/providers.ts, ProviderConfig was renamed to AIModelProviderConfig to deduplicate type names, as there was an existing ProviderConfig type that better suited the "ProviderConfig" name. This was an intentional breaking change for better type organization.

Applied to files:

  • src/lib/types/tts.ts
  • src/lib/adapters/tts/openaiTTSHandler.ts
  • src/lib/types/index.ts
📚 Learning: 2025-11-11T14:02:21.868Z
Learnt from: vigneshJuspay
Repo: juspay/neurolink PR: 214
File: src/lib/index.ts:205-233
Timestamp: 2025-11-11T14:02:21.868Z
Learning: In the NeuroLink TTS SDK (src/lib/tts/), use GOOGLE_TTS_API_KEY environment variable specifically for Google Cloud Text-to-Speech access. GOOGLE_AI_API_KEY does not provide TTS access and should not be used for TTS functionality. The keys are intentionally kept separate for better access control and separation of concerns.

Applied to files:

  • src/lib/types/tts.ts
  • src/lib/adapters/tts/openaiTTSHandler.ts
📚 Learning: 2025-11-04T22:14:18.719Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 0
File: :0-0
Timestamp: 2025-11-04T22:14:18.719Z
Learning: In the juspay/neurolink repository, all new type definitions must be placed in src/lib/types/. New type definitions outside this directory should be flagged and blocked in code reviews.

Applied to files:

  • src/lib/types/index.ts
📚 Learning: 2025-12-01T08:39:22.794Z
Learnt from: CR
Repo: juspay/neurolink PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T08:39:22.794Z
Learning: Use MessageBuilder (src/lib/utils/messageBuilder.ts) as the central component for constructing all messages with multimodal support

Applied to files:

  • src/lib/types/index.ts
📚 Learning: 2025-09-02T13:50:42.770Z
Learnt from: YasmeenOgo
Repo: juspay/neurolink PR: 145
File: src/lib/core/types.ts:0-0
Timestamp: 2025-09-02T13:50:42.770Z
Learning: The APIVersions enum in src/lib/core/types.ts now contains comprehensive API version constants for all major AI providers: Azure OpenAI (latest, stable, legacy), OpenAI (current, beta), Google AI (current, beta), and Anthropic (current). This centralization helps avoid API version drift across the codebase.

Applied to files:

  • package.json
🧬 Code graph analysis (2)
src/lib/adapters/tts/openaiTTSHandler.ts (1)
src/lib/types/tts.ts (5)
  • ITTSHandler (128-147)
  • OpenAITTSVoice (23-29)
  • TTSAudioFormat (13-13)
  • TTSSynthesisOptions (34-68)
  • TTSResult (73-123)
test/unit/adapters/openaiTTSHandler.test.ts (2)
src/lib/adapters/tts/index.ts (1)
  • OpenAITTSHandler (9-9)
src/lib/adapters/tts/openaiTTSHandler.ts (1)
  • OpenAITTSHandler (25-201)
🔇 Additional comments (11)
src/lib/types/index.ts (1)

216-218: LGTM!

The TTS type re-exports follow the established pattern and are properly placed in the centralized types directory. Based on learnings, this aligns with the project convention that all new type definitions must be placed in src/lib/types/.

src/lib/adapters/tts/index.ts (1)

1-9: LGTM!

Clean barrel file pattern with proper JSDoc documentation. The structure allows for easy addition of future TTS handlers (e.g., GoogleTTSHandler, AzureTTSHandler).

test/unit/adapters/openaiTTSHandler.test.ts (2)

19-45: Good coverage for capability getters.

The tests properly verify all expected voices and formats are returned.


47-68: Thorough text validation testing.

Good coverage of empty text, whitespace-only text, and text exceeding the 4096 character limit.

src/lib/adapters/tts/openaiTTSHandler.ts (6)

1-21: Good module documentation and imports.

Clear documentation of supported models, voices, and formats. Proper type imports from the types module.


44-52: Constructor follows standard pattern.

Lazy API key validation (deferred to API call time) is acceptable. The OpenAI SDK will throw a clear error if the key is missing when synthesize() is called.


99-102: Duration estimation is a rough heuristic — consider documenting limitations.

The 150 words/minute estimate is reasonable for typical speech, but actual duration varies by voice, language, and content. The metadata.duration is typed as optional (duration?: number), which correctly signals it's an estimate.


125-140: Solid error handling with context preservation.

Logging before re-throwing aids debugging. The error wrapping provides useful context about the operation that failed.


151-184: Comprehensive input validation.

All inputs are validated with clear error messages. The validation order (text → voice → format → speed) ensures users get the most relevant error first.


186-200: LGTM!

Defensive copying via spread operator prevents external mutation of internal state.

src/lib/types/tts.ts (1)

13-29: Union types for formats/quality/voices look solid and aligned with requirements

The string-literal unions for TTSAudioFormat, TTSQuality, and OpenAITTSVoice cleanly model the supported capabilities and give good autocomplete/validation. This matches the stated OpenAI TTS formats and voices.

Comment thread package.json Outdated
Comment thread src/lib/adapters/tts/README.md
Comment thread src/lib/adapters/tts/README.md
@adarsh02125

Copy link
Copy Markdown

@copilot review the comments that coderabbit has given, if valid implement the changes else skip

Copilot AI commented Dec 5, 2025 •

Copy link
Copy Markdown
Contributor Author

@copilot review the comments that coderabbit has given, if valid implement the changes else skip

Reviewed and implemented CodeRabbit's feedback (commit 15f1ff2):

✅ Fixed Issues:

  1. Major - Import path error: Added "./adapters/tts" export to package.json. The documentation examples now work correctly with import { OpenAITTSHandler } from "@juspay/neurolink/adapters/tts"

  2. Minor - OpenAI version: Upgraded from v4.104.0 to v6.10.0 (latest stable). The TTS API is backward compatible, and v6 provides security updates and new features.

Validation:

  • ✅ All 14 TTS tests passing
  • ✅ Build successful
  • ✅ TypeScript compilation clean
  • ✅ Package exports validated

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.openai.com
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --conditions development --conditions node /home/REDACTED/work/neurolink/neurolink/node_modules/tinypool/dist/entry/process.js (dns block)
  • googlechromelabs.github.io
    • Triggering command: /usr/local/bin/node node install.mjs (dns block)
  • https://storage.googleapis.com/chrome-for-testing-public/143.0.7499.40/linux64/chrome-linux64.zip
    • Triggering command: /usr/local/bin/node node install.mjs (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@adarsh02125
adarsh02125 force-pushed the copilot/implement-openaittshandler-synthesize branch from b1c4551 to 6c88275 Compare December 7, 2025 04:47
@github-actions

github-actions Bot commented Dec 7, 2025

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@adarsh02125

Copy link
Copy Markdown

@copilot read through the complete implementation and fix the same.

build is failing, seems like it was a bad rebase

Copilot AI commented Dec 7, 2025

Copy link
Copy Markdown
Contributor Author

@copilot read through the complete implementation and fix the same.

build is failing, seems like it was a bad rebase

Fixed all implementation issues from the bad rebase (commit ac9d964):

Issues resolved:

  1. Extended AudioFormat type to include OpenAI formats (aac, flac, pcm) - was missing from type definition
  2. Fixed TTSResult structure - changed from nested metadata object to flat structure matching type definition
  3. Updated README examples to use flat structure (result.size vs result.metadata.size)

Type consistency:

  • Handler now returns flat TTSResult: { buffer, format, size, duration, voice, sampleRate }
  • All 7 audio formats properly defined in type and validation array
  • Documentation examples match implementation

Build should now pass successfully.

@adarsh02125
adarsh02125 force-pushed the copilot/implement-openaittshandler-synthesize branch from ac9d964 to ea93477 Compare December 7, 2025 06:26
@github-actions

github-actions Bot commented Dec 7, 2025

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@adarsh02125
adarsh02125 force-pushed the copilot/implement-openaittshandler-synthesize branch from ea93477 to 398a721 Compare December 7, 2025 06:35
@github-actions

github-actions Bot commented Dec 7, 2025

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@adarsh02125
adarsh02125 force-pushed the copilot/implement-openaittshandler-synthesize branch from 398a721 to 3cd8e26 Compare December 7, 2025 06:43
@github-actions

github-actions Bot commented Dec 7, 2025

Copy link
Copy Markdown
Contributor

🤖 AI Review & Build Compliance ✅

Status: AI analysis complete • Build rules validated • Ready for review

📊 View detailed analysis results

🛡️ Analysis Complete

  • ✅ Security scan (vulnerabilities, API keys)
  • ✅ TypeScript safety & code quality
  • ✅ Error handling & best practices
  • ✅ Build rule enforcement validated
  • ✅ Commit format & compliance checks

📋 Ready for Merge When

  • All CI checks passing
  • Manual review approved
  • Any AI-flagged issues resolved

🤖 AI analysis complete - check individual code comments for specific feedback

@adarsh02125

Copy link
Copy Markdown

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Dec 7, 2025

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/lib/adapters/tts/README.md (1)

7-9: Import path issue resolved.

The import path @juspay/neurolink/adapters/tts is now valid since package.json exports have been updated to include ./adapters/tts. This addresses the previous review feedback.

🧹 Nitpick comments (6)
src/lib/types/ttsTypes.ts (1)

22-25: Consider making text required in TTSOptions type.

The text field is optional (text?: string), but the synthesize method throws if text is missing. Making it required at the type level would provide compile-time safety rather than relying solely on runtime validation.

However, this may be intentional if TTSOptions is used in other contexts where text is not always required (e.g., configuration objects).

 export type TTSOptions = {
   /** Text to synthesize */
-  text?: string;
+  text: string;
   /** Enable TTS output */
test/unit/adapters/openaiTTSHandler.test.ts (1)

12-16: Clean up environment variable after test.

Setting process.env.OPENAI_API_KEY without cleanup can leak state to subsequent tests, potentially causing flaky behavior.

+import { beforeEach, afterEach, describe, it, expect } from "vitest";
+
+// At the top of the describe block or in a beforeEach/afterEach:
+let originalApiKey: string | undefined;
+
+beforeEach(() => {
+  originalApiKey = process.env.OPENAI_API_KEY;
+});
+
+afterEach(() => {
+  if (originalApiKey === undefined) {
+    delete process.env.OPENAI_API_KEY;
+  } else {
+    process.env.OPENAI_API_KEY = originalApiKey;
+  }
+});
src/lib/adapters/tts/openaiTTSHandler.ts (4)

22-25: Consider reusing types from ttsTypes.ts to prevent drift.

OpenAIAudioFormat is defined locally but partially overlaps with AudioFormat from ttsTypes.ts. If AudioFormat changes (e.g., adding "ogg" variants), this local type won't be updated, potentially causing inconsistencies.

You could derive this type or add a comment noting the intentional subset:

/**
 * Audio formats supported by OpenAI's TTS API
 * Note: Intentionally excludes "ogg" which is in AudioFormat but not supported by OpenAI
 */
type OpenAIAudioFormat = Exclude<AudioFormat, "ogg">;

72-79: Potential issue with "ogg" format handling.

The format value comes from TTSOptions.format which can be "ogg" (part of AudioFormat), but "ogg" is not in supportedFormats. The cast to OpenAIAudioFormat on line 74 occurs before validation on line 79, so an unsupported format will be caught, but the type cast is technically unsafe.

Consider validating format before casting or using a type guard:

-const format = (options.format || "mp3") as OpenAIAudioFormat;
+const format = options.format || "mp3";
+
+// Validate inputs (including format check)
+this.validateInputs(options.text, voice, format, speed);
+
+// Safe cast after validation
+const validatedFormat = format as OpenAIAudioFormat;

67-70: Consider using ErrorFactory for typed errors instead of plain Error objects.

Per coding guidelines, src/lib/**/*.ts files should use ErrorFactory for creating typed errors. This file uses plain Error objects throughout (lines 69, ~104, ~136, ~140, ~145, ~152, ~159). Import ErrorFactory from src/lib/utils/errorHandling.ts and replace all instances with appropriate factory methods.


94-100: Add timeout protection to the OpenAI TTS API call.

The OpenAI API call at lines 94-100 lacks timeout protection. Per coding guidelines, async operations in src/lib/**/*.ts should use the withTimeout utility to prevent hanging requests. The pattern from the codebase shows wrapping with an Error object created by ErrorFactory.

-import OpenAI from "openai";
-import { logger } from "../../utils/logger.js";
+import OpenAI from "openai";
+import { logger } from "../../utils/logger.js";
+import { withTimeout } from "../../utils/errorHandling.js";
+import { ErrorFactory } from "../../utils/errorHandling.js";

       // Call OpenAI TTS API
-      const response = await this.client.audio.speech.create({
+      const response = await withTimeout(
+        this.client.audio.speech.create({
           model,
           voice,
           input: options.text,
           response_format: format,
           speed,
-      });
+        }),
+        30000,
+        ErrorFactory.toolTimeout("openai-tts", 30000)
+      );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2bd877b and 3cd8e26.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • package.json (2 hunks)
  • src/lib/adapters/tts/README.md (1 hunks)
  • src/lib/adapters/tts/index.ts (1 hunks)
  • src/lib/adapters/tts/openaiTTSHandler.ts (1 hunks)
  • src/lib/types/ttsTypes.ts (4 hunks)
  • test/unit/adapters/openaiTTSHandler.test.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/lib/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/lib/**/*.ts: Use ErrorFactory for creating typed errors in error handling
Use withTimeout utility to wrap async operations for timeout protection

Files:

  • src/lib/types/ttsTypes.ts
  • src/lib/adapters/tts/index.ts
  • src/lib/adapters/tts/openaiTTSHandler.ts
src/lib/types/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Add model definitions to appropriate model enum when adding a new provider

Files:

  • src/lib/types/ttsTypes.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.ts: Mock external API calls for unit tests and use real API calls sparingly in integration tests
Validate multimodal content handling in tests when adding new file types

Files:

  • test/unit/adapters/openaiTTSHandler.test.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: vigneshJuspay
Repo: juspay/neurolink PR: 237
File: memory-bank/tts-provider-implementation-plan.md:92-106
Timestamp: 2025-11-17T13:53:20.209Z
Learning: In PR 237's TTS modality implementation approach, TTS functionality uses GOOGLE_AI_API_KEY (not GOOGLE_TTS_API_KEY) when using the google-ai provider. TTS is implemented as an output modality that leverages the existing google-ai provider authentication.
Learnt from: swaroopvarma1
Repo: juspay/neurolink PR: 141
File: docs/REAL-TIME-SPEECH-AGENTS.md:124-149
Timestamp: 2025-09-01T14:12:14.227Z
Learning: In the NeuroLink Speech-to-Speech agent system, the team prefers simple void-returning APIs (sendAudioFrame, sendText, flush) over Promise-based backpressure mechanisms, prioritizing ease of use and implementation simplicity for real-time speech processing.
📚 Learning: 2025-09-02T13:50:42.770Z
Learnt from: YasmeenOgo
Repo: juspay/neurolink PR: 145
File: src/lib/core/types.ts:0-0
Timestamp: 2025-09-02T13:50:42.770Z
Learning: The APIVersions enum in src/lib/core/types.ts now contains comprehensive API version constants for all major AI providers: Azure OpenAI (latest, stable, legacy), OpenAI (current, beta), Google AI (current, beta), and Anthropic (current). This centralization helps avoid API version drift across the codebase.

Applied to files:

  • src/lib/types/ttsTypes.ts
  • package.json
📚 Learning: 2025-09-17T17:55:15.261Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 173
File: src/lib/index.ts:16-16
Timestamp: 2025-09-17T17:55:15.261Z
Learning: In src/lib/types/providers.ts, ProviderConfig was renamed to AIModelProviderConfig to deduplicate type names, as there was an existing ProviderConfig type that better suited the "ProviderConfig" name. This was an intentional breaking change for better type organization.

Applied to files:

  • src/lib/types/ttsTypes.ts
📚 Learning: 2025-09-01T22:58:39.149Z
Learnt from: sudharsan-juspay
Repo: juspay/neurolink PR: 140
File: src/lib/core/types.ts:198-203
Timestamp: 2025-09-01T22:58:39.149Z
Learning: In src/lib/core/types.ts, StreamOptions (imported from streamTypes.js) and StreamingOptions are intentionally different types with different use cases. StreamingOptions is for unified AI requests with multiple provider configurations, while StreamOptions is for individual streaming operations.

Applied to files:

  • src/lib/types/ttsTypes.ts
📚 Learning: 2025-12-06T11:08:18.370Z
Learnt from: CR
Repo: juspay/neurolink PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T11:08:18.370Z
Learning: Applies to src/lib/types/index.ts : Add new provider names to the AIProviderName enum

Applied to files:

  • src/lib/types/ttsTypes.ts
📚 Learning: 2025-12-06T11:08:18.370Z
Learnt from: CR
Repo: juspay/neurolink PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T11:08:18.370Z
Learning: Applies to test/**/*.test.ts : Validate multimodal content handling in tests when adding new file types

Applied to files:

  • src/lib/types/ttsTypes.ts
  • test/unit/adapters/openaiTTSHandler.test.ts
📚 Learning: 2025-11-17T13:53:20.209Z
Learnt from: vigneshJuspay
Repo: juspay/neurolink PR: 237
File: memory-bank/tts-provider-implementation-plan.md:92-106
Timestamp: 2025-11-17T13:53:20.209Z
Learning: In PR 237's TTS modality implementation approach, TTS functionality uses GOOGLE_AI_API_KEY (not GOOGLE_TTS_API_KEY) when using the google-ai provider. TTS is implemented as an output modality that leverages the existing google-ai provider authentication.

Applied to files:

  • src/lib/types/ttsTypes.ts
  • src/lib/adapters/tts/openaiTTSHandler.ts
📚 Learning: 2025-12-06T11:08:18.370Z
Learnt from: CR
Repo: juspay/neurolink PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T11:08:18.370Z
Learning: Applies to test/**/*.test.ts : Mock external API calls for unit tests and use real API calls sparingly in integration tests

Applied to files:

  • test/unit/adapters/openaiTTSHandler.test.ts
📚 Learning: 2025-11-04T22:14:18.719Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 0
File: :0-0
Timestamp: 2025-11-04T22:14:18.719Z
Learning: In the juspay/neurolink repository, all new type definitions must be placed in src/lib/types/. New type definitions outside this directory should be flagged and blocked in code reviews.

Applied to files:

  • src/lib/adapters/tts/README.md
📚 Learning: 2025-11-05T20:31:04.103Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 227
File: src/lib/utils/redis.ts:15-15
Timestamp: 2025-11-05T20:31:04.103Z
Learning: In the juspay/neurolink repository, type centralization rules (requiring types in src/lib/types/) do not apply to private, non-exported utility types used within a single file. Simple readability helpers like `type RedisClient = ReturnType<typeof createClient>` should remain in their implementation file when they are not exported and only used locally. Only exported types shared across modules, business/domain types, and public API types require centralization.

Applied to files:

  • src/lib/adapters/tts/README.md
📚 Learning: 2025-11-04T22:14:18.719Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 0
File: :0-0
Timestamp: 2025-11-04T22:14:18.719Z
Learning: In the juspay/neurolink repository, do not flag existing type or interface definitions located outside src/lib/types/ - these are part of a phased migration plan and will be addressed in upcoming PRs. Only enforce type centralization rules on new code going forward.

Applied to files:

  • src/lib/adapters/tts/README.md
📚 Learning: 2025-11-04T22:14:18.719Z
Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 0
File: :0-0
Timestamp: 2025-11-04T22:14:18.719Z
Learning: In the juspay/neurolink repository, new type definitions should use the `type` keyword instead of `interface`, unless there is a valid and justified exception. Flag new interface declarations in code reviews.

Applied to files:

  • src/lib/adapters/tts/README.md
📚 Learning: 2025-11-11T14:02:21.868Z
Learnt from: vigneshJuspay
Repo: juspay/neurolink PR: 214
File: src/lib/index.ts:205-233
Timestamp: 2025-11-11T14:02:21.868Z
Learning: In the NeuroLink TTS SDK (src/lib/tts/), use GOOGLE_TTS_API_KEY environment variable specifically for Google Cloud Text-to-Speech access. GOOGLE_AI_API_KEY does not provide TTS access and should not be used for TTS functionality. The keys are intentionally kept separate for better access control and separation of concerns.

Applied to files:

  • src/lib/adapters/tts/README.md
🧬 Code graph analysis (2)
test/unit/adapters/openaiTTSHandler.test.ts (1)
src/lib/adapters/tts/openaiTTSHandler.ts (1)
  • OpenAITTSHandler (30-206)
src/lib/adapters/tts/openaiTTSHandler.ts (1)
src/lib/types/ttsTypes.ts (5)
  • ITTSHandler (164-183)
  • OpenAITTSVoice (153-159)
  • TTSOptions (22-39)
  • TTSResult (44-57)
  • AudioFormat (12-12)
🔇 Additional comments (13)
src/lib/adapters/tts/index.ts (1)

1-9: LGTM!

Clean barrel export file with proper ESM .js extension and module documentation.

package.json (2)

149-154: LGTM!

The new ./adapters/tts export is correctly configured with types, import, and default paths matching the existing export patterns. This resolves the previously flagged documentation import path issue.


197-197: OpenAI dependency version looks good.

The openai@^6.10.0 version addresses the previous review feedback about using the latest v6.x series.

src/lib/adapters/tts/README.md (1)

1-186: Comprehensive documentation.

The README thoroughly covers all handler capabilities with clear examples for voices, formats, quality levels, speed control, error handling, and result structure. Well organized and matches the implementation.

src/lib/types/ttsTypes.ts (3)

12-12: LGTM!

The AudioFormat union correctly extends to include all OpenAI-supported formats (aac, flac, pcm) while maintaining backward compatibility with existing formats.


149-159: LGTM!

The OpenAITTSVoice type correctly uses the type keyword (per repo conventions) and enumerates all six OpenAI voices.


161-183: LGTM!

The ITTSHandler type is well-defined with proper JSDoc comments and uses type instead of interface per repository conventions.

test/unit/adapters/openaiTTSHandler.test.ts (1)

1-137: Good validation test coverage.

The tests comprehensively cover constructor behavior, supported voices/formats, and input validation boundaries (empty text, whitespace, max length, invalid voice/format, speed limits). The validation error assertions are well-targeted.

src/lib/adapters/tts/openaiTTSHandler.ts (5)

1-21: LGTM!

Clear module documentation and proper imports using ESM .js extensions.


109-112: Duration estimation is a rough approximation.

The comment clearly documents this limitation. Consider adding this caveat to the TTSResult.duration JSDoc or README to set proper expectations for consumers.


130-145: Good error handling with context logging.

The error handling properly logs failure context (latency, model, voice, format) and wraps the error with enhanced information. This aids debugging production issues.


156-189: LGTM!

Comprehensive input validation covering text presence, length limits, voice/format support, and speed boundaries. Error messages are clear and actionable.


191-205: LGTM!

Helper methods correctly return copies of internal arrays to prevent mutation.

Comment on lines +77 to +90
it("should accept all supported voices", async () => {
const handler = new OpenAITTSHandler("test-key");
const voices = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"];

for (const voice of voices) {
// This will fail with API error but validation should pass
try {
await handler.synthesize({ text: "test", voice });
} catch (error) {
// Should not be a validation error
expect((error as Error).message).not.toContain("Unsupported voice");
}
}
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Mock the OpenAI API calls in unit tests.

This test makes real API calls to OpenAI, which violates the coding guideline to "mock external API calls for unit tests." The test pattern of catching errors and checking they're "not validation errors" is fragile and depends on network availability.

Consider mocking the OpenAI client:

import { vi } from "vitest";

// Mock the OpenAI module
vi.mock("openai", () => ({
  default: vi.fn().mockImplementation(() => ({
    audio: {
      speech: {
        create: vi.fn().mockResolvedValue({
          arrayBuffer: () => Promise.resolve(new ArrayBuffer(100)),
        }),
      },
    },
  })),
}));

As per coding guidelines, external API calls should be mocked for unit tests.

🤖 Prompt for AI Agents
In test/unit/adapters/openaiTTSHandler.test.ts around lines 77 to 90, the test
performs real OpenAI API calls; replace those with a mock of the OpenAI client
so unit tests don’t hit the network. Mock the module used by OpenAITTSHandler
(e.g., with vi.mock or your test runner’s mocking utility) to return a fake
client whose audio.speech.create resolves with a predictable ArrayBuffer (or
rejects for specific cases), then update the test to call handler.synthesize and
assert behavior against the mocked response (keeping the original check that
thrown errors are not validation errors).

Comment on lines +117 to +135
it("should accept speed of exactly 0.25", async () => {
const handler = new OpenAITTSHandler("test-key");
try {
await handler.synthesize({ text: "test", speed: 0.25 });
} catch (error) {
// Should not be a speed validation error
expect((error as Error).message).not.toContain("Speed must be between");
}
});

it("should accept speed of exactly 4.0", async () => {
const handler = new OpenAITTSHandler("test-key");
try {
await handler.synthesize({ text: "test", speed: 4.0 });
} catch (error) {
// Should not be a speed validation error
expect((error as Error).message).not.toContain("Speed must be between");
}
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Mock API calls for speed boundary tests.

These tests also make real API calls. With proper mocking, you can assert that synthesize completes successfully rather than relying on error message inspection.

With mocked API calls, these tests become deterministic:

it("should accept speed of exactly 0.25", async () => {
  const handler = new OpenAITTSHandler("test-key");
  const result = await handler.synthesize({ text: "test", speed: 0.25 });
  expect(result.buffer).toBeDefined();
});

As per coding guidelines, external API calls should be mocked for unit tests.

🤖 Prompt for AI Agents
In test/unit/adapters/openaiTTSHandler.test.ts around lines 117 to 135, the two
boundary tests currently rely on real API calls and catch errors to assert no
speed validation error; replace those with deterministic mocks of the OpenAI TTS
API (use Jest mocks or nock to intercept the handler's network call or the
underlying client method) so synthesize resolves successfully for speed=0.25 and
speed=4.0, then assert the returned result (e.g., result.buffer or equivalent)
is defined; ensure the mock returns the same shape the handler expects and
remove the try/catch error-inspection assertions.

@adarsh02125

Copy link
Copy Markdown

@copilot review coderabbit's recent comments on improving test files and make necessary changes. Use the prompts that coderabbit has suggested in the comments and complete this task

Copilot AI commented Dec 7, 2025 •

Copy link
Copy Markdown
Contributor Author

@copilot review coderabbit's recent comments on improving test files and make necessary changes. Use the prompts that coderabbit has suggested in the comments and complete this task

I don't see CodeRabbit's specific comments in the PR thread. Could you please share the specific suggestions or prompts that CodeRabbit provided? Alternatively, I can:

  1. Add mock implementations for the OpenAI client to enable successful test scenarios
  2. Add tests for successful synthesis with different configurations
  3. Verify the TTSResult structure is returned correctly
  4. Add edge case tests for all supported formats and voices

Which improvements would you like me to prioritize?

@copilot review coderabbit's recent comments on improving test files and make necessary changes. Use the prompts that coderabbit has suggested in the comments and complete this task

Enhanced the test file with comprehensive improvements (commit 94a7ad7):

Major improvements:

  1. Added OpenAI client mocking - Tests no longer require API key or make real API calls
  2. 39 tests total (up from 14) covering:
    • Successful synthesis scenarios with all options
    • Model selection (tts-1 vs tts-1-hd)
    • All voices and formats individually tested
    • Duration estimation and speed-adjusted calculations
    • TTSResult structure validation
    • Error handling (API errors, network failures)
  3. Better test organization - Grouped by functionality with clear describe blocks
  4. Fast & reliable - Mocked tests run instantly without external dependencies

Tests now properly validate the implementation without requiring OpenAI API access.

…overage

Co-authored-by: adarsh-bhaskar <207358788+adarsh-bhaskar@users.noreply.github.com>
@murdore

murdore commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Closing as part of project audit (2026-03-29). This PR does not align with current project architecture/conventions, or is broken/empty. See docs/project-audit-2026-03-29.md for details.

@murdore murdore closed this Mar 29, 2026
@murdore
murdore deleted the copilot/implement-openaittshandler-synthesize branch March 29, 2026 07:33
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.

TTS-008: Implement OpenAITTSHandler.synthesize() AUDIO-028: Add openai Package Dependency

4 participants