Skip to content

Conversation

@AnthonyRonning
Copy link
Contributor

@AnthonyRonning AnthonyRonning commented Dec 18, 2025

Summary

Adds Kimi K2 Thinking as a new reasoning model and re-enables the brain toggle feature.

Changes

  • Add kimi-k2-thinking to MODEL_CONFIG (256k context, Pro tier, Reasoning badge)
  • Set Kimi K2 as reasoning_on model (with thinking enabled)
  • Keep DeepSeek R1 as reasoning_off model (without thinking)
  • Re-enable brain toggle button in chat UI (was disabled when V3.1 was removed)

How it works

When users select the Reasoning category, they can use the brain toggle to switch between:

  • Brain ON: Kimi K2 Thinking (deep multi-step reasoning)
  • Brain OFF: DeepSeek R1 (faster, no extended thinking)

Related

Summary by CodeRabbit

  • New Features

    • Added Kimi K2 as a reasoning-enabled model; thinking-mode toggle switches between reasoning and non-reasoning models.
    • Streaming "thinking" content now appears during responses and can be copied via aggregate copy-to-clipboard.
  • UI Improvements

    • Assistant turns group thinking, tool outputs, and search results for clearer conversation flow.
    • Marketing: new Kimi K2 badge and a tighter, more responsive AI models grid layout.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 18, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a new reasoning-capable model entry ("kimi-k2-thinking"), remaps category reasoning to use it, exports ThinkingBlock/props from markdown, and integrates streaming reasoning items (delta/done) and thinking-toggle rendering into the chat UI.

Changes

Cohort / File(s) Summary
Model configuration
frontend/src/components/ModelSelector.tsx
Added kimi-k2-thinking to MODEL_CONFIG (displayName, shortName, badges, requiresPro, tokenLimit). Updated CATEGORY_MODELS so reasoning_onkimi-k2-thinking and reasoning_offdeepseek-r1-0528.
Thinking UI & streaming logic
frontend/src/components/UnifiedChat.tsx
Added internal ReasoningContentItem/ReasoningItem types and extended Message union. Wired streaming events reasoning_text.delta and reasoning_text.done to create/update/complete reasoning items, track serverReasoningId, accumulate reasoning text, render exported ThinkingBlock within assistant turns, and adjust thinking toggle visibility/ARIA/icons.
Markdown / ThinkingBlock export
frontend/src/components/markdown.tsx
Exported ThinkingBlock component and its ThinkingBlockProps interface for external use by UnifiedChat.tsx.
Marketing UI
frontend/src/components/Marketing.tsx
Added Kimi K2 badge (/badge-kimi-logo.png) to AI_MODELS and changed AI models grid from a 5-column desktop layout to a 3-column desktop layout (and 2-column on small screens).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Browser as Browser (UnifiedChat)
  participant Server as Backend (Streaming API)
  participant Model as Model/Reasoner

  Browser->>Server: Send chat request (assistant message, reasoning enabled)
  Server->>Model: Forward request (model id includes reasoning)
  Model-->>Server: Provide serverReasoningId, initial reasoning output
  Server-->>Browser: Event: reasoning_text.delta (serverReasoningId, text chunk)
  Note right of Browser: UnifiedChat creates/updates ReasoningItem\nrenders ThinkingBlock with partial text
  Server-->>Browser: Additional reasoning_text.delta events...
  Server-->>Browser: Event: reasoning_text.done (serverReasoningId)
  Note right of Browser: UnifiedChat finalizes ReasoningItem,\naggregates assistant text and updates UI (toggle/copy)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Review focus:
    • Correctness of streaming reasoning handling (delta ordering, partial deltas, finalization).
    • Sync between serverReasoningId and assistant IDs when multiple assistant streams interleave.
    • Integration and exports of ThinkingBlock with existing markdown rendering and accessibility labels.
  • Files to inspect carefully:
    • frontend/src/components/UnifiedChat.tsx
    • frontend/src/components/ModelSelector.tsx
    • frontend/src/components/markdown.tsx

Possibly related PRs

Poem

🐇 I nudged the keys at break of day,
Kimi hummed thoughts in steady sway.
Deltas hopped in, then rang “done” — hooray!
I nibble bytes and bound away. ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the two main changes in the pull request: adding the Kimi K2 Thinking model and re-enabling the brain toggle feature.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/kimi-k2-thinking-model

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a62605 and e6a20f1.

⛔ Files ignored due to path filters (1)
  • frontend/public/badge-kimi-logo.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • frontend/src/components/Marketing.tsx (2 hunks)
  • frontend/src/components/ModelSelector.tsx (2 hunks)
  • frontend/src/components/UnifiedChat.tsx (13 hunks)
  • frontend/src/components/markdown.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/src/components/markdown.tsx
  • frontend/src/components/Marketing.tsx
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid using any type
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Run just format, just lint, and just build after making TypeScript/React changes to ensure code quality and compilation

Files:

  • frontend/src/components/ModelSelector.tsx
  • frontend/src/components/UnifiedChat.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Greptile Review
  • GitHub Check: build-android
  • GitHub Check: build-macos (universal-apple-darwin)
  • GitHub Check: build-linux
  • GitHub Check: build-ios
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (11)
frontend/src/components/ModelSelector.tsx (2)

71-77: LGTM! Kimi K2 model configuration looks correct.

The model configuration properly defines all required fields including the 256k token limit, Pro tier requirement, and appropriate badges (Pro, Reasoning, New) as described in the PR objectives.


116-117: LGTM! Brain toggle mapping correctly implemented.

The reasoning model mapping properly assigns Kimi K2 Thinking to reasoning_on (with thinking) and DeepSeek R1 to reasoning_off (without thinking), which aligns with the PR objectives.

frontend/src/components/UnifiedChat.tsx (9)

53-53: LGTM! ThinkingBlock import added.

The import correctly uses the path alias and enables reasoning content rendering for the new Kimi K2 model.


106-114: LGTM! Reasoning types properly defined.

The ReasoningItem and ReasoningContentItem types follow the same patterns as existing message types with appropriate status values and content structure.


122-123: LGTM! ReasoningItem added to Message union.

Correctly extends the Message type to include reasoning items as first-class conversation items.


400-439: LGTM! Message grouping correctly refactored.

The grouping logic properly consolidates assistant-related items (reasoning, tool calls, web search, and messages) into unified assistant turns, which improves the UI presentation.


484-498: LGTM! Reasoning items rendered correctly with ThinkingBlock.

The rendering logic properly extracts reasoning text content and passes it to ThinkingBlock with the appropriate isThinking state based on the item's status.


598-708: LGTM! Grouped message rendering correctly implemented.

The rendering logic properly handles both user and assistant groups, with assistant groups displaying all related items (reasoning, tool calls, web search, and messages) in a unified presentation.


710-760: LGTM! Loading indicator correctly handles reasoning state.

The logic properly checks for streaming reasoning items and prevents showing the loading indicator when reasoning content is already being rendered, avoiding duplicate loading states.


1858-2029: LGTM! Reasoning streaming events properly handled.

The streaming implementation correctly handles the full lifecycle of reasoning items: creation via output_item.added, incremental updates via reasoning_text.delta, and finalization via reasoning_text.done. The use of item_id with fallback to serverReasoningId provides good defensive programming.


2771-2803: LGTM! Thinking toggle correctly implemented.

Both toggle button implementations (centered and bottom input) correctly:

  • Show when reasoning models are selected
  • Switch between Kimi K2 Thinking (brain on) and DeepSeek R1 (brain off)
  • Provide clear visual feedback and accessibility labels

This aligns perfectly with the PR objective to re-enable the brain toggle feature.

Also applies to: 3048-3080


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

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 18, 2025

Deploying maple with  Cloudflare Pages  Cloudflare Pages

Latest commit: e6a20f1
Status: ✅  Deploy successful!
Preview URL: https://cab51b7e.maple-ca8.pages.dev
Branch Preview URL: https://feature-kimi-k2-thinking-mod.maple-ca8.pages.dev

View logs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/components/UnifiedChat.tsx (1)

2805-2837: LGTM! Consistent implementation across both toolbars.

The thinking toggle button is correctly duplicated in the bottom toolbar with identical functionality, ensuring consistent behavior across both the centered input (new chat) and bottom toolbar (active chat) views.

While the current duplication is acceptable, consider extracting the thinking toggle into a shared component if more customization is needed in the future. For now, the consistent implementation across both locations ensures a reliable user experience.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 827b17e and b4c5a85.

📒 Files selected for processing (2)
  • frontend/src/components/ModelSelector.tsx (2 hunks)
  • frontend/src/components/UnifiedChat.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid using any type
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Run just format, just lint, and just build after making TypeScript/React changes to ensure code quality and compilation

Files:

  • frontend/src/components/UnifiedChat.tsx
  • frontend/src/components/ModelSelector.tsx
🧬 Code graph analysis (1)
frontend/src/components/UnifiedChat.tsx (2)
frontend/src/components/ModelSelector.tsx (1)
  • CATEGORY_MODELS (113-120)
frontend/src/components/ui/button.tsx (1)
  • Button (62-62)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Greptile Review
  • GitHub Check: build-macos (universal-apple-darwin)
  • GitHub Check: build-ios
  • GitHub Check: build-linux
  • GitHub Check: build-android
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
frontend/src/components/ModelSelector.tsx (2)

71-77: LGTM! Well-configured new model entry.

The Kimi K2 Thinking model configuration is complete and follows the established pattern. The 256k token limit is a nice improvement over DeepSeek R1's 130k, providing users with more context capacity.


116-117: LGTM! Clear model mapping for thinking toggle.

The CATEGORY_MODELS update correctly maps reasoning modes to their respective models with clear comments. The existing useEffect (lines 247-254) ensures the thinking state stays synchronized when the model changes.

frontend/src/components/UnifiedChat.tsx (1)

2528-2560: LGTM! Well-implemented thinking toggle with clear visual feedback.

The thinking toggle button is properly implemented with:

  • Correct conditional rendering for reasoning models only
  • Clean state management that updates both thinkingEnabled and switches between models
  • Clear visual feedback via Brain icon color (purple when active, muted when inactive)
  • Proper accessibility with descriptive aria-labels

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Dec 18, 2025

Greptile Summary

Successfully adds Kimi K2 Thinking as a new reasoning model and re-enables the brain toggle feature. The implementation groups reasoning content, tool calls, and message content into a single assistant box for better UX.

Key Changes:

  • Added kimi-k2-thinking model config with 256k context, Pro tier, and Reasoning badge
  • Brain toggle now switches between Kimi K2 (reasoning_on) and DeepSeek R1 (reasoning_off)
  • Added ReasoningItem type to handle thinking content as proper conversation items
  • Grouped assistant items (reasoning, tools, messages) into single "Maple" box instead of separate bubbles
  • Added Kimi K2 logo to marketing page with updated responsive grid layout (2/3 columns)
  • Exported ThinkingBlock component for reuse across the app

Confidence Score: 4/5

  • This PR is safe to merge with minor issues previously identified in review comments
  • The implementation is well-structured with proper type safety and state synchronization. The brain toggle logic correctly switches between models and syncs state via useEffect. The grouping of assistant items provides better UX. However, there are two minor issues already noted in previous review threads: missing newlines between reasoning and content sections, and the copy button not including reasoning content despite the PR description mentioning it should be copyable.
  • frontend/src/components/UnifiedChat.tsx has minor formatting and copy functionality issues already noted in previous review comments

Important Files Changed

Filename Overview
frontend/src/components/ModelSelector.tsx Added Kimi K2 Thinking model config and updated reasoning category mappings
frontend/src/components/UnifiedChat.tsx Re-enabled brain toggle, added reasoning item support, grouped assistant items into single box
frontend/src/components/Marketing.tsx Added Kimi K2 to AI models showcase, updated grid layout to 2/3 columns

Sequence Diagram

sequenceDiagram
    participant User
    participant UnifiedChat
    participant ModelSelector
    participant API
    participant MessageList

    User->>UnifiedChat: Select "Reasoning" category
    UnifiedChat->>ModelSelector: Load reasoning_on model (Kimi K2)
    ModelSelector-->>UnifiedChat: Model set to kimi-k2-thinking
    
    User->>UnifiedChat: Click brain toggle button
    UnifiedChat->>UnifiedChat: Toggle thinkingEnabled state
    
    alt Brain ON (thinking enabled)
        UnifiedChat->>ModelSelector: Set model to reasoning_on
        ModelSelector-->>UnifiedChat: Switch to kimi-k2-thinking
        UnifiedChat-->>User: Brain icon filled
    else Brain OFF (thinking disabled)
        UnifiedChat->>ModelSelector: Set model to reasoning_off
        ModelSelector-->>UnifiedChat: Switch to deepseek-r1-0528
        UnifiedChat-->>User: Brain icon outlined
    end
    
    User->>UnifiedChat: Send message
    UnifiedChat->>API: Stream request with selected model
    
    alt Kimi K2 (reasoning_on)
        API-->>UnifiedChat: response.output_item.added (type: reasoning)
        UnifiedChat->>MessageList: Create ReasoningItem
        API-->>UnifiedChat: response.reasoning_text.delta
        UnifiedChat->>MessageList: Update reasoning content (streaming)
        MessageList-->>User: Show ThinkingBlock (collapsible)
        API-->>UnifiedChat: response.reasoning_text.done
        UnifiedChat->>MessageList: Mark reasoning completed
        API-->>UnifiedChat: response.output_text.delta
        UnifiedChat->>MessageList: Stream assistant message
        MessageList-->>User: Show reasoning + message in Maple box
    else DeepSeek R1 (reasoning_off)
        API-->>UnifiedChat: response.output_text.delta
        UnifiedChat->>MessageList: Stream assistant message directly
        MessageList-->>User: Show message in Maple box (no reasoning)
    end
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/components/UnifiedChat.tsx (1)

2593-2625: LGTM! Brain toggle correctly re-enabled with proper model switching.

The thinking toggle implementation correctly:

  • Shows only when reasoning models are selected (kimi-k2-thinking or deepseek-r1-0528)
  • Switches between Kimi K2 (with thinking) and DeepSeek R1 (without thinking) per the PR objectives
  • Provides clear visual feedback with icon color changes (purple when enabled, muted when disabled)
  • Includes accessible aria-labels that describe the toggle action

The toggle appears in both the centered input view (lines 2593-2625) and bottom input view (lines 2870-2902), which is appropriate for the different layouts.

💡 Optional: Consider extracting duplicate toggle logic to reduce code duplication

The toggle button logic is duplicated between the centered and bottom input views. While acceptable given the different rendering contexts, you could optionally extract it to a memoized component or helper function:

const ThinkingToggleButton = memo(({ className }: { className?: string }) => {
  const localState = useLocalState();
  
  if (
    localState.model !== CATEGORY_MODELS.reasoning_on &&
    localState.model !== CATEGORY_MODELS.reasoning_off
  ) {
    return null;
  }

  return (
    <Button
      type="button"
      variant="ghost"
      size="sm"
      className={`h-8 w-8 p-0 ${className || ''}`}
      onClick={() => {
        const newThinkingEnabled = !localState.thinkingEnabled;
        localState.setThinkingEnabled(newThinkingEnabled);
        localState.setModel(
          newThinkingEnabled
            ? CATEGORY_MODELS.reasoning_on
            : CATEGORY_MODELS.reasoning_off
        );
      }}
      aria-label={
        localState.thinkingEnabled
          ? "Disable thinking mode"
          : "Enable thinking mode"
      }
    >
      <Brain
        className={`h-4 w-4 ${
          localState.thinkingEnabled
            ? "text-purple-500"
            : "text-muted-foreground"
        }`}
      />
    </Button>
  );
});

This is a low-priority refactor and can be deferred if preferred.

Also applies to: 2870-2902

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b4c5a85 and aba79d4.

📒 Files selected for processing (1)
  • frontend/src/components/UnifiedChat.tsx (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid using any type
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Run just format, just lint, and just build after making TypeScript/React changes to ensure code quality and compilation

Files:

  • frontend/src/components/UnifiedChat.tsx
🧬 Code graph analysis (1)
frontend/src/components/UnifiedChat.tsx (1)
frontend/src/components/ModelSelector.tsx (1)
  • CATEGORY_MODELS (113-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-ios
  • GitHub Check: Greptile Review
  • GitHub Check: build-android
  • GitHub Check: build-linux
  • GitHub Check: build-macos (universal-apple-darwin)
🔇 Additional comments (2)
frontend/src/components/UnifiedChat.tsx (2)

1655-1655: LGTM! Reasoning streaming integration is well-implemented.

The reasoning accumulation logic correctly handles the streaming flow:

  • Incremental deltas are accumulated in accumulatedReasoning
  • During streaming, reasoning is displayed with an opening <think> tag (no closing tag to indicate in-progress state)
  • On reasoning_done, the reasoning is finalized with a closing </think> tag and appended to any existing content
  • Message deduplication is properly handled via mergeMessagesById

This implementation aligns with the PR objective to add Kimi K2 Thinking model support with extended reasoning visualization.

Also applies to: 1806-1864


1878-1882: LGTM! Content display properly integrates reasoning.

The display concatenation logic correctly prepends accumulated reasoning to the content when both exist. The \n\n spacing between the closing </think> tag and content provides visual separation in the markdown rendering, which enhances readability.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/components/UnifiedChat.tsx (1)

2650-2682: Consider extracting the thinking toggle button to a reusable component.

This toggle button logic is duplicated in the compact/bottom input section (lines 2927-2959). While acceptable for now given the "Chill" review mode, extracting to a shared component would improve maintainability.

🔎 Example extraction:
// Could be defined near other button components
function ThinkingToggleButton() {
  const localState = useLocalState();
  
  if (localState.model !== CATEGORY_MODELS.reasoning_on && 
      localState.model !== CATEGORY_MODELS.reasoning_off) {
    return null;
  }
  
  return (
    <Button
      type="button"
      variant="ghost"
      size="sm"
      className="h-8 w-8 p-0"
      onClick={() => {
        const newThinkingEnabled = !localState.thinkingEnabled;
        localState.setThinkingEnabled(newThinkingEnabled);
        localState.setModel(
          newThinkingEnabled
            ? CATEGORY_MODELS.reasoning_on
            : CATEGORY_MODELS.reasoning_off
        );
      }}
      aria-label={
        localState.thinkingEnabled ? "Disable thinking mode" : "Enable thinking mode"
      }
    >
      <Brain
        className={`h-4 w-4 ${
          localState.thinkingEnabled ? "text-purple-500" : "text-muted-foreground"
        }`}
      />
    </Button>
  );
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aba79d4 and 0596852.

📒 Files selected for processing (2)
  • frontend/src/components/UnifiedChat.tsx (9 hunks)
  • frontend/src/components/markdown.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid using any type
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Run just format, just lint, and just build after making TypeScript/React changes to ensure code quality and compilation

Files:

  • frontend/src/components/markdown.tsx
  • frontend/src/components/UnifiedChat.tsx
🧬 Code graph analysis (1)
frontend/src/components/UnifiedChat.tsx (2)
frontend/src/components/markdown.tsx (1)
  • ThinkingBlock (31-119)
frontend/src/components/ModelSelector.tsx (1)
  • CATEGORY_MODELS (113-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Greptile Review
  • GitHub Check: build-linux
  • GitHub Check: build-macos (universal-apple-darwin)
  • GitHub Check: build-ios
  • GitHub Check: build-android
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (10)
frontend/src/components/markdown.tsx (1)

25-31: LGTM!

Clean export of ThinkingBlockProps interface and ThinkingBlock component to enable reuse in UnifiedChat.tsx for rendering reasoning items.

frontend/src/components/UnifiedChat.tsx (9)

53-53: LGTM!

Correct import using path alias as per coding guidelines.


106-123: LGTM!

The ReasoningItem type correctly models reasoning content with appropriate status values that align with the ThinkingBlock component's isThinking prop logic. The types are kept internal (non-exported) which is appropriate for this use case.


473-494: LGTM!

Correct integration of ThinkingBlock for reasoning items. The status-based isThinking detection properly reflects the streaming state, and the text extraction handles the content array structure appropriately.


1686-1690: LGTM!

The new tracking variables follow the established pattern for serverAssistantId and accumulatedContent, maintaining consistency in the streaming response processing logic.


1737-1754: LGTM!

The reasoning item creation handler follows the established pattern for other output item types, correctly initializing the item with status: "in_progress" and tracking the ID for subsequent delta/done events.


1859-1884: LGTM!

The reasoning delta handler correctly accumulates text and updates the reasoning item. The fallback from event.item_id to serverReasoningId provides resilience against missing event properties.


1885-1908: LGTM!

The done handler correctly finalizes the reasoning item, using the event's text property as the authoritative final content when available, and properly transitioning status to "completed".


1937-1970: LGTM!

Good refactoring to make the response.output_item.done handler generic, supporting any item type (reasoning, message, etc.) while maintaining backward compatibility with the serverAssistantId fallback.


2927-2959: LGTM!

The thinking toggle button in the compact input correctly mirrors the centered input behavior. The duplication concern was noted above.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/components/UnifiedChat.tsx (1)

3048-3080: Consider extracting the thinking toggle to a shared component.

This toggle button is duplicated from lines 2771-2803. While both work correctly, extracting to a shared component (e.g., ThinkingToggleButton) would reduce duplication and prevent future drift if the logic needs updating.

🔎 Example extraction:
// Could be defined near the top of the file or in a separate file
function ThinkingToggleButton() {
  const localState = useLocalState();
  
  if (localState.model !== CATEGORY_MODELS.reasoning_on && 
      localState.model !== CATEGORY_MODELS.reasoning_off) {
    return null;
  }
  
  return (
    <Button
      type="button"
      variant="ghost"
      size="sm"
      className="h-8 w-8 p-0"
      onClick={() => {
        const newThinkingEnabled = !localState.thinkingEnabled;
        localState.setThinkingEnabled(newThinkingEnabled);
        localState.setModel(
          newThinkingEnabled
            ? CATEGORY_MODELS.reasoning_on
            : CATEGORY_MODELS.reasoning_off
        );
      }}
      aria-label={
        localState.thinkingEnabled
          ? "Disable thinking mode"
          : "Enable thinking mode"
      }
    >
      <Brain
        className={`h-4 w-4 ${
          localState.thinkingEnabled
            ? "text-purple-500"
            : "text-muted-foreground"
        }`}
      />
    </Button>
  );
}

Then replace both instances with <ThinkingToggleButton />.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0596852 and 03b87cf.

📒 Files selected for processing (1)
  • frontend/src/components/UnifiedChat.tsx (13 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid using any type
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Run just format, just lint, and just build after making TypeScript/React changes to ensure code quality and compilation

Files:

  • frontend/src/components/UnifiedChat.tsx
🧬 Code graph analysis (1)
frontend/src/components/UnifiedChat.tsx (2)
frontend/src/components/markdown.tsx (2)
  • ThinkingBlock (31-119)
  • Markdown (676-705)
frontend/src/components/ModelSelector.tsx (1)
  • CATEGORY_MODELS (113-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Greptile Review
  • GitHub Check: build-ios
  • GitHub Check: build-android
  • GitHub Check: build-macos (universal-apple-darwin)
  • GitHub Check: build-linux
🔇 Additional comments (11)
frontend/src/components/UnifiedChat.tsx (11)

53-53: LGTM!

The ThinkingBlock import is correctly added using the path alias convention.


106-124: LGTM!

The new ReasoningItem type is well-structured with proper discriminant (type: "reasoning") for the union type. The content array structure mirrors existing patterns and allows for future extensibility.


364-368: LGTM!

The MessageGroup type cleanly separates user and assistant turns, with the assistant turn properly containing an array of related items (reasoning, tool calls, messages).


400-439: LGTM!

The grouping logic correctly separates user messages from assistant-related items (reasoning, tool calls, messages). The use of useMemo optimizes re-computation, and the flush-then-push pattern ensures proper ordering.


484-498: LGTM!

The reasoning item rendering correctly extracts text content and determines the isThinking state based on both "in_progress" and "streaming" statuses. The ThinkingBlock component will display the animated "Thinking for X seconds" indicator while streaming and "Thought for X seconds" when complete.


570-583: Reasoning text is excluded from copy.

The copy button only captures assistant message content, not the reasoning/thinking text. This seems intentional for typical use cases. If users should be able to copy reasoning content too, consider including it or providing a separate option.


729-741: LGTM!

The loading indicator logic correctly accounts for streaming reasoning items, preventing duplicate loading indicators when ThinkingBlock is already displaying its own "Thinking..." animation.


1858-1875: LGTM!

The reasoning item is correctly created when response.output_item.added fires with type: "reasoning". The initial state with empty content and "in_progress" status matches the pattern used for assistant messages.


1980-2029: LGTM!

The delta and done handlers for reasoning text follow the established pattern for streaming content:

  • Delta accumulates text and sets status to "streaming"
  • Done finalizes with the complete text (from event or accumulated) and sets status to "completed"
  • Both handlers correctly fall back to serverReasoningId when item_id is not in the event

2058-2077: LGTM!

The response.output_item.done handler is correctly generalized to handle completion for any item type (reasoning, message, etc.), updating the status to "completed" and the lastSeenItemId for polling.


2771-2803: LGTM!

The thinking toggle correctly:

  • Shows only when a reasoning model is selected
  • Toggles between Kimi K2 (with thinking) and DeepSeek R1 (without thinking)
  • Updates both thinkingEnabled state and the active model
  • Uses appropriate visual feedback (purple when enabled)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
frontend/src/components/Marketing.tsx (1)

436-436: Consider verifying mobile layout on small screens.

The grid layout change from 5-column to 3-column desktop creates a balanced 2×3 grid with 6 models. However, the mobile layout now displays 2 columns instead of 1, which may be tight on smaller devices (320px-375px width) given the badge images and labels.

Consider testing the layout on small mobile devices (iPhone SE, small Android phones) to ensure the badge images and labels render comfortably in the 2-column layout.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03b87cf and 1a62605.

⛔ Files ignored due to path filters (1)
  • frontend/public/badge-kimi-logo.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • frontend/src/components/Marketing.tsx (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React files
Use 2-space indentation, double quotes, and enforce 100-character line limit in TypeScript/React code
Maintain strict TypeScript and avoid using any type
Use PascalCase for component names and camelCase for variables and function names
Use functional components with React hooks instead of class components
Use React context for global state management and TanStack Query for server state management
Run just format, just lint, and just build after making TypeScript/React changes to ensure code quality and compilation

Files:

  • frontend/src/components/Marketing.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build-ios
  • GitHub Check: build-android
  • GitHub Check: build-macos (universal-apple-darwin)
  • GitHub Check: build-linux
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
frontend/src/components/Marketing.tsx (1)

30-34: LGTM! Image asset verified.

The Kimi K2 model entry is correctly structured and consistent with other entries in the AI_MODELS array. The badge image file exists at ./frontend/public/badge-kimi-logo.png. Code follows all formatting guidelines with proper 2-space indentation and double quotes.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

AnthonyRonning and others added 6 commits December 19, 2025 14:43
- Add kimi-k2-thinking to MODEL_CONFIG (256k context, Pro tier)
- Set Kimi K2 as reasoning_on model (with thinking)
- Keep DeepSeek R1 as reasoning_off model (without thinking)
- Re-enable brain toggle button in chat UI

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Handle response.reasoning_text.delta and response.reasoning_text.done events
for models like Kimi K2 that stream reasoning separately from content.
Reasoning is wrapped in <think> tags to reuse existing ThinkingBlock rendering.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Export ThinkingBlock from markdown.tsx for reuse
- Add ReasoningItem type to Message union for type: reasoning items
- Add rendering for reasoning items in MessageList using ThinkingBlock
- Handle response.output_item.added for reasoning items during streaming
- Update reasoning_text.delta/done handlers to update reasoning items
- Remove inline <think> tag wrapping from output_text.delta

Reasoning items are now proper conversation items that can be fetched
via the items API and are handled with the same dedup/paging logic
as messages and tool calls.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Update handler to use item.id from the event to mark the correct item
as completed, rather than only handling serverAssistantId. This properly
supports the separate reasoning and message items in the streaming flow.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Refactor MessageList to group consecutive assistant items (reasoning,
tool calls, message content) into a single 'Maple' box instead of
rendering them separately. This provides a cleaner UI similar to how
DeepSeek's <think> tags rendered inline.

Changes:
- Add MessageGroup type for user/assistant turn grouping
- Group messages using useMemo before rendering
- Render all assistant items within one Maple wrapper
- Fix loading indicator to not show duplicate box during tool use
- Export ThinkingBlock from markdown.tsx for reuse

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Add Kimi logo (badge-kimi-logo.png)
- Add Kimi K2 to AI_MODELS array
- Change grid to 3 columns for balanced 2-row layout

Closes #345

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@AnthonyRonning AnthonyRonning force-pushed the feature/kimi-k2-thinking-model branch from 1a62605 to e6a20f1 Compare December 19, 2025 20:43
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