@e-llm-studio/requirement-ai

中文文档
0.0.382发布于 2026/11/11MITTypeScriptESM + CJS近 30 天下载 5981

原始使用文档
文档目录38 节
  1. IUserStory
  2. TAIReasoning
  3. UserStoryCitations
  4. ImageCitationsForFile
  5. FileImageData
  6. Create State
  7. Wrap Components
  8. useStreamContentHandler(props)
  9. Returns
  10. setUserStory
  11. setAiReasoning
  12. setUserStoryCitations
  13. onStreamingCompleted
  14. isGraphQLCallInProgress
  15. knowledgeBase
  16. projectAnalyserSummary
  17. dataSourceFiles
  18. aiReasoning
  19. setRedisValue
  20. fetchCitationByBlock
  21. BlockStreamItem
  22. Quick Demo
  23. Core Sub-Components
  24. Root Props
  25. Key Features
  26. Usage Notes
  27. Overview
  28. Quick Demo
  29. Component Structure
  30. Root Component Props
  31. Configuration Options
  32. Callback Handlers
  33. Accessing Context
  34. 🧩 Diff Edit Utilities – Usage Guide
  35. 1. handleDiffEditApplied
  36. 2. handleDiscardAll
  37. 3. handleAcceptAllChanges
  38. License

RequirementAIWrapper


Props

PropType
userStoryIUserStory | null
setUserStoryReact.Dispatch<React.SetStateAction<IUserStory | null>>
aiReasoningTAIReasoning[]
setAiReasoningReact.Dispatch<React.SetStateAction<TAIReasoning[]>>
citationsUserStoryCitations[]
setCitationsReact.Dispatch<React.SetStateAction<UserStoryCitations[]>>
childrenReactNode

Data Structures

IUserStory

export interface IUserStory {
  artifactId: string;
  title: string;
  value: string;
  sub_features?: IUserStory[];

  storyNumber?: string;
  description?: string;
  section?: "intro" | "subfeature";
  blockNumber?: string;

  citation?: UserStoryCitations;
  aiReasoning?: TAIReasoning[];

  isEnd?: boolean;
}

TAIReasoning

export type TAIReasoning = {
  id: string;
  reason: string;
  gap: string;
  relevance_score: number;
  reasonSource?: string;
  gapSource?: string;
  isOpen?: boolean;
  relevance_score_diff?: number;
  explanation?: string;
};

UserStoryCitations

export type UserStoryCitations = {
  image_citations?: ImageCitation[];
  appmod_citations?: TextCitation[];
  audio_citations?: AudioCitation[];
  file_citations?: FileCitation[];
  file_image_data?: ImageCitationsForFile | null;
  rca_citations?: RcaCitation[];
  web_citations?: WebCitation[];
  code_generated?: GeneratedCodeCitation[];
};

ImageCitationsForFile

interface ImageCitationsForFile {
  [key: string]: FileImageData;
}

FileImageData

interface FileImageData {
  filename: string;
  signed_url: string;
  gs_url: string;
}

Usage

Create State

const [userStory, setUserStory] = useState<IUserStory | null>(null);

const [aiReasoning, setAiReasoning] = useState<TAIReasoning[]>([]);

const [citations, setCitations] = useState<UserStoryCitations[]>([]);

Wrap Components

<RequirementAIWrapper
  userStory={userStory}
  setUserStory={setUserStory}
  aiReasoning={aiReasoning}
  setAiReasoning={setAiReasoning}
  citations={citations}
  setCitations={setCitations}
>
  {children}
</RequirementAIWrapper>

Context Value

The wrapper provides the following context value:

{
  (userStory,
    setUserStory,
    aiReasoning,
    setAiReasoning,
    citations,
    setCitations);
}

Usage

import { useStreamContentHandler } from "@e-llm-studio/requirement-ai";

function StreamingComponent() {
  const { processStreamContent } = useStreamContentHandler({
    setUserStory,
    setAiReasoning,
    setUserStoryCitations,
    onStreamingCompleted,
    isGraphQLCallInProgress,
    knowledgeBase,
    projectAnalyserSummary,
    dataSourceFiles,
    aiReasoning,
    setRedisValue,
    fetchCitationByBlock,
  });

  const handleStream = (blockList) => {
    processStreamContent(blockList, metadata, "story-artifact-id");
  };

  return <div>Streaming...</div>;
}

Hook API

useStreamContentHandler(props)

Returns

{
  processStreamContent: (
    blockList: BlockStreamItem[],
    customMetadata: any,
    storyArtifactID: string
  ) => void
}

Props

setUserStory

React state setter used to store generated user stories.

React.Dispatch<React.SetStateAction<IUserStory[]>>;

setAiReasoning

State setter used to store extracted AI reasoning.

React.Dispatch<React.SetStateAction<TAIReasoning[]>>;

setUserStoryCitations

State setter used to store citations generated from blocks.

React.Dispatch<React.SetStateAction<UserStoryCitations>>;

onStreamingCompleted

Callback executed once all citation generation tasks have completed.

(gap_items_prompt?: string, risk_items_prompt?: string) => Promise<void>;

isGraphQLCallInProgress

Boolean flag indicating whether a GraphQL call is currently running.

This prevents the completion callback from firing prematurely.

boolean;

knowledgeBase

Knowledge base metadata associated with the current stream.

any;

projectAnalyserSummary

Project analysis summary used during processing.

any;

dataSourceFiles

Information about uploaded data source files.

{
  document: string[];
  image: string[];
  meetingRecording: string[];
}

aiReasoning

Existing AI reasoning state.

TAIReasoning[]

setRedisValue

Function responsible for storing streaming state in Redis.

<T>({ key, value }: SetRedisParams<T>) => Promise<any>;

Example implementation:

async function setRedisValue({ key, value }) {
  await redis.set(key, JSON.stringify(value));
}

fetchCitationByBlock

Async function responsible for generating citations for a given block.

(block: BlockStreamItem, metadata: any, ai_reasonings: TAIReasoning[]) =>
  Promise<IGetCitationsByBlock>;

Types

BlockStreamItem

Represents a streamed AI block.

type BlockStreamItem = {
  title: string;
  section: "intro" | "subfeature";
  description?: string;
  blockNumber: string;
  value: string;
  storyNumber: string;
};

Streaming Flow

AI Stream
   ↓
Block List
   ↓
processStreamContent
   ↓
Reasoning Extraction
   ↓
User Story Generation
   ↓
Citation Generation
   ↓
Redis Persistence
   ↓
Streaming Completed Callback

Internal Safeguards

The hook includes several mechanisms to optimize streaming performance:

MechanismPurpose
updateCitationCallKeysRefPrevents duplicate citation requests
citationGenerationCompletedKeysRefTracks completed citation tasks
lastProcessedBlockListHashRefAvoids reprocessing identical block lists
lastRedisValueRefPrevents redundant Redis writes

Best Practices

  • Ensure fetchCitationByBlock is idempotent.
  • Avoid extremely frequent calls to processStreamContent without batching.
  • Always serialize Redis values using JSON.

UserStoryScreen Component

A composable UI component system for displaying and editing user stories with AI reasoning citations. It must be wrapped within RequirementAIWrapper to access shared state.

Quick Demo

import React, { useState } from "react";
import RequirementAIWrapper from "@e-llm-studio/requirement-ai";
import UserStoryScreen from "@e-llm-studio/requirement-ai";
import UserStoryWithCitations from "@e-llm-studio/requirement-ai";
import RichTextEditor from "@e-llm-studio/requirement-ai";
import AtomicButton from "@e-llm-studio/requirement-ai";

function MyStoryApp() {
  const [userStory, setUserStory] = useState<IUserStory[]>([
    {
      artifactId: "story-1",
      title: "User Login",
      value: "As a user, I want to login to the system",
    },
  ]);

  const [aiReasoning, setAiReasoning] = useState<TAIReasoning[]>([]);
  const [citations, setCitations] = useState<UserStoryCitations[]>([]);

  return (
    <RequirementAIWrapper
      userStory={userStory}
      setUserStory={setUserStory}
      aiReasoning={aiReasoning}
      setAiReasoning={setAiReasoning}
      citations={citations}
      setCitations={setCitations}
      apiCachingConfig={{
        queryClient: null, // replace with original tanstack-query client
        useGetSignedUrlQuery: (gsUtilPath: string, cacheKey: string[]) => null, // replace with original hook
        useGetSignedUrlMutation: (gsUtilPath: string) => null, // replace with original hook
        useExtractAudioPeaksMutation: () => null, // replace with original hook
        useExtractAudioPeaksQuery: (gsUtilPath: string, cacheKey: string[]) => null, // replace with original hook
        useGetVideoSignedUrlMutation: (gsUtilPath: string) => null, // replace with original hook
        useGetVideoSignedUrlQuery: (gsUtilPath: string, cacheKey: string[]) => null, // replace with original hook
      }}
    >
      <UserStoryScreen scenario="ready" isCitationLoadingNotStarted={true}>
        <UserStoryScreen.Content AtomicButton={AtomicButton}>
          <UserStoryScreen.Body>
            <UserStoryScreen.Story Component={UserStoryWithCitations} />
            <UserStoryScreen.Editor Component={RichTextEditor} />
            <UserStoryScreen.SubFeatures />
          </UserStoryScreen.Body>
          <UserStoryScreen.ScrollButton />
        </UserStoryScreen.Content>
      </UserStoryScreen>
    </RequirementAIWrapper>
  );
}

Core Sub-Components

ComponentPurpose
UserStoryScreen.SidebarNavigation sidebar for story selection
UserStoryScreen.SidebarToggleCollapse/expand sidebar button
UserStoryScreen.ContentMain content wrapper with header and controls
UserStoryScreen.BodyContainer for Story/Editor (handles mutual exclusion)
UserStoryScreen.StoryDisplays selected story with citations (read mode)
UserStoryScreen.EditorRich text editor for editing stories (edit mode)
UserStoryScreen.SubFeaturesAccordion for nested sub-features
UserStoryScreen.ScrollButtonFloating button to scroll to bottom

Root Props

interface UserStoryScreenProps {
  scenario: "streaming" | "ready"; // "streaming" for real-time, "ready" for static
  isCitationLoadingNotStarted: boolean; // Flag for citation loading state
  children: React.ReactNode; // Sub-components
  classNames?: UserStoryScreenClassNames; // Optional custom CSS classes
}

Key Features

  • Automatic State Management: All components pull from RequirementAIWrapper context
  • Mutual Exclusion: Story and Editor views are automatically exclusive
  • Streaming Support: Real-time updates with skeleton loaders
  • Citation Integration: AI reasoning and citations highlighted in stories
  • Markdown Support: Stories support markdown formatting with custom tags

Usage Notes

  1. Always wrap with RequirementAIWrapper - Provides context for all sub-components
  2. Use Body wrapper - Ensures proper Story/Editor mutual exclusion
  3. Pass custom components - Story and Editor expect React components as props
  4. Set scenario correctly - "streaming" for real-time data, "ready" for static content

UserStoryApprovalScreen Component

A dedicated approval workflow component for reviewing and approving AI-generated user stories. It must be wrapped within RequirementAIWrapper to access shared state.

Overview

UserStoryApprovalScreen provides a structured interface for:

  • Reviewing generated user stories segment-by-segment
  • Editing individual content segments
  • Approving content progressively
  • Managing sub-features with delete capabilities
  • Bulk approval with "Approve All" functionality

Quick Demo

import React, { useState } from "react";
import RequirementAIWrapper from "@e-llm-studio/requirement-ai";
import UserStoryApprovalScreen from "@e-llm-studio/requirement-ai";
import UserStoryWithCitations from "@e-llm-studio/requirement-ai";
import RichTextEditor from "@e-llm-studio/requirement-ai";
import AtomicButton from "@e-llm-studio/requirement-ai";

function MyApprovalFlow() {
  const [userStory, setUserStory] = useState<IUserStory[]>([]);
  const [aiReasoning, setAiReasoning] = useState<TAIReasoning[]>([]);
  const [citations, setCitations] = useState<UserStoryCitations[]>([]);

  return (
    <RequirementAIWrapper
      userStory={userStory}
      setUserStory={setUserStory}
      aiReasoning={aiReasoning}
      setAiReasoning={setAiReasoning}
      citations={citations}
      setCitations={setCitations}
      apiCachingConfig={{
        queryClient: null, // replace with original tanstack-query client
        useGetSignedUrlQuery: (gsUtilPath: string, cacheKey: string[]) => null, // replace with original hook
        useGetSignedUrlMutation: (gsUtilPath: string) => null, // replace with original hook
        useExtractAudioPeaksMutation: () => null, // replace with original hook
        useExtractAudioPeaksQuery: (gsUtilPath: string, cacheKey: string[]) => null, // replace with original hook
        useGetVideoSignedUrlMutation: (gsUtilPath: string) => null, // replace with original hook
        useGetVideoSignedUrlQuery: (gsUtilPath: string, cacheKey: string[]) => null, // replace with original hook
      }}
    >
      <UserStoryApprovalScreen
        artifactTitleIds={["STORY-001"]}
        config={{
          showApproveAllButton: true,
          allowEditing: true,
          allowDeletion: true,
          containerHeight: "calc(100vh - 100px)",
        }}
        callbacks={{
          onShowNotification: (type, title, message) => {
            console.log(`[${type}] ${title}: ${message}`);
          },
          onInitialize: () => {
            console.log("Approval screen initialized");
          },
          onSaveState: async (stories) => {
            await saveToRedis(stories);
          },
          onAllApproved: async (stories) => {
            await submitApprovedStories(stories);
          },
        }}
      >
        <UserStoryApprovalScreen.Content ButtonComponent={AtomicButton}>
          <UserStoryApprovalScreen.Body
            EditorComponent={RichTextEditor}
            ViewerComponent={UserStoryWithCitations}
          />
        </UserStoryApprovalScreen.Content>
      </UserStoryApprovalScreen>
    </RequirementAIWrapper>
  );
}

Component Structure

ComponentPurpose
UserStoryApprovalScreen (Root)Container with approval state management
UserStoryApprovalScreen.ContentHeader with title, metadata, and "Approve All" button
UserStoryApprovalScreen.BodyRenders content segments with edit/approve/delete actions

Root Component Props

interface UserStoryApprovalScreenProps {
  artifactTitleIds: string[]; // Display IDs for each story
  config?: UserStoryApprovalScreenConfig; // Feature toggles
  callbacks?: UserStoryApprovalScreenCallbacks; // Platform-specific handlers
  labels?: Partial<UserStoryApprovalScreenLabels>; // Custom text labels
  isDisabled?: boolean; // Disable all interactions
  children: React.ReactNode; // Sub-components
  classNames?: UserStoryApprovalScreenClassNames; // Custom CSS classes
}

Configuration Options

interface UserStoryApprovalScreenConfig {
  showApproveAllButton?: boolean; // Show/hide "Approve All" button (default: true)
  allowEditing?: boolean; // Enable editing segments (default: true)
  allowDeletion?: boolean; // Enable deleting sub-features (default: true)
  showSidebar?: boolean; // Show sidebar for multi-story navigation (default: false)
  containerHeight?: string; // CSS height value (default: "calc(100vh - 100px)")
  useFullWidth?: boolean; // Use 100% width without margins (default: false)
}

Callback Handlers

interface UserStoryApprovalScreenCallbacks {
  /** Show toast/notification - required for user feedback */
  onShowNotification?: (
    type: "success" | "error" | "warn" | "info",
    title: string,
    message: string,
    duration?: number,
  ) => void;

  /** Initialize platform (e.g., adjust chat width in web app) */
  onInitialize?: () => void;

  /** Persist approval state to Redis/storage */
  onSaveState?: (stories: IUserStoryForApproval[]) => Promise<void>;

  /** Triggered when all stories are approved */
  onAllApproved?: (stories: IUserStoryForApproval[]) => Promise<void>;

  /** Custom scroll behavior for focusing segments */
  onScrollToElement?: (element: HTMLElement) => void;
}

Accessing Context

Use useRequirementAI() hook within UserStoryScreen components:

import { useRequirementAI } from "@e-llm-studio/requirement-ai";

function MyCustomComponent() {
  const { userStory, setUserStory, aiReasoning } = useRequirementAI();
  return <div>{userStory?.[0]?.title}</div>;
}


🧩 Diff Edit Utilities – Usage Guide

1. handleDiffEditApplied

Applies AI diff response to user stories, reasoning, and chat history.

handleDiffEditApplied(
  aiResponseString,
  selectedUserStoryType,
  username,
  setUserStory,
  setAiReasoning,
  setAiReasoningDiffView,
  setChatHistory,
  setUserStoryDiffView
);

Use when:

  • You receive AI diff-edit response
  • You want to update UI with new stories, reasoning, and chat

2. handleDiscardAll

Rejects all diff changes and restores original state.

handleDiscardAll(
  userStory,
  setUserStory,
  setAiReasoning,
  setUserStoryDiffView
);

Use when:

  • User clicks “Discard All Changes”
  • You want to revert to original content

3. handleAcceptAllChanges

Accepts all diff changes and updates user stories.

handleAcceptAllChanges(
  userStory,
  setUserStory,
  setIsAutoSaveEnabled
);

License

This library is released under the MIT License. See the LICENSE file for more details.

The license information is also available in the citation/package.json file under the 'license' field.

版本与发布记录

@e-llm-studio/requirement-ai 共发布 375 个版本,首次发布于 2026/03/17;过去 12 个月发布了 375 个版本。

版本发布日期距今
0.0.382latest2026/11/112 天前
0.0.3812026/11/112 天前
0.0.3802026/11/112 天前
0.0.3792026/11/103 天前
0.0.3782026/11/093 天前
0.0.3772026/11/076 天前

其他发布通道:reqAIConflictFix → 0.0.98,reqAIConflitFixFinal → 0.0.99,bildTime100 → 0.0.100。

关于 @e-llm-studio/requirement-ai 的常见问题

如何安装 @e-llm-studio/requirement-ai?

在项目目录运行 npm install @e-llm-studio/requirement-ai,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=16.8.0 <19.0.0)、react-dom(>=16.8.0 <19.0.0)、@mui/material(^6.5.0)、monaco-editor(^0.55.1)、@emotion/react(^11.13.5)、@emotion/styled(^11.13.0)、@react-pdf-viewer/core(^3.12.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@e-llm-studio/requirement-ai 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@e-llm-studio/requirement-ai 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@e-llm-studio/requirement-ai 可以商用吗?

@e-llm-studio/requirement-ai 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@e-llm-studio/requirement-ai 的下载量有多少?

根据 npm 官方下载统计,@e-llm-studio/requirement-ai 在 2026/10/13 – 2026/11/11 这 30 天内被下载 5,981 次,日均约 199 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@e-llm-studio/requirement-ai 还在维护吗?

最新版本 0.0.382 发布于 2026/11/11(2 天前);至今共发布 375 个版本,其中过去 12 个月发布了 375 个;首次发布于 2026/03/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。