#1658·corsair

[BUG] Gemini `generateContent` drops subsequent text/reasoning parts and unconditionally strips markdown code blocks

Author: vanssh012Created Sep 7, 2026Updated Sep 13, 2026

Package

@corsair-dev/gemini (packages/gemini/endpoints/content.ts & packages/gemini/endpoints/text-utils.ts)

Summary

In the Gemini plugin, generateContent extracts the candidate text by finding only the first part matching typeof part.text === 'string', and passes it through stripMarkdownFences().

This causes two major issues for AI/ML workflows:

  1. Truncation with Modern Models / Reasoning: Gemini 2.0 Flash Thinking, Gemini 2.5, and multi-part responses return multiple content parts (e.g. reasoning/thought parts followed by text parts, or split stream chunks). Using Array.prototype.find() only grabs the first part (often the reasoning or first chunk) and completely discards all subsequent text parts.
  2. Destructive Output Mutation: stripMarkdownFences() automatically detects and strips markdown code fences (```). If a user specifically prompts the model to return a markdown document or code snippet wrapped in a code fence, the returned response text is silently mutated and stripped.

Location

  • File: packages/gemini/endpoints/content.ts (Lines 80–93)
  • File: packages/gemini/endpoints/text-utils.ts (Lines 6–9)

Steps to Reproduce

Call gemini.content.generateContent with a model returning multi-part output or thoughts (e.g. gemini-2.0-flash-thinking-exp or multi-part content):

typescript
await corsair.gemini.content.generateContent({
    model: 'gemini-2.5-flash',
    contents: [{ role: 'user', parts: [{ text: 'Write a typescript function wrapped in a markdown code block' }] }]
});

Inspect the returned .text property:

  • Only the first part is returned if multiple parts exist.
  • The markdown code block syntax (typescript ... ) is stripped even though it was explicitly requested.

Expected Behavior

All text parts belonging to the candidate should be concatenated together (ignoring or properly distinguishing thought parts if needed). The convenience .text field should preserve the exact string returned by the model without modifying markdown formatting, or make fence stripping an explicit opt-in parameter.

Suggested Fix

Update packages/gemini/endpoints/content.ts to concatenate all text parts from the primary candidate instead of calling .find(). Remove the automatic stripMarkdownFences() transform from generateContent or make it optional so raw model completions are not altered.