Skip to content

feat(groq): Add TTS adapter#346

Open
dhamivibez wants to merge 3 commits into
TanStack:mainfrom
dhamivibez:feat/groq-tts
Open

feat(groq): Add TTS adapter#346
dhamivibez wants to merge 3 commits into
TanStack:mainfrom
dhamivibez:feat/groq-tts

Conversation

@dhamivibez

@dhamivibez dhamivibez commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Adds a tree-shakeable Text-to-Speech (TTS) adapter for the Groq API. This includes support for English and Arabic voices, various output formats (with WAV as default),
and configuration options like speed and sample rate.

Includes new types, model metadata for TTS models, and comprehensive unit tests.

🎯 Changes

  • Added a tree-shakeable Text-to-Speech (TTS) adapter for the Groq API.
  • Added support for English and Arabic voices.
  • Added configurable output formats (default: WAV), speed, and sample rate.
  • Introduced new types and model metadata for TTS models.
  • Added comprehensive unit tests for the TTS adapter.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features
    • Added Groq text-to-speech support with English and Arabic Orpheus voices.
    • Supports multiple output formats (WAV default).
    • Added configurable playback speed and sample rate.
    • Includes model metadata in the audio response, with safer error logging.
    • Added convenience helpers for creating the TTS adapter (including env-based API key usage).
  • Tests
    • Added unit tests for the Groq TTS adapter.

@coderabbitai

coderabbitai Bot commented Mar 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Groq TTS adapter module and a changeset entry marking @tanstack/ai-groq for a minor release. The adapter adds public config and factory helpers, request/response handling for speech generation, and content-type mapping for returned audio.

Changes

Groq TTS Adapter

Layer / File(s) Summary
Public config and factories
packages/ai-groq/src/adapters/tts.ts
Adds GroqTTSConfig and the createGroqSpeech and groqSpeech factory helpers.
Speech request and response flow
packages/ai-groq/src/adapters/tts.ts
Validates TTS input, builds the Groq/OpenAI-compatible speech request, calls the speech endpoint, converts audio to base64, and maps output formats to content types.
Minor release changeset
.changeset/groq-tts-adapter.md
Marks @tanstack/ai-groq for a minor version bump and records the adapter addition.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

A rabbit found a TTS tune in the breeze,
With Groq in its paws and WAV files with ease.
It hopped through requests, then home with a sound,
And left a small changeset rustling around.
🐇🎙️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a Groq TTS adapter.
Description check ✅ Passed The description matches the template and includes changes, checklist items, and release impact notes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@nx-cloud

nx-cloud Bot commented Mar 6, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 076c52c

Command Status Duration Result
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 5s View ↗

☁️ Nx Cloud last updated this comment at 2026-06-24 10:56:14 UTC

@pkg-pr-new

pkg-pr-new Bot commented Mar 6, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@346

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@346

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@346

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@346

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@346

@tanstack/ai-code-mode-skills

npm i https://pkg.pr.new/@tanstack/ai-code-mode-skills@346

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@346

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@346

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@346

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@346

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@346

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@346

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@346

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@346

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@346

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@346

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@346

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@346

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@346

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@346

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@346

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@346

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@346

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@346

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@346

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@346

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@346

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@346

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@346

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@346

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@346

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@346

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@346

commit: ba6b1f2

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/typescript/ai-groq/src/utils/schema-converter.ts (1)

53-91: ⚠️ Potential issue | 🟠 Major

Preserve strict object normalization for schemas without properties.

Line 53 now skips { type: 'object' } schemas entirely, so structuredOutput() can send a strict schema without additionalProperties: false when the AI layer omits properties. packages/typescript/ai-groq/src/adapters/text.ts:134-182 passes that result straight to Groq, so this regresses zero-property object outputs and nested object schemas that are declared without a properties key.

Suggested fix
-  if (result.type === 'object' && result.properties) {
-    const properties = { ...result.properties }
+  if (result.type === 'object') {
+    const properties = { ...(result.properties ?? {}) }
     const allPropertyNames = Object.keys(properties)

     for (const propName of allPropertyNames) {
       const prop = properties[propName]
       const wasOptional = !originalRequired.includes(propName)
@@
     }

     result.properties = properties
     result.required = allPropertyNames
     result.additionalProperties = false
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai-groq/src/utils/schema-converter.ts` around lines 53 -
91, The code currently only normalizes object schemas when result.properties
exists, skipping strict normalization for plain { type: 'object' } and nested
object/array items that lack a properties key; update the logic in
makeGroqStructuredOutputCompatible so that when result.type === 'object' but
result.properties is absent or empty you still enforce strict output by setting
result.properties = result.properties || {} (or leave empty object),
result.required = [], and result.additionalProperties = false; also ensure the
same normalization is applied to nested schemas passed into the recursive calls
(e.g., where prop.type === 'object' and prop.properties may be undefined, and
for array items via prop.items) so zero-property objects and nested object
schemas without a properties key remain strict.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/typescript/ai-groq/src/adapters/tts.ts`:
- Around line 64-65: The code uses Node-only
Buffer.from(arrayBuffer).toString('base64') to produce base64 for the TTS
response (see variables arrayBuffer and base64), which breaks in browsers;
replace that call with an isomorphic encoder (e.g. add a helper
base64Encode(arrayBuffer) that checks for global Buffer and uses
Buffer.from(...).toString('base64') in Node, and uses a browser path (Uint8Array
-> binary string -> btoa) otherwise) and use that helper where base64 is
computed; this keeps compatibility with the existing browser-oriented window.env
lookup in the same adapter.
- Around line 46-60: In generateSpeech, stop using the caller-supplied model and
replace the request.model with this.model (the adapter-configured model) and
remove the unchecked casts of voice/format; validate the incoming options.voice
and options.format against explicit allow-lists (e.g., allowed voices and
allowed formats matching GroqTTSVoice and GroqTTSFormat) and fall back to safe
defaults ('autumn' for voice, 'wav' for format) only after validation; update
the construction of Groq_SDK.Audio.Speech.SpeechCreateParams in generateSpeech
to use validatedVoice and validatedFormat variables and preserve other fields
(input, speed, ...modelOptions) so unsupported values are rejected before
calling the Groq API.

In `@packages/typescript/ai-groq/src/audio/tts-provider-options.ts`:
- Around line 22-26: The JSDoc for GroqTTSFormat is misleading; update the
comment above the exported type GroqTTSFormat to accurately reflect supported
formats (either list all supported values 'flac', 'mp3', 'mulaw', 'ogg', 'wav'
or remove the "Only wav is currently supported" claim) so generated docs match
the type declaration; edit the comment near the GroqTTSFormat type to be
accurate and concise.

In `@packages/typescript/ai-groq/src/model-meta.ts`:
- Around line 377-418: ResolveProviderOptions<TModel> is only discriminating
chat models so TModel like 'canopylabs/orpheus-v1-english' resolves to
GroqTextProviderOptions; modify the provider-options resolver type to account
for the new TTS model union by adding a branch that maps GroqTTSModel (exported
GROQ_TTS_MODELS / GroqTTSModel) to GroqTTSProviderOptions (instead of falling
through to GroqTextProviderOptions), i.e. update the conditional type that
currently checks GROQ_CHAT_MODELS to also check (or add) GROQ_TTS_MODELS /
GroqTTSModel so sample_rate and other TTS-specific options are correctly typed.

---

Outside diff comments:
In `@packages/typescript/ai-groq/src/utils/schema-converter.ts`:
- Around line 53-91: The code currently only normalizes object schemas when
result.properties exists, skipping strict normalization for plain { type:
'object' } and nested object/array items that lack a properties key; update the
logic in makeGroqStructuredOutputCompatible so that when result.type ===
'object' but result.properties is absent or empty you still enforce strict
output by setting result.properties = result.properties || {} (or leave empty
object), result.required = [], and result.additionalProperties = false; also
ensure the same normalization is applied to nested schemas passed into the
recursive calls (e.g., where prop.type === 'object' and prop.properties may be
undefined, and for array items via prop.items) so zero-property objects and
nested object schemas without a properties key remain strict.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5e16ea17-fc04-4f5e-abfb-ea476c75ea0e

📥 Commits

Reviewing files that changed from the base of the PR and between 0ea82f6 and 5c99251.

📒 Files selected for processing (9)
  • .changeset/green-colts-kiss.md
  • packages/typescript/ai-groq/src/adapters/tts.ts
  • packages/typescript/ai-groq/src/audio/audio-provider-options.ts
  • packages/typescript/ai-groq/src/audio/tts-provider-options.ts
  • packages/typescript/ai-groq/src/index.ts
  • packages/typescript/ai-groq/src/model-meta.ts
  • packages/typescript/ai-groq/src/tools/function-tool.ts
  • packages/typescript/ai-groq/src/utils/schema-converter.ts
  • packages/typescript/ai-groq/tests/groq-tts.test.ts
💤 Files with no reviewable changes (1)
  • packages/typescript/ai-groq/src/tools/function-tool.ts

Comment thread packages/typescript/ai-groq/src/adapters/tts.ts
Comment thread packages/typescript/ai-groq/src/adapters/tts.ts Outdated
Comment thread packages/ai-groq/src/audio/tts-provider-options.ts
Comment thread packages/ai-groq/src/model-meta.ts
@dhamivibez dhamivibez marked this pull request as draft March 6, 2026 18:26
@dhamivibez dhamivibez marked this pull request as ready for review March 7, 2026 08:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/typescript/ai-groq/src/adapters/tts.ts (1)

46-85: ⚠️ Potential issue | 🟠 Major

Prior review issues remain unaddressed: model consistency, voice/format validation, and isomorphic base64.

Three issues flagged in previous reviews persist:

  1. Model inconsistency (lines 50, 63, 80): Uses caller-supplied options.model instead of this.model. The adapter is constructed with a specific model, but generateSpeech ignores it.

  2. Unchecked type casts (lines 60, 65): TTSOptions allows format: 'opus' | 'aac' | 'pcm' which aren't valid for Groq (GroqTTSFormat supports 'flac' | 'mp3' | 'mulaw' | 'ogg' | 'wav'). The casts bypass compile-time safety, causing API failures at runtime.

  3. Node-only Buffer.from (line 74): The adapter supports browser environments via window.env detection in getGroqApiKeyFromEnv, but Buffer.from() fails in browsers.

Suggested fix
   async generateSpeech(
     options: TTSOptions<GroqTTSProviderOptions>,
   ): Promise<TTSResult> {
     const {
-      model,
       text,
       voice = 'autumn',
       format = 'wav',
       speed,
       modelOptions,
     } = options

     validateAudioInput({ input: text, model })

-    const voiceFormat = format as GroqTTSFormat
+    const validatedFormat = this.validateFormat(format)
+    const validatedVoice = this.validateVoice(voice)

     const request: Groq_SDK.Audio.Speech.SpeechCreateParams = {
-      model,
+      model: this.model,
       input: text,
-      voice: voice as GroqTTSVoice,
-      response_format: voiceFormat,
+      voice: validatedVoice,
+      response_format: validatedFormat,
       speed,
       ...modelOptions,
     }

     const response = await this.client.audio.speech.create(request)

     const arrayBuffer = await response.arrayBuffer()
-    const base64 = Buffer.from(arrayBuffer).toString('base64')
+    const base64 = this.arrayBufferToBase64(arrayBuffer)

-    const contentType = this.getContentType(voiceFormat)
+    const contentType = this.getContentType(validatedFormat)

     return {
       id: generateId(this.name),
-      model,
+      model: this.model,
       audio: base64,
-      format: voiceFormat,
+      format: validatedFormat,
       contentType,
     }
   }
+
+  private validateFormat(format: string): GroqTTSFormat {
+    const validFormats: GroqTTSFormat[] = ['flac', 'mp3', 'mulaw', 'ogg', 'wav']
+    if (validFormats.includes(format as GroqTTSFormat)) {
+      return format as GroqTTSFormat
+    }
+    return 'wav' // fallback to default
+  }
+
+  private validateVoice(voice: string): GroqTTSVoice {
+    const validVoices: GroqTTSVoice[] = [
+      'autumn', 'diana', 'hannah', 'austin', 'daniel', 'troy',
+      'fahad', 'sultan', 'lulwa', 'noura'
+    ]
+    if (validVoices.includes(voice as GroqTTSVoice)) {
+      return voice as GroqTTSVoice
+    }
+    return 'autumn' // fallback to default
+  }
+
+  private arrayBufferToBase64(buffer: ArrayBuffer): string {
+    if (typeof Buffer !== 'undefined') {
+      return Buffer.from(buffer).toString('base64')
+    }
+    const bytes = new Uint8Array(buffer)
+    let binary = ''
+    for (let i = 0; i < bytes.byteLength; i++) {
+      binary += String.fromCharCode(bytes[i])
+    }
+    return btoa(binary)
+  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai-groq/src/adapters/tts.ts` around lines 46 - 85,
generateSpeech currently ignores the adapter's configured model and uses
caller-supplied options.model, unsafely casts voice/format to Groq types, and
uses Node-only Buffer.from for base64 conversion; update generateSpeech to use
this.model (not options.model) when building the request, remove the unchecked
casts for voice/format and instead validate/map options.voice and options.format
against GroqTTSVoice and GroqTTSFormat (throw or normalize when unsupported),
and replace Buffer.from(arrayBuffer).toString('base64') with an isomorphic
conversion helper (e.g., use Buffer when available or a browser-safe
ArrayBuffer→base64 path like Uint8Array→binary string→btoa) so the adapter works
in both Node and browsers; refer to the generateSpeech method, request variable
(Groq_SDK.Audio.Speech.SpeechCreateParams), and getContentType for where to
apply these fixes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/typescript/ai-groq/src/adapters/tts.ts`:
- Around line 46-85: generateSpeech currently ignores the adapter's configured
model and uses caller-supplied options.model, unsafely casts voice/format to
Groq types, and uses Node-only Buffer.from for base64 conversion; update
generateSpeech to use this.model (not options.model) when building the request,
remove the unchecked casts for voice/format and instead validate/map
options.voice and options.format against GroqTTSVoice and GroqTTSFormat (throw
or normalize when unsupported), and replace
Buffer.from(arrayBuffer).toString('base64') with an isomorphic conversion helper
(e.g., use Buffer when available or a browser-safe ArrayBuffer→base64 path like
Uint8Array→binary string→btoa) so the adapter works in both Node and browsers;
refer to the generateSpeech method, request variable
(Groq_SDK.Audio.Speech.SpeechCreateParams), and getContentType for where to
apply these fixes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a0381b5d-b6d4-4520-8faf-a4c1e967da64

📥 Commits

Reviewing files that changed from the base of the PR and between 5c99251 and 28ad865.

📒 Files selected for processing (3)
  • packages/typescript/ai-groq/src/adapters/tts.ts
  • packages/typescript/ai-groq/src/index.ts
  • packages/typescript/ai-groq/src/model-meta.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/typescript/ai-groq/src/index.ts

@dhamivibez

Copy link
Copy Markdown
Contributor Author

@AlemTuzlak check this. The doc has been merged but the tts adapter is yet to be reviewed and merged

required: [],
}) as JSONSchema

// Ensure object schemas always have properties (e.g. z.object({}) may produce { type: 'object' } without properties)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why did you remove this? This introduces a bug with groq and how they parse tools. I specifically added this in to fix that

Comment on lines -53 to -98
@@ -90,12 +87,7 @@ export function makeGroqStructuredOutputCompatible(
}

result.properties = properties
// Groq rejects `required` when there are no properties, even if it's an empty array
if (allPropertyNames.length > 0) {
result.required = allPropertyNames
} else {
delete result.required
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same question from above

@AlemTuzlak AlemTuzlak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

revert the changes to schema converters and function tool

@dhamivibez

Copy link
Copy Markdown
Contributor Author

revert the changes to schema converters and function tool

I've revert the changes

@dhamivibez dhamivibez requested a review from AlemTuzlak March 9, 2026 16:27

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/typescript/ai-groq/src/utils/schema-converter.ts (1)

90-97: ⚠️ Potential issue | 🔴 Critical

Dead code and conflicting logic cause potential API rejection.

Line 96 unconditionally sets result.required = allPropertyNames, which makes the conditional block at lines 91-95 dead code. For schemas with empty properties: {}:

  1. Lines 91-95: conditional correctly deletes required (since allPropertyNames.length === 0)
  2. Line 96: immediately overwrites with required: []

According to the comment on line 90, Groq rejects empty required arrays, so this will break empty object schemas. The commit message states the intent was to "remove required when there are no properties", but line 96 does the opposite.

🐛 Proposed fix: Remove line 96 to preserve the correct conditional logic
     result.properties = properties
     // Groq rejects `required` when there are no properties, even if it's an empty array
     if (allPropertyNames.length > 0) {
       result.required = allPropertyNames
     } else {
       delete result.required
     }
-    result.required = allPropertyNames
     result.additionalProperties = false
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai-groq/src/utils/schema-converter.ts` around lines 90 -
97, The conditional that sets or deletes result.required based on
allPropertyNames is being overridden by an unconditional assignment; remove the
stray unconditional assignment "result.required = allPropertyNames" so the
existing if/else (which deletes result.required when allPropertyNames is empty)
is the only logic that determines result.required in schema-converter.ts (leave
result.additionalProperties = false intact).
♻️ Duplicate comments (1)
packages/typescript/ai-groq/src/utils/schema-converter.ts (1)

53-53: ⚠️ Potential issue | 🟡 Minor

Add safeguard in structuredOutput() to ensure object schemas have properties before conversion.

The guard at line 53 of schema-converter.ts requires result.properties to exist, so bare { type: 'object' } schemas (without a properties key) skip the entire processing block, leaving additionalProperties unset. Per the docstring requirement, additionalProperties must be false for objects.

While function-tool.ts adds this safeguard (lines 24-26: if (inputSchema.type === 'object' && !inputSchema.properties) { inputSchema.properties = {} }), text.ts structuredOutput() does not. Add the same safeguard before calling makeGroqStructuredOutputCompatible() at line 140.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/typescript/ai-groq/src/utils/schema-converter.ts` at line 53,
structuredOutput() may pass a bare { type: 'object' } into
makeGroqStructuredOutputCompatible(), which expects a properties object; add the
same safeguard used in function-tool.ts: before calling
makeGroqStructuredOutputCompatible() inside structuredOutput(), check if
inputSchema.type === 'object' && !inputSchema.properties and if so set
inputSchema.properties = {}; this mirrors the protection in function-tool and
ensures makeGroqStructuredOutputCompatible() can set additionalProperties
correctly for object schemas.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/typescript/ai-groq/src/utils/schema-converter.ts`:
- Around line 90-97: The conditional that sets or deletes result.required based
on allPropertyNames is being overridden by an unconditional assignment; remove
the stray unconditional assignment "result.required = allPropertyNames" so the
existing if/else (which deletes result.required when allPropertyNames is empty)
is the only logic that determines result.required in schema-converter.ts (leave
result.additionalProperties = false intact).

---

Duplicate comments:
In `@packages/typescript/ai-groq/src/utils/schema-converter.ts`:
- Line 53: structuredOutput() may pass a bare { type: 'object' } into
makeGroqStructuredOutputCompatible(), which expects a properties object; add the
same safeguard used in function-tool.ts: before calling
makeGroqStructuredOutputCompatible() inside structuredOutput(), check if
inputSchema.type === 'object' && !inputSchema.properties and if so set
inputSchema.properties = {}; this mirrors the protection in function-tool and
ensures makeGroqStructuredOutputCompatible() can set additionalProperties
correctly for object schemas.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ea13ad49-d0ac-4fb4-bc21-1a2fa8f742ec

📥 Commits

Reviewing files that changed from the base of the PR and between 28ad865 and 8d0d792.

📒 Files selected for processing (1)
  • packages/typescript/ai-groq/src/utils/schema-converter.ts

Adds a Groq TTS adapter (groqSpeech / createGroqSpeech) for the Orpheus
English and Arabic voices, driving Groq's OpenAI-compatible /audio/speech
endpoint via the OpenAI SDK. Includes provider option types, TTS model
metadata, index exports, and unit tests.
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