Skip to content

AI Explain Feature: Anonymous access, streaming response #170

Description

@DevanshuNEU

AI Explain Feature: Anonymous Access with Streaming Response

Parent Epic: #166
Depends on: #169 (Search Results Component)

The Feature

When a user clicks "Explain This" on any search result, they get an AI-generated explanation of the code. This works without login. This is a key differentiator - competitors gate this behind signup.

User Flow

  1. User sees search result
  2. Clicks "Explain This" button
  3. Button transforms to loading state
  4. AI explanation streams in character-by-character
  5. Full explanation visible, can be copied or dismissed

UI Specification

Button States

[Explain This]          <- Idle
[Explaining...]         <- Loading (spinner)
[Close Explanation]     <- Showing explanation

Explanation Panel

Appears below the code snippet, within the same card:

┌──────────────────────────────────────────────────────────────────┐
│  flask/src/flask/app.py                               98% match  │
│  ───────────────────────────────────────────────────────────────│
│  [code snippet...]                                               │
│  ───────────────────────────────────────────────────────────────│
│                                                                  │
│  Explanation                                          [Copy] [X] │
│  ─────────────────────────────────────────────────────────────── │
│                                                                  │
│  This decorator registers a function to run before each         │
│  incoming request. Common use cases include:                     │
│                                                                  │
│  - Opening database connections                                  │
│  - Loading the current user from session                        │
│  - Setting up request-specific context                          │
│                                                                  │
│  The decorated function receives no arguments. If it returns    │
│  a value, that value is used as the response and the actual    │
│  view function is never called.                                  │
│                                                                  │
│  ───────────────────────────────────────────────────────────────│
│  [Copy Code]  [View Full File]  [GitHub]                        │
└──────────────────────────────────────────────────────────────────┘

Streaming Response

The explanation should stream in character-by-character, like ChatGPT. This creates anticipation and feels more natural than a sudden wall of text.

// Typewriter effect
const TypewriterText = ({ text, speed = 20 }) => {
  const [displayed, setDisplayed] = useState('');
  
  useEffect(() => {
    let i = 0;
    const interval = setInterval(() => {
      if (i < text.length) {
        setDisplayed(prev => prev + text[i]);
        i++;
      } else {
        clearInterval(interval);
      }
    }, speed);
    return () => clearInterval(interval);
  }, [text]);
  
  return <span>{displayed}<span className="cursor">|</span></span>;
};

If the backend supports true streaming (SSE or WebSocket), use that instead of simulated typewriter.

Backend Integration

Endpoint

POST /api/v2/explain
{
  "repo_id": "flask",
  "file_path": "src/flask/app.py",
  "line_start": 847,
  "line_end": 858,
  "code_snippet": "...",
  "query_context": "authentication middleware patterns"
}

Response (Streaming)

data: {"chunk": "This decorator "}
data: {"chunk": "registers a function "}
data: {"chunk": "to run before each..."}
data: {"done": true}

Anonymous Access

This endpoint must work without authentication. Rate limit by IP/session to prevent abuse:

  • 10 explanations per hour for anonymous users
  • Show remaining count subtly

Animation Specifications

Button Click -> Explanation Panel

1. Button text changes to "Explaining..."
2. Sparkle icon starts rotating
3. Card expands smoothly (height animation)
4. Explanation header fades in
5. Text streams in character by character
6. When done, cursor blinks then disappears

Collapse Explanation

1. Click X or "Close Explanation"
2. Text fades out quickly (150ms)
3. Card height collapses (300ms)
4. Button returns to "Explain This"

Rate Limiting UI

When approaching limit:

[Explain This]  (7 remaining)

When limit reached:

[Sign up for unlimited explains]

This is how we convert anonymous users - give them value, then ask for signup when they want more.

Implementation Tasks

  • Create components/search/ExplanationPanel.tsx
  • Create components/ui/TypewriterText.tsx
  • Create hooks/useExplainCode.ts - manages API call and streaming
  • Modify SearchResult.tsx to include expandable explanation
  • Create backend endpoint POST /api/v2/explain
  • Implement rate limiting by session/IP
  • Add "remaining" counter to UI
  • Add copy explanation functionality

Acceptance Criteria

  • Explain works without login
  • Explanation streams in (not instant)
  • Loading state is clear
  • Can collapse/dismiss explanation
  • Copy explanation works
  • Rate limit enforced and communicated
  • Graceful degradation if AI unavailable
  • Mobile: explanation readable, doesn't break layout

Technical Notes

Use OpenAI or Claude API for explanations. Prompt should include:

  • The code snippet
  • The search query (for context)
  • The file path (for additional context)

Keep explanations concise - 3-5 sentences max. Developers don't want essays.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions