Skip to content

Conversation

@yfge
Copy link
Contributor

@yfge yfge commented Sep 6, 2025

Summary

  • Replaced all any types with proper TypeScript definitions across the codebase
  • Added proper interface definitions for React components and SSE data handling
  • Improved type safety by using unknown instead of any where appropriate
  • Removed unused ESLint disable directives

Changes Made

  • ContentRender.tsx: Added CodeProps interface for markdown code components
  • useScrollToBottom.ts: Changed any[] to unknown[] for dependencies
  • Playground.tsx: Created VariableValue and SSEData types for proper typing
  • useMarkdownInfo.ts: Improved error handling with proper type guards
  • useSSE.ts: Updated all generic defaults from any to unknown
  • plugins_bac: Updated Record types to use unknown instead of any

Test plan

  • All lint checks pass without warnings
  • TypeScript compilation successful
  • Code formatting applied correctly
  • Pre-commit hooks pass successfully

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Playground now supports additional options: SSE URL, session ID, and an option to disable typing.
    • Expanded live-connection statuses (disconnected, connecting, connected) for clearer feedback during streaming.
  • Bug Fixes

    • More robust error handling in markdown info loading to avoid missing or misleading messages.
  • Refactor

    • Broad type-safety improvements across code rendering, custom plugins, scrolling behavior, SSE handling, and Playground variables for more predictable behavior without changing functionality.

- Define CodeProps interface for markdown code components
- Replace any[] with unknown[] for better type safety
- Create VariableValue and SSEData types for proper typing
- Use proper error handling with type guards instead of any
- Remove unused eslint-disable directives
- Ensure all components have proper TypeScript definitions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Copilot AI review requested due to automatic review settings September 6, 2025 07:49
@coderabbitai
Copy link

coderabbitai bot commented Sep 6, 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.

Warning

Rate limit exceeded

@yfge has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 41 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 4c008b2 and 0bb274b.

📒 Files selected for processing (3)
  • src/components/ContentRender/ContentRender.tsx (2 hunks)
  • src/components/ContentRender/plugins/CustomVariable.tsx (1 hunks)
  • src/components/Playground/Playground.tsx (4 hunks)

Walkthrough

Type-safety refinements across components and hooks: narrowed types (any→unknown/union), added local interfaces, and adjusted error handling. Public API changes include new Playground props, narrowed variable types, stricter generics for useSSE, expanded connection states, and typed code renderer props. No functional control-flow changes except additional SSE connection states.

Changes

Cohort / File(s) Summary
Content rendering typing
src/components/ContentRender/ContentRender.tsx
Added local CodeProps interface; typed code renderer signature; removed as any cast; runtime behavior unchanged.
Remark plugin typings
src/components/ContentRender/plugins_bac/remark-custom-button.ts, src/components/ContentRender/plugins_bac/remark-custom-variable.ts
hProperties typed from Record<string, any> to Record<string, unknown>; removed no-console disable comment; no runtime changes.
Markdown scrolling hook
src/components/MarkdownFlow/useScrollToBottom.ts
Hook dependency type changed from any[] to unknown[]; signature updated; behavior unchanged.
Playground typing and props
src/components/Playground/Playground.tsx
Introduced VariableValue and SSEData types; defaultVariables narrowed; added sseUrl, sessionId, disableTyping props; SSEParams.variables narrowed; useSSE now generic with SSEData.
Markdown info error handling
src/components/Playground/useMarkdownInfo.ts
Catch variable typed as unknown; safe error message extraction using instanceof Error; control flow unchanged.
SSE hook API and states
src/components/sse/useSSE.ts
Default generics any→unknown; onFinish typed with unknown; ConnectionState expanded (disconnected/connecting/connected/error/closed); message parsing typed; public interfaces updated.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as UI Component
  participant H as useSSE Hook
  participant ES as EventSource (SSE)

  Note over C,H: Initialization
  C->>H: useSSE<T=unknown>(url, options)
  H-->>C: {state: "connecting", data, error}

  Note over H,ES: Connect
  H->>ES: new EventSource(url)
  ES-->>H: open
  H-->>C: state = "connected"

  rect rgba(230,245,255,0.5)
    Note over ES,H: Data events
    ES-->>H: message (data: string)
    H->>H: parse/update data<T>
    H-->>C: data update
  end

  alt Error
    ES--x H: error
    H-->>C: state = "error", error set
  else Closed
    ES-->>H: close
    H-->>C: state = "closed"
    opt onFinish
      H->>C: options.onFinish(finalData: unknown, index)
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

A rabbit taps keys with careful delight,
Swapping any for unknown in the night.
States now connect, then close with grace,
Playground props neatly fall in place.
Type-safe trails where packets stream—
Hop, hop, the code aligns with the dream. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @yfge, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the codebase's robustness and maintainability by migrating from loose 'any' types to strict TypeScript definitions. The changes aim to prevent common type-related bugs, improve code predictability, and provide clearer contracts for data structures and component props. This refactoring makes the application more resilient and easier to understand for future development.

Highlights

  • Type Safety Enhancement: Replaced all 'any' types with proper TypeScript definitions across the codebase to improve type safety and reduce potential runtime errors.
  • Interface and Type Definitions: Added specific interface definitions for React components (e.g., CodeProps) and Server-Sent Events (SSE) data handling (e.g., VariableValue, SSEData).
  • Improved Error Handling: Switched from 'any' to 'unknown' in various contexts, particularly for error handling in catch blocks and generic types, promoting safer type assertions.
  • Code Clean-up: Removed unused ESLint disable directives, contributing to a cleaner and more maintainable codebase.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

Copilot AI left a comment

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 improves TypeScript type safety by replacing any types with proper TypeScript definitions throughout the codebase. The changes focus on better type constraints and error handling while maintaining functional behavior.

  • Replaced generic any defaults with unknown for safer type handling
  • Added proper interface definitions for React components and SSE data structures
  • Improved error handling with type guards and proper type checking

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
useSSE.ts Updated generic defaults from any to unknown and improved SSE data typing
useMarkdownInfo.ts Enhanced error handling with proper type guards instead of any
Playground.tsx Added proper type definitions for variables and SSE data structures
useScrollToBottom.ts Changed dependency array type from any[] to unknown[]
remark-custom-button.ts Updated Record type to use unknown instead of any
ContentRender.tsx Added proper CodeProps interface for markdown code components

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request does a great job of improving type safety by replacing any with more specific types like unknown and custom interfaces. The changes make the code more robust and easier to maintain. I've found a few areas where the new typings could be further improved for better correctness and safety. Specifically, there's an issue with an unsafe type assertion in the useSSE hook and a resulting incorrect type usage in Playground.tsx. I've also suggested a small improvement to the new CodeProps interface for completeness. Overall, these are excellent changes towards a more strongly-typed codebase.

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: 1

Caution

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

⚠️ Outside diff range comments (8)
src/components/Playground/useMarkdownInfo.ts (1)

22-41: Prevent stale updates on rapid content changes (abort + sequencing).

Without aborting in-flight requests, older responses can override newer state. Add AbortController and ignore out-of-date responses.

-import { useState, useEffect } from "react";
+import { useState, useEffect, useRef } from "react";
@@
 const useMarkdownInfo = (content: string) => {
   const [data, setData] = useState<MarkdownInfoData | null>(null);
   const [loading, setLoading] = useState<boolean>(true);
   const [error, setError] = useState<string | null>(null);
+  const requestSeq = useRef(0);
 
   useEffect(() => {
-    const fetchMarkdownInfo = async () => {
+    const ac = new AbortController();
+    const fetchMarkdownInfo = async () => {
       try {
         setLoading(true);
+        setError(null);
+        setData(null);
+        const seq = ++requestSeq.current;
@@
-        const response = await fetch(
+        const response = await fetch(
           "https://play.dev.pillowai.cn/api/v1/playground/markdownflow_info",
           {
             method: "POST",
             headers: {
               "Content-Type": "application/json",
             },
             body: JSON.stringify({ content }),
             // Next.js fetch caching options
             cache: "no-store",
             // Or use next: { revalidate: 0 } to disable cache
-          }
+            signal: ac.signal,
+          }
         );
@@
-        const result: MarkdownInfoResponse = await response.json();
+        const result: MarkdownInfoResponse = await response.json();
+        // Ignore if a newer request has started
+        if (requestSeq.current !== seq) return;
@@
-      } catch (err: unknown) {
+      } catch (err: unknown) {
+        // Swallow aborts
+        if (err instanceof DOMException && err.name === "AbortError") return;
         const errorMessage =
           err instanceof Error ? err.message : "Network error";
         setError(errorMessage);
       } finally {
         setLoading(false);
       }
     };
 
     if (content) {
       fetchMarkdownInfo();
     }
+    return () => {
+      ac.abort();
+    };
   }, [content]);

Also applies to: 57-65

src/components/sse/useSSE.ts (3)

85-96: Normalize HeadersInit correctly (handles Headers, array tuples, objects).

Object.entries fails for Headers or string[][]. Normalize before merging.

-        headers: {
+        headers: {
           Accept: "text/event-stream",
           "Content-Type": "application/json",
           "Cache-Control": "no-cache",
-          ...Object.entries(options.headers || {}).reduce(
-            (acc, [key, value]) => {
-              acc[key] = String(value);
-              return acc;
-            },
-            {} as Record<string, string>
-          ),
+          ...normalizeHeaders(options.headers),
         },

Add this helper above connect (outside this hunk):

function normalizeHeaders(input?: HeadersInit): Record<string, string> {
  if (!input) return {};
  if (input instanceof Headers) {
    const out: Record<string, string> = {};
    input.forEach((v, k) => (out[k] = String(v)));
    return out;
  }
  if (Array.isArray(input)) {
    return Object.fromEntries(input.map(([k, v]) => [k, String(v)]));
  }
  return Object.fromEntries(
    Object.entries(input).map(([k, v]) => [k, String(v as string)])
  );
}

100-107: Avoid stale handler closures: keep onStart/onFinish in refs.

Functions are dropped by JSON.stringify, so updates won’t re-create connect; capture the latest handlers in refs.

-            options.onStart?.(newIndex);
+            onStartRef.current?.(newIndex);
@@
-              options.onFinish?.(finalDataRef.current, newIndex);
+              onFinishRef.current?.(finalDataRef.current as unknown as T, newIndex);

Also add (outside this hunk, e.g., near other refs):

const onStartRef = useRef<((index: number) => void) | undefined>(options.onStart);
const onFinishRef = useRef<((finalData: T, index: number) => void) | undefined>(
  (options as UseSSEOptions<T>).onFinish
);
useEffect(() => void (onStartRef.current = options.onStart), [options.onStart]);
useEffect(() => void (onFinishRef.current = (options as UseSSEOptions<T>).onFinish), [options.onFinish]);

Also applies to: 111-113


148-149: JSON.stringify(options) in deps is brittle and drops function changes.

This can miss updates to onStart/onFinish and cause unnecessary reconnects.

Minimal change: exclude handlers from the diff key.

-  }, [url, JSON.stringify(options), retry]);
+  }, [url, JSON.stringify({ ...options, onStart: undefined, onFinish: undefined }), retry]);
@@
-  }, [url, JSON.stringify(options), connect, close]);
+  }, [url, JSON.stringify({ ...options, onStart: undefined, onFinish: undefined }), connect, close]);

Better: compute a stable optionsKey from serializable fields and keep handlers in refs (as above).

Also applies to: 209-210

src/components/Playground/Playground.tsx (4)

19-29: Export the public props type and document it.

Components under src/components should export their prop interfaces and include JSDoc.

Apply:

-type PlaygroundComponentProps = {
+/**
+ * Playground component public props.
+ * @example
+ * <PlaygroundComponent defaultContent="..." />
+ */
+export type PlaygroundComponentProps = {
   defaultContent: string;
   defaultVariables?: {
     [key: string]: VariableValue;
   };
   defaultDocumentPrompt?: string;
   styles?: React.CSSProperties;
   sseUrl?: string;
   sessionId?: string;
   disableTyping?: boolean;
+  /** Label shown while streaming/loading */
+  loadingLabel?: string;
 };

148-166: Fix potential crash when contentList is empty.

Spreading newList[lastIndex] when lastIndex === -1 throws.

Apply:

   const updateContentListWithUserError = (data: string) => {
     const newList = [...contentList];
     const lastIndex = newList.length - 1;
-    const item = {
-      ...newList[lastIndex],
-    };
+    const item = lastIndex >= 0 ? { ...newList[lastIndex] } : {};
     newList.push({
       content: data,
     });
     newList.push({
       ...item,
       readonly: false,
       defaultButtonText: "",
       defaultInputText: "",
     });
 
     return newList;
   };

201-208: SSEParams misses t; object literal includes an unknown property.

You set t: +new Date() but the type doesn’t declare it.

Apply:

 type SSEParams = {
   content: string;
   block_index: number;
   context: Array<{
     role: string;
     content: string;
   }>;
   variables?: {
     [key: string]: VariableValue;
   };
   user_input: string | null;
   document_prompt: string | null;
   interaction_prompt: string | null;
   interaction_error_prompt: string | null;
   model: string | null;
+  /** Cache-busting timestamp (ms) */
+  t?: number;
 };

Also applies to: 293-302


297-300: Don’t write an empty-string key into variables.

Guard variableName before spreading.

-      variables: {
-        ...prev.variables,
-        [params.variableName || ""]: userInput,
-      },
+      variables: params.variableName
+        ? { ...prev.variables, [params.variableName]: userInput }
+        : prev.variables,
🧹 Nitpick comments (12)
src/components/Playground/useMarkdownInfo.ts (1)

17-21: Add JSDoc for the public hook.

Per repo guidelines, please document params/return with an @example.

src/components/ContentRender/plugins_bac/remark-custom-button.ts (1)

9-11: Prefer a precise shape over Record<string, unknown>.

Narrow hProperties to the actual shape for safer downstream access.

-    hProperties?: Record<string, unknown>;
+    hProperties?: { buttonText: string };
src/components/MarkdownFlow/useScrollToBottom.ts (2)

20-22: Consider readonly deps to prevent accidental mutation.

-  dependencies: unknown[] = [],
+  dependencies: ReadonlyArray<unknown> = [],

35-38: NodeJS.Timeout can be incorrect in the browser.

Use ReturnType for isomorphic typing.

-  const timers = useRef({
-    scroll: null as NodeJS.Timeout | null,
-    init: null as NodeJS.Timeout | null,
-    content: null as NodeJS.Timeout | null,
-  });
+  const timers = useRef({
+    scroll: null as ReturnType<typeof setTimeout> | null,
+    init: null as ReturnType<typeof setTimeout> | null,
+    content: null as ReturnType<typeof setTimeout> | null,
+  });
src/components/ContentRender/ContentRender.tsx (2)

25-31: Use react-markdown’s CodeComponent instead of a custom CodeProps.

Prevents drift from library prop conventions and improves type safety.

-// Define types for markdown components
-interface CodeProps extends React.HTMLAttributes<HTMLElement> {
-  inline?: boolean;
-  className?: string;
-  children?: React.ReactNode;
-}
+// Prefer library-provided type
+// import added at top: `import type { CodeComponent } from "react-markdown/lib/ast-to-react";`

Add this import at the top of the file (outside this hunk):

import type { CodeComponent } from "react-markdown/lib/ast-to-react";

79-81: Type the code renderer with CodeComponent and deduplicate return.

-    code: (props: CodeProps) => {
-      const { inline, className, children, ...rest } = props;
+    code: (({ inline, className, children, ...rest }) => {
       const match = /language-(\w+)/.exec(className || "");
       const language = match ? match[1] : "";
@@
-      return !inline && match ? (
-        <code className={className} {...rest}>
-          {children}
-        </code>
-      ) : (
-        <code className={className} {...rest}>
-          {children}
-        </code>
-      );
-    },
+      return (
+        <code className={className} {...rest}>
+          {children}
+        </code>
+      );
+    }) as CodeComponent,
src/components/sse/useSSE.ts (1)

18-21: Make onFinish generic over T for end-to-end typing.

Carry the generic through UseSSEOptions so finalData is strongly typed.

-interface UseSSEOptions extends RequestInit {
+interface UseSSEOptions<T = unknown> extends RequestInit {
   autoConnect?: boolean;
   onStart?: (index: number) => void;
-  onFinish?: (finalData: unknown, index: number) => void;
+  onFinish?: (finalData: T, index: number) => void;
   maxRetries?: number;
   retryDelay?: number;
 }

And in the signature:

-const useSSE = <T = unknown>(
+const useSSE = <T = unknown>(
   url: string,
-  options: UseSSEOptions = {}
+  options: UseSSEOptions<T> = {}
 ): UseSSEReturn<T> => {
src/components/Playground/Playground.tsx (5)

236-243: Avoid double-connect: autoConnect plus manual connect() can open two streams.

Rely on one mechanism. Prefer autoConnect, remove the effect.

   const { data, connect } = useSSE<SSEData>(sseUrl, {
     method: "POST",
     body: getSSEBody(),
     headers: sessionId ? { "session-id": sessionId } : {},
     autoConnect: !!markdownInfo && !isMarkdownLoading,
     onStart: handleOnStart,
     onFinish: handleOnFinish,
   });
 
-  useEffect(() => {
-    if (markdownInfo && !isMarkdownLoading) {
-      connect();
-    }
-  }, [markdownInfo, isMarkdownLoading, connect]);
+  // Connection is controlled via autoConnect; no manual connect() needed.

If useSSE requires explicit connect, set autoConnect: false and keep the effect—pick one.

Also applies to: 245-249


262-278: Externalize hardcoded “Loading…” string and wire a default.

Follow “no hardcoded user-facing strings” in components.

-const PlaygroundComponent: React.FC<PlaygroundComponentProps> = ({
+const PlaygroundComponent: React.FC<PlaygroundComponentProps> = ({
   defaultContent,
   defaultVariables = {},
   defaultDocumentPrompt = "",
   styles = {},
   sseUrl = "https://play.dev.pillowai.cn/api/v1/playground/generate",
   sessionId,
   disableTyping,
+  loadingLabel = "Loading...",
 }) => {
@@
-  const LoadingBar: CustomRenderBarProps = ({
+  const LoadingBar: CustomRenderBarProps = ({
     content: _content,
     displayContent: _displayContent,
     onSend: _onSend,
   }) => {
     return (
       <span className="flex gap-[10px] items-center">
         <Loader
           className="animate-spin"
           style={{ width: "15px", height: "15px" }}
         />
-        Loading...
+        {loadingLabel}
       </span>
     );
   };

If you have a shared i18n/config system, consider sourcing loadingLabel from there by default.

Also applies to: 48-56, 19-29


48-56: Adopt forwardRef and set displayName (components guideline).

Bring the component in line with src/components conventions.

-const PlaygroundComponent: React.FC<PlaygroundComponentProps> = ({
+const PlaygroundComponent = React.forwardRef<HTMLDivElement, PlaygroundComponentProps>(({
   defaultContent,
@@
-}) => {
+}, ref) => {
@@
-  return (
-    <div style={styles}>
+  return (
+    <div ref={ref} style={styles}>
       <ScrollableMarkdownFlow
         initialContentList={getAdaptedContentList()}
         onSend={handleSend}
         disableTyping={disableTyping}
       />
     </div>
   );
-};
+});
 
-export default PlaygroundComponent;
+PlaygroundComponent.displayName = "PlaygroundComponent";
+export default PlaygroundComponent;

Also applies to: 320-329, 331-331


14-16: Narrow status to known values.

Prefer a discriminated union for better exhaustiveness and DX.

-interface SSEData {
+interface SSEData {
   content?: string;
-  status?: string;
+  status?: "connecting" | "open" | "message" | "done" | "error";
   [key: string]: unknown;
 }

262-278: Confirm CustomRenderBarProps naming matches its meaning.

If it’s props (not a component type), annotate as React.FC<CustomRenderBarProps>; if it’s a component type, consider renaming to CustomRenderBar or CustomRenderBarComponent.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f9ba62 and 4c008b2.

📒 Files selected for processing (7)
  • src/components/ContentRender/ContentRender.tsx (2 hunks)
  • src/components/ContentRender/plugins_bac/remark-custom-button.ts (1 hunks)
  • src/components/ContentRender/plugins_bac/remark-custom-variable.ts (0 hunks)
  • src/components/MarkdownFlow/useScrollToBottom.ts (1 hunks)
  • src/components/Playground/Playground.tsx (3 hunks)
  • src/components/Playground/useMarkdownInfo.ts (1 hunks)
  • src/components/sse/useSSE.ts (4 hunks)
💤 Files with no reviewable changes (1)
  • src/components/ContentRender/plugins_bac/remark-custom-variable.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx,md,mdx}

📄 CodeRabbit inference engine (AGENTS.md)

Use English for all code: comments, identifiers, props, types, error messages, and documentation

Files:

  • src/components/MarkdownFlow/useScrollToBottom.ts
  • src/components/ContentRender/ContentRender.tsx
  • src/components/Playground/useMarkdownInfo.ts
  • src/components/ContentRender/plugins_bac/remark-custom-button.ts
  • src/components/sse/useSSE.ts
  • src/components/Playground/Playground.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,tsx}: All public APIs must be properly typed; avoid implicit or missing types
Use appropriate generics for reusable components and utilities
Use strict typing and avoid any; prefer precise types
Provide JSDoc API documentation for components and hooks, including @example usage

Files:

  • src/components/MarkdownFlow/useScrollToBottom.ts
  • src/components/ContentRender/ContentRender.tsx
  • src/components/Playground/useMarkdownInfo.ts
  • src/components/ContentRender/plugins_bac/remark-custom-button.ts
  • src/components/sse/useSSE.ts
  • src/components/Playground/Playground.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/components/**/*.{ts,tsx}: Export component prop interfaces so they are publicly available
Document all public props with JSDoc comments

Files:

  • src/components/MarkdownFlow/useScrollToBottom.ts
  • src/components/ContentRender/ContentRender.tsx
  • src/components/Playground/useMarkdownInfo.ts
  • src/components/ContentRender/plugins_bac/remark-custom-button.ts
  • src/components/sse/useSSE.ts
  • src/components/Playground/Playground.tsx
src/components/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

src/components/**/*.tsx: Do not hardcode user-facing strings in components; expose them via props/config
Use Tailwind CSS utility classes for styling in components
Use the cn() utility for conditional class name composition
Implement components using React.forwardRef and set Component.displayName

Files:

  • src/components/ContentRender/ContentRender.tsx
  • src/components/Playground/Playground.tsx
src/components/ContentRender/ContentRender.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Register new plugins in the ContentRender plugin registry

Files:

  • src/components/ContentRender/ContentRender.tsx
🧠 Learnings (1)
📚 Learning: 2025-09-03T04:20:04.265Z
Learnt from: CR
PR: ai-shifu/markdown-flow-ui#0
File: AGENTS.md:0-0
Timestamp: 2025-09-03T04:20:04.265Z
Learning: Applies to src/components/ContentRender/plugins/**/*.{ts,tsx} : Place custom markdown plugins under src/components/ContentRender/plugins/

Applied to files:

  • src/components/ContentRender/ContentRender.tsx
🔇 Additional comments (8)
src/components/Playground/useMarkdownInfo.ts (1)

53-56: Type-safe error handling LGTM.

Good switch to unknown with a safe Error guard.

src/components/ContentRender/plugins_bac/remark-custom-button.ts (1)

17-19: Confirm plugin registration.

If this plugin is intended for use, ensure it’s registered in ContentRender’s remarkPlugins; otherwise keep it clearly marked as backup.

src/components/MarkdownFlow/useScrollToBottom.ts (1)

20-22: Safer dependency typing LGTM.

unknown[] avoids unsafe any in dependency spreads.

src/components/sse/useSSE.ts (3)

4-11: Default generic to unknown: good hardening.

The public surface is now safer by default.


23-29: Expanded connection states LGTM.

Clearer state machine.


30-34: Generic default LGTM.

Aligns with the stronger defaults.

src/components/Playground/Playground.tsx (2)

9-11: Good replacement for any in variables.

Union covers common scalar cases and keeps callers honest.


12-17: Align useSSE generic with actual data type
Change useSSE<SSEData> to useSSE<string> so data is string | null, and update handleOnFinish to coerce its unknown payload to string.

- const { data, connect } = useSSE<SSEData>(sseUrl, {...})
+ const { data, connect } = useSSE<string>(sseUrl, {...})

- const handleOnFinish = (data: string) => { … }
+ const handleOnFinish = (final: unknown) => {
+   const data = typeof final === "string" ? final : "";
+
+ }

Likely an incorrect or invalid review comment.

- Fix useSSE type mismatch by using string instead of SSEData interface
- Add proper type guard in handleOnFinish callback to ensure type safety
- Improve CodeProps interface with node property and remove redundant fields
- Add missing tooltipMinLength property to CustomVariableProps interface
- Remove unused SSEData interface to clean up codebase

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
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.

1 participant