Skip to content

feat(sso): PKCE, Nonce 검증, Keycloak end_session 로그아웃 보안 강화#12381

Closed
YeonghyeonKO wants to merge 23 commits intolangflow-ai:mainfrom
YeonghyeonKO:feat/sso-pkce-nonce-oidc-logout
Closed

feat(sso): PKCE, Nonce 검증, Keycloak end_session 로그아웃 보안 강화#12381
YeonghyeonKO wants to merge 23 commits intolangflow-ai:mainfrom
YeonghyeonKO:feat/sso-pkce-nonce-oidc-logout

Conversation

@YeonghyeonKO
Copy link
Copy Markdown

개요

레퍼런스 구현 Wonki4/llm-ops를 분석하여 현재 Keycloak SSO 플러그인에 누락된 세 가지 보안 기능을 식별하고 적용합니다.

식별된 보안 취약점

항목 레퍼런스 구현 기존 구현 이번 PR
PKCE S256 방식으로 구현 미적용 적용
Nonce 검증 id_token nonce claim 검증 state에 nonce 생성하나 검증 안 함 적용
Keycloak 로그아웃 end_session_endpoint 호출 /login으로 단순 리다이렉트 적용

변경 내용

settings.py

  • end_session_endpoint 프로퍼티 추가: {SERVER_URL}/realms/{REALM}/protocol/openid-connect/logout
  • LOGOUT_REDIRECT_URI: str = "" 설정 추가 (Keycloak 로그아웃 후 리다이렉트 대상, 미설정 시 REDIRECT_URI origin + /login 자동 구성)

keycloak_client.py

  • exchange_code 메서드에 code_verifier: str | None = None 파라미터 추가
  • code_verifier 가 있을 때 token endpoint POST 데이터에 포함

router.py

  • PKCE: /login에서 _generate_pkce()code_verifier/code_challenge 생성, state JWT에 code_verifier 저장, auth URL에 code_challenge·code_challenge_method=S256 추가
  • Nonce 검증: /login에서 nonce 생성, state JWT와 auth URL 파라미터에 포함. /callback에서 id_token의 nonce claim과 비교하여 불일치 시 401 반환
  • id_token 쿠키: /callback에서 Keycloak id_tokenkc_id_token_lf httpOnly 쿠키로 저장
  • Keycloak end_session 로그아웃: /logoutrequest: Request 파라미터 추가, kc_id_token_lf 쿠키 읽어 id_token_hint로 Keycloak end_session_endpoint 호출. kc_id_token_lf 쿠키도 삭제 목록에 포함

의도적으로 적용하지 않은 것

레퍼런스 구현과 비교해 다음 항목은 아키텍처 차이로 인해 의도적으로 적용하지 않습니다:

  • 공유 사용자 모델 제거: 레퍼런스는 Keycloak 사용자별 개별 Langflow 계정을 생성하지만, 본 프로젝트는 단일 공유 계정(KEYCLOAK_SHARED_USERNAME) 방식을 유지합니다. 인가(Authorization)는 Keycloak에 완전히 위임하는 설계입니다.
  • Fernet 세션 암호화: 레퍼런스의 Fernet 기반 세션 저장 방식은 사용하지 않습니다. Langflow 기본 JWT 쿠키 방식을 유지합니다.
  • LiteLLM 팀 프로비저닝: 레퍼런스의 LiteLLM 연동 기능은 본 프로젝트의 범위 밖입니다.

테스트 체크리스트

  • Keycloak 클라이언트에 PKCE 지원 활성화 후 로그인 플로우 정상 동작 확인
  • id_token nonce 불일치 시 401 Nonce mismatch 응답 확인
  • 로그아웃 후 Keycloak 세션도 함께 종료되어 재로그인 요구 확인
  • KEYCLOAK_LOGOUT_REDIRECT_URI 미설정 시 REDIRECT_URI origin + /login으로 자동 구성 확인
  • id_token 쿠키 없는 경우 기존과 동일하게 /login으로 리다이렉트 확인

🤖 Generated with Claude Code

YeonghyeonKO and others added 22 commits March 25, 2026 20:12
Implements Keycloak OIDC authentication via the Langflow plugin system.
Users are authenticated with company Keycloak credentials; members of
the same Keycloak group share a single Langflow account (group → account
mapping is managed at runtime via a DB table and admin API).

Key components:
- langflow-keycloak-sso: plugin package registered via langflow.plugins
  entry-point; adds /api/v1/keycloak/{config,login,callback,mappings}
- OIDC flow: authorization code + PKCE-less with JWKS signature verify
- Shared account auto-provisioning on first login
- Login page: "Login with Keycloak" button shown when KEYCLOAK_ENABLED=true
- mock_oidc_server.py: standalone FastAPI OIDC mock for local development

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For local Keycloak SSO development/testing only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Authorization is fully delegated to Keycloak (client-level access control).
Any user who passes Keycloak is logged into one shared Langflow account
configured via KEYCLOAK_SHARED_USERNAME — no group mapping DB needed.

- Remove KeycloakGroupMapping DB table and admin API endpoints
- Remove models.py (no DB schema needed)
- Replace group→account mapping with KEYCLOAK_SHARED_USERNAME env var
- Update mock OIDC server with 10 employees (사번 EMP001~EMP010):
  - EMP001, EMP002: 모든 프로젝트 접근 가능
  - EMP003~EMP005: project-a 전용
  - EMP006~EMP008: project-b 전용
  - EMP009, EMP010: 접근 권한 없음

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LoginPage: remove username/password form; show only "SSO 로그인" button
- AccountMenu: override logout to call GET /api/v1/keycloak/logout
  (bypasses IS_AUTO_LOGIN bug that skipped cookie deletion in JS logout)
- router.py: add GET /api/v1/keycloak/logout endpoint that deletes all
  session cookies server-side and redirects to /login
- scripts/mock_oidc_server.py: rewrite with group-based client access
  control (langflow-admins / project-a-members / project-b-members,
  EMP001-EMP010), uv inline script metadata for zero-setup dependency mgmt
- scripts/start_dev.sh: start project-a (:7860) and project-b (:7861)
  on subdomains (project-a.localhost / project-b.localhost) to isolate
  cookies between instances

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- docker/keycloak-sso.Dockerfile: multi-stage build (builder + runtime),
  installs langflow-keycloak-sso plugin via uv pip after workspace sync,
  builds modified frontend (SSO-only login page) in builder stage
- docker/keycloak-sso.docker-compose.yml: local multi-instance test setup
  (project-a :7860, project-b :7861, mock-oidc :9000)

Build:
  docker build -f docker/keycloak-sso.Dockerfile -t langflow-keycloak-sso .

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deleted 62 component directories and removed them from __init__.py
(_dynamic_imports, __all__, TYPE_CHECKING imports):

agentql, aiml, altk, amazon, anthropic, apify, arxiv, assemblyai, azure,
baidu, bing, cassandra, chroma, cleanlab, crewai, datastax, deepseek,
duckduckgo, exa, firecrawl, glean, google, groq, homeassistant, huggingface,
ibm, icosacomputing, jigsawstack, langwatch, lmstudio, maritalk, mem0,
mistral, mongodb, needle, Notion, notdiamond, novita, nvidia, olivya,
ollama, perplexity, pinecone, qdrant, sambanova, scrapegraph, searchapi,
serpapi, supabase, twelvelabs, unstructured, upstash, vectara, vertexai,
vlmrun, weaviate, wikipedia, wolframalpha, xai, yahoosearch, youtube, zep

Remaining: FAISS, chains, clickhouse, cloudflare, cohere, composio,
confluence, couchbase, cuga, custom_component, data, deactivated, docling,
documentloaders, elastic, embeddings, git, helpers, input_output,
langchain_utilities, link_extractors, litellm, logic, milvus, models_and_agents,
openai, openrouter, output_parsers, pgvector, processing, prototypes, redis,
tavily, textsplitters, toolkits, tools, vectorstores

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…for Node.js

- Move langflow-keycloak-sso install to after final uv sync to prevent
  --frozen cleanup from removing the plugin (it's not in the lockfile)
- Replace dynamic Node.js tarball detection (grep -oP Perl regex) with
  nodesource setup_22.x in runtime stage — fixes ARM/amd64 compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When Langflow runs in Docker, KEYCLOAK_SERVER_URL points to the internal
service name (e.g. http://mock-oidc:9000) which the browser cannot resolve.
KEYCLOAK_EXTERNAL_SERVER_URL overrides only the authorization_endpoint
(browser redirect) while token exchange and JWKS still use SERVER_URL.

Updated docker-compose to set EXTERNAL_SERVER_URL=http://localhost:9000
so the browser is redirected to the host-accessible mock OIDC server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: Keycloak SSO plugin — instance-scoped shared account login
- textAreaComponent: add localValue state and composition guards to prevent
  setSelectionRange and parent state updates during IME composition, fixing
  Korean consonant/vowel separation in Parser Template and LLM System Message inputs
- CustomInputPopover: same localValue + composition pattern for general text inputs
- accordionPromptComponent: skip innerHTML update during composition to prevent
  breaking Korean input in contentEditable prompt fields
- LoginPage: change SSO login button text to 'SK하이닉스 SSO 로그인'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed packages for the 62 deleted lfx components from
src/backend/base/pyproject.toml:

Direct deps removed (not imported anywhere in remaining code):
- firecrawl-py (firecrawl component deleted)
- assemblyai (assemblyai component deleted)
- onnxruntime (no remaining usage)

Removed from [complete] extras (corresponding components deleted):
- Vector stores: cassandra, mongodb, mongodb-vectors, qdrant, weaviate,
  upstash, pinecone, astradb, astra, astrapy, ragstack
- LLM providers: anthropic, groq, mistral, sambanova, nvidia
- AWS: aws, aioboto3
- Other: altk, apify, assemblyai, cleanlab, dspy, duckduckgo,
  huggingface, jigsawstack, langchain-unstructured, mem0, metal,
  metaphor, needle, pydantic-ai, pytube, qianfan, ragstack, scrapegraph,
  serpapi, smolagents, supabase, twelvelabs, vlmrun, weaviate, wikipedia,
  wolframalpha, youtube, zep, ag2

Packages kept: ibm-watsonx-ai, langchain-ibm (used by models_and_agents),
langchain-chroma (used by vectorstores), scipy/elevenlabs (voice features),
spider-client (langchain_utilities), clickhouse-connect (clickhouse),
langchain-ollama (files_and_knowledge/retrieval), google packages
(files_and_knowledge/retrieval + tools/google_search_api),
langchain-huggingface (files_and_knowledge/retrieval),
langwatch (tracing service), opensearch (elastic components)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…re during IME composition

- accordionPromptComponent: move handleOnNewValue inside !isComposingRef.current
  guard so partial IME states (e.g. individual Hangul jamo) are never pushed
  upstream; merge with the existing innerHTML guard into a single block
- popover: add !isComposing guard and isComposing to deps of cursor restore
  useEffect so setSelectionRange is never called while IME is active
- textAreaComponent: add isComposing to deps of cursor restore useEffect
  (guard was already present; adds exhaustive-deps compliance and ensures
  the effect re-runs when composition ends)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ci.yml: remove ANTHROPIC_API_KEY from env — Anthropic components are
  not used in hynix fork, so key should not be injected; tests that
  check ANTHROPIC_API_KEY will now correctly skip instead of failing
  with a 400 credit-balance error
- typescript_test.yml: change shard formula from 1/5 (max 70) to 1/15
  (max 20) — reduces ~57 parallel shards to ~19, cutting CI wall-clock
  time significantly for a fork that runs fewer integration flows

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: resolve Korean IME input issue and update SSO login button text
- Add ignoreTitleCase prop to SSO login button to prevent toTitleCase()
  from converting "SK하이닉스 SSO 로그인" → "Sk하이닉스 Sso 로그인"
- Update KEYCLOAK_BUTTON_TEXT default in Dockerfile to "SK하이닉스 SSO 로그인"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Read KEYCLOAK_BUTTON_TEXT env var via /api/v1/keycloak/config instead of
hardcoding, so each instance can display its own label without a frontend rebuild.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
langflow-base was overwriting langflow's frontend because both packages
install into langflow/frontend/. Fixed by copying the npm build output
directly into src/backend/base/langflow/frontend (after clearing it),
so langflow-base's wheel includes the freshly built frontend.

Also added rm -rf to ensure a clean copy (cp -r into existing dir
creates a subdirectory instead of replacing).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
레퍼런스 구현(https://github.com/Wonki4/llm-ops) 분석을 통해 식별한
세 가지 보안 취약점을 Keycloak SSO 플러그인에 적용합니다.

- PKCE S256: /login에서 code_verifier/code_challenge 생성, state JWT에
  code_verifier 저장, /callback에서 token exchange 시 code_verifier 전달
- Nonce 검증: /login에서 nonce 생성 후 auth URL과 state JWT에 포함,
  /callback에서 id_token nonce claim 비교로 재전송 공격 방지
- Keycloak end_session 로그아웃: 로그인 시 id_token을 kc_id_token_lf
  쿠키에 저장, /logout에서 id_token_hint로 Keycloak end_session_endpoint
  호출하여 SSO 세션 완전 종료
- settings.py에 end_session_endpoint 프로퍼티 및 LOGOUT_REDIRECT_URI
  설정 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 28, 2026

Important

Review skipped

Too many files!

This PR contains 232 files, which is 82 over the limit of 150.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 257e5cb6-d3b0-4fc3-83f6-95315ffa04e2

📥 Commits

Reviewing files that changed from the base of the PR and between 08bf984 and 995d775.

⛔ Files ignored due to path filters (1)
  • src/frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (232)
  • .github/workflows/ci.yml
  • .github/workflows/typescript_test.yml
  • docker/keycloak-sso.Dockerfile
  • docker/keycloak-sso.docker-compose.yml
  • scripts/mock_oidc_server.py
  • scripts/start_dev.sh
  • src/backend/langflow-keycloak-sso/pyproject.toml
  • src/backend/langflow-keycloak-sso/src/langflow_keycloak_sso/__init__.py
  • src/backend/langflow-keycloak-sso/src/langflow_keycloak_sso/keycloak_client.py
  • src/backend/langflow-keycloak-sso/src/langflow_keycloak_sso/mapping.py
  • src/backend/langflow-keycloak-sso/src/langflow_keycloak_sso/plugin.py
  • src/backend/langflow-keycloak-sso/src/langflow_keycloak_sso/router.py
  • src/backend/langflow-keycloak-sso/src/langflow_keycloak_sso/settings.py
  • src/frontend/src/components/core/appHeaderComponent/components/AccountMenu/index.tsx
  • src/frontend/src/components/core/parameterRenderComponent/components/accordionPromptComponent/index.tsx
  • src/frontend/src/components/core/parameterRenderComponent/components/inputComponent/components/popover/index.tsx
  • src/frontend/src/components/core/parameterRenderComponent/components/textAreaComponent/index.tsx
  • src/frontend/src/controllers/API/queries/keycloak/use-get-keycloak-config.ts
  • src/frontend/src/pages/LoginPage/index.tsx
  • src/lfx/src/lfx/components/Notion/__init__.py
  • src/lfx/src/lfx/components/Notion/add_content_to_page.py
  • src/lfx/src/lfx/components/Notion/create_page.py
  • src/lfx/src/lfx/components/Notion/list_database_properties.py
  • src/lfx/src/lfx/components/Notion/list_pages.py
  • src/lfx/src/lfx/components/Notion/list_users.py
  • src/lfx/src/lfx/components/Notion/page_content_viewer.py
  • src/lfx/src/lfx/components/Notion/search.py
  • src/lfx/src/lfx/components/Notion/update_page_property.py
  • src/lfx/src/lfx/components/__init__.py
  • src/lfx/src/lfx/components/agentql/__init__.py
  • src/lfx/src/lfx/components/agentql/agentql_api.py
  • src/lfx/src/lfx/components/aiml/__init__.py
  • src/lfx/src/lfx/components/aiml/aiml.py
  • src/lfx/src/lfx/components/aiml/aiml_embeddings.py
  • src/lfx/src/lfx/components/altk/__init__.py
  • src/lfx/src/lfx/components/altk/altk_agent.py
  • src/lfx/src/lfx/components/amazon/__init__.py
  • src/lfx/src/lfx/components/amazon/amazon_bedrock_converse.py
  • src/lfx/src/lfx/components/amazon/amazon_bedrock_embedding.py
  • src/lfx/src/lfx/components/amazon/amazon_bedrock_model.py
  • src/lfx/src/lfx/components/amazon/s3_bucket_uploader.py
  • src/lfx/src/lfx/components/anthropic/__init__.py
  • src/lfx/src/lfx/components/anthropic/anthropic.py
  • src/lfx/src/lfx/components/apify/__init__.py
  • src/lfx/src/lfx/components/apify/apify_actor.py
  • src/lfx/src/lfx/components/arxiv/__init__.py
  • src/lfx/src/lfx/components/arxiv/arxiv.py
  • src/lfx/src/lfx/components/assemblyai/__init__.py
  • src/lfx/src/lfx/components/assemblyai/assemblyai_get_subtitles.py
  • src/lfx/src/lfx/components/assemblyai/assemblyai_lemur.py
  • src/lfx/src/lfx/components/assemblyai/assemblyai_list_transcripts.py
  • src/lfx/src/lfx/components/assemblyai/assemblyai_poll_transcript.py
  • src/lfx/src/lfx/components/assemblyai/assemblyai_start_transcript.py
  • src/lfx/src/lfx/components/azure/__init__.py
  • src/lfx/src/lfx/components/azure/azure_openai.py
  • src/lfx/src/lfx/components/azure/azure_openai_embeddings.py
  • src/lfx/src/lfx/components/baidu/__init__.py
  • src/lfx/src/lfx/components/baidu/baidu_qianfan_chat.py
  • src/lfx/src/lfx/components/bing/__init__.py
  • src/lfx/src/lfx/components/bing/bing_search_api.py
  • src/lfx/src/lfx/components/cassandra/__init__.py
  • src/lfx/src/lfx/components/cassandra/cassandra.py
  • src/lfx/src/lfx/components/cassandra/cassandra_chat.py
  • src/lfx/src/lfx/components/cassandra/cassandra_graph.py
  • src/lfx/src/lfx/components/chroma/__init__.py
  • src/lfx/src/lfx/components/chroma/chroma.py
  • src/lfx/src/lfx/components/cleanlab/__init__.py
  • src/lfx/src/lfx/components/cleanlab/cleanlab_evaluator.py
  • src/lfx/src/lfx/components/cleanlab/cleanlab_rag_evaluator.py
  • src/lfx/src/lfx/components/cleanlab/cleanlab_remediator.py
  • src/lfx/src/lfx/components/crewai/__init__.py
  • src/lfx/src/lfx/components/crewai/crewai.py
  • src/lfx/src/lfx/components/crewai/hierarchical_crew.py
  • src/lfx/src/lfx/components/crewai/hierarchical_task.py
  • src/lfx/src/lfx/components/crewai/sequential_crew.py
  • src/lfx/src/lfx/components/crewai/sequential_task.py
  • src/lfx/src/lfx/components/crewai/sequential_task_agent.py
  • src/lfx/src/lfx/components/datastax/__init__.py
  • src/lfx/src/lfx/components/datastax/astradb_assistant_manager.py
  • src/lfx/src/lfx/components/datastax/astradb_chatmemory.py
  • src/lfx/src/lfx/components/datastax/astradb_cql.py
  • src/lfx/src/lfx/components/datastax/astradb_graph.py
  • src/lfx/src/lfx/components/datastax/astradb_tool.py
  • src/lfx/src/lfx/components/datastax/astradb_vectorize.py
  • src/lfx/src/lfx/components/datastax/astradb_vectorstore.py
  • src/lfx/src/lfx/components/datastax/create_assistant.py
  • src/lfx/src/lfx/components/datastax/create_thread.py
  • src/lfx/src/lfx/components/datastax/dotenv.py
  • src/lfx/src/lfx/components/datastax/get_assistant.py
  • src/lfx/src/lfx/components/datastax/getenvvar.py
  • src/lfx/src/lfx/components/datastax/graph_rag.py
  • src/lfx/src/lfx/components/datastax/hcd.py
  • src/lfx/src/lfx/components/datastax/list_assistants.py
  • src/lfx/src/lfx/components/datastax/run.py
  • src/lfx/src/lfx/components/deepseek/__init__.py
  • src/lfx/src/lfx/components/deepseek/deepseek.py
  • src/lfx/src/lfx/components/duckduckgo/__init__.py
  • src/lfx/src/lfx/components/duckduckgo/duck_duck_go_search_run.py
  • src/lfx/src/lfx/components/exa/__init__.py
  • src/lfx/src/lfx/components/exa/exa_search.py
  • src/lfx/src/lfx/components/firecrawl/__init__.py
  • src/lfx/src/lfx/components/firecrawl/firecrawl_crawl_api.py
  • src/lfx/src/lfx/components/firecrawl/firecrawl_extract_api.py
  • src/lfx/src/lfx/components/firecrawl/firecrawl_map_api.py
  • src/lfx/src/lfx/components/firecrawl/firecrawl_scrape_api.py
  • src/lfx/src/lfx/components/glean/__init__.py
  • src/lfx/src/lfx/components/glean/glean_search_api.py
  • src/lfx/src/lfx/components/google/__init__.py
  • src/lfx/src/lfx/components/google/gmail.py
  • src/lfx/src/lfx/components/google/google_bq_sql_executor.py
  • src/lfx/src/lfx/components/google/google_drive.py
  • src/lfx/src/lfx/components/google/google_drive_search.py
  • src/lfx/src/lfx/components/google/google_generative_ai.py
  • src/lfx/src/lfx/components/google/google_generative_ai_embeddings.py
  • src/lfx/src/lfx/components/google/google_oauth_token.py
  • src/lfx/src/lfx/components/google/google_search_api_core.py
  • src/lfx/src/lfx/components/google/google_serper_api_core.py
  • src/lfx/src/lfx/components/groq/__init__.py
  • src/lfx/src/lfx/components/groq/groq.py
  • src/lfx/src/lfx/components/homeassistant/__init__.py
  • src/lfx/src/lfx/components/homeassistant/home_assistant_control.py
  • src/lfx/src/lfx/components/homeassistant/list_home_assistant_states.py
  • src/lfx/src/lfx/components/huggingface/__init__.py
  • src/lfx/src/lfx/components/huggingface/huggingface.py
  • src/lfx/src/lfx/components/huggingface/huggingface_inference_api.py
  • src/lfx/src/lfx/components/ibm/__init__.py
  • src/lfx/src/lfx/components/ibm/watsonx.py
  • src/lfx/src/lfx/components/ibm/watsonx_embeddings.py
  • src/lfx/src/lfx/components/icosacomputing/__init__.py
  • src/lfx/src/lfx/components/icosacomputing/combinatorial_reasoner.py
  • src/lfx/src/lfx/components/jigsawstack/__init__.py
  • src/lfx/src/lfx/components/jigsawstack/ai_scrape.py
  • src/lfx/src/lfx/components/jigsawstack/ai_web_search.py
  • src/lfx/src/lfx/components/jigsawstack/file_read.py
  • src/lfx/src/lfx/components/jigsawstack/file_upload.py
  • src/lfx/src/lfx/components/jigsawstack/image_generation.py
  • src/lfx/src/lfx/components/jigsawstack/nsfw.py
  • src/lfx/src/lfx/components/jigsawstack/object_detection.py
  • src/lfx/src/lfx/components/jigsawstack/sentiment.py
  • src/lfx/src/lfx/components/jigsawstack/text_to_sql.py
  • src/lfx/src/lfx/components/jigsawstack/text_translate.py
  • src/lfx/src/lfx/components/jigsawstack/vocr.py
  • src/lfx/src/lfx/components/langwatch/__init__.py
  • src/lfx/src/lfx/components/langwatch/langwatch.py
  • src/lfx/src/lfx/components/lmstudio/__init__.py
  • src/lfx/src/lfx/components/lmstudio/lmstudioembeddings.py
  • src/lfx/src/lfx/components/lmstudio/lmstudiomodel.py
  • src/lfx/src/lfx/components/maritalk/__init__.py
  • src/lfx/src/lfx/components/maritalk/maritalk.py
  • src/lfx/src/lfx/components/mem0/__init__.py
  • src/lfx/src/lfx/components/mem0/mem0_chat_memory.py
  • src/lfx/src/lfx/components/mistral/__init__.py
  • src/lfx/src/lfx/components/mistral/mistral.py
  • src/lfx/src/lfx/components/mistral/mistral_embeddings.py
  • src/lfx/src/lfx/components/mongodb/__init__.py
  • src/lfx/src/lfx/components/mongodb/mongodb_atlas.py
  • src/lfx/src/lfx/components/needle/__init__.py
  • src/lfx/src/lfx/components/needle/needle.py
  • src/lfx/src/lfx/components/notdiamond/__init__.py
  • src/lfx/src/lfx/components/notdiamond/notdiamond.py
  • src/lfx/src/lfx/components/novita/__init__.py
  • src/lfx/src/lfx/components/novita/novita.py
  • src/lfx/src/lfx/components/nvidia/__init__.py
  • src/lfx/src/lfx/components/nvidia/nvidia.py
  • src/lfx/src/lfx/components/nvidia/nvidia_embedding.py
  • src/lfx/src/lfx/components/nvidia/nvidia_ingest.py
  • src/lfx/src/lfx/components/nvidia/nvidia_rerank.py
  • src/lfx/src/lfx/components/nvidia/system_assist.py
  • src/lfx/src/lfx/components/olivya/__init__.py
  • src/lfx/src/lfx/components/olivya/olivya.py
  • src/lfx/src/lfx/components/ollama/__init__.py
  • src/lfx/src/lfx/components/ollama/ollama.py
  • src/lfx/src/lfx/components/ollama/ollama_embeddings.py
  • src/lfx/src/lfx/components/perplexity/__init__.py
  • src/lfx/src/lfx/components/perplexity/perplexity.py
  • src/lfx/src/lfx/components/pinecone/__init__.py
  • src/lfx/src/lfx/components/pinecone/pinecone.py
  • src/lfx/src/lfx/components/qdrant/__init__.py
  • src/lfx/src/lfx/components/qdrant/qdrant.py
  • src/lfx/src/lfx/components/sambanova/__init__.py
  • src/lfx/src/lfx/components/sambanova/sambanova.py
  • src/lfx/src/lfx/components/scrapegraph/__init__.py
  • src/lfx/src/lfx/components/scrapegraph/scrapegraph_markdownify_api.py
  • src/lfx/src/lfx/components/scrapegraph/scrapegraph_search_api.py
  • src/lfx/src/lfx/components/scrapegraph/scrapegraph_smart_scraper_api.py
  • src/lfx/src/lfx/components/searchapi/__init__.py
  • src/lfx/src/lfx/components/searchapi/search.py
  • src/lfx/src/lfx/components/serpapi/__init__.py
  • src/lfx/src/lfx/components/serpapi/serp.py
  • src/lfx/src/lfx/components/supabase/__init__.py
  • src/lfx/src/lfx/components/supabase/supabase.py
  • src/lfx/src/lfx/components/twelvelabs/__init__.py
  • src/lfx/src/lfx/components/twelvelabs/convert_astra_results.py
  • src/lfx/src/lfx/components/twelvelabs/pegasus_index.py
  • src/lfx/src/lfx/components/twelvelabs/split_video.py
  • src/lfx/src/lfx/components/twelvelabs/text_embeddings.py
  • src/lfx/src/lfx/components/twelvelabs/twelvelabs_pegasus.py
  • src/lfx/src/lfx/components/twelvelabs/video_embeddings.py
  • src/lfx/src/lfx/components/twelvelabs/video_file.py
  • src/lfx/src/lfx/components/unstructured/__init__.py
  • src/lfx/src/lfx/components/unstructured/unstructured.py
  • src/lfx/src/lfx/components/upstash/__init__.py
  • src/lfx/src/lfx/components/upstash/upstash.py
  • src/lfx/src/lfx/components/vectara/__init__.py
  • src/lfx/src/lfx/components/vectara/vectara.py
  • src/lfx/src/lfx/components/vectara/vectara_rag.py
  • src/lfx/src/lfx/components/vertexai/__init__.py
  • src/lfx/src/lfx/components/vertexai/vertexai.py
  • src/lfx/src/lfx/components/vertexai/vertexai_embeddings.py
  • src/lfx/src/lfx/components/vlmrun/__init__.py
  • src/lfx/src/lfx/components/vlmrun/vlmrun_transcription.py
  • src/lfx/src/lfx/components/weaviate/__init__.py
  • src/lfx/src/lfx/components/weaviate/weaviate.py
  • src/lfx/src/lfx/components/wikipedia/__init__.py
  • src/lfx/src/lfx/components/wikipedia/wikidata.py
  • src/lfx/src/lfx/components/wikipedia/wikipedia.py
  • src/lfx/src/lfx/components/wolframalpha/__init__.py
  • src/lfx/src/lfx/components/wolframalpha/wolfram_alpha_api.py
  • src/lfx/src/lfx/components/xai/__init__.py
  • src/lfx/src/lfx/components/xai/xai.py
  • src/lfx/src/lfx/components/yahoosearch/__init__.py
  • src/lfx/src/lfx/components/yahoosearch/yahoo.py
  • src/lfx/src/lfx/components/youtube/__init__.py
  • src/lfx/src/lfx/components/youtube/channel.py
  • src/lfx/src/lfx/components/youtube/comments.py
  • src/lfx/src/lfx/components/youtube/playlist.py
  • src/lfx/src/lfx/components/youtube/search.py
  • src/lfx/src/lfx/components/youtube/trending.py
  • src/lfx/src/lfx/components/youtube/video_details.py
  • src/lfx/src/lfx/components/youtube/youtube_transcripts.py
  • src/lfx/src/lfx/components/zep/__init__.py
  • src/lfx/src/lfx/components/zep/zep.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@github-actions github-actions Bot added community Pull Request from an external contributor enhancement New feature or request labels Mar 28, 2026
@github-actions github-actions Bot added enhancement New feature or request and removed enhancement New feature or request labels Mar 28, 2026
@YeonghyeonKO
Copy link
Copy Markdown
Author

Wrong repository - this PR was unintentionally opened against the upstream repo. The intended PR is at YeonghyeonKO#5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Pull Request from an external contributor enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant