Skip to content

feat: sdk scripts#1848

Merged
edwinjosechittilappilly merged 10 commits into
mainfrom
sdk-scripts
Jun 12, 2026
Merged

feat: sdk scripts#1848
edwinjosechittilappilly merged 10 commits into
mainfrom
sdk-scripts

Conversation

@edwinjosechittilappilly

@edwinjosechittilappilly edwinjosechittilappilly commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

feat: sdk scripts

Summary by CodeRabbit

  • New Features

    • Added a standalone Python smoke-test runner for OpenRAG SaaS with end-to-end suites for settings, models, documents, search, chat, knowledge filters, and error handling; per-check reporting, cleanup, and exit codes.
  • Tests

    • Added comprehensive async checks covering ingest, search, chat (streaming & multi-turn), filters CRUD/scoping, models listing, settings, and error scenarios; ordered suites and dependency handling.
  • Documentation

    • Added README and example env configuration plus gitignore guidance for running the smoke tests.

@github-actions github-actions Bot added the enhancement 🔵 New feature or request label Jun 11, 2026
Comment thread scripts/test_scripts/sdk/python/main.py Fixed
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9028ec67-44c6-4a8d-90c5-22bbd20ea4d1

📥 Commits

Reviewing files that changed from the base of the PR and between 209a19d and 83afdd1.

📒 Files selected for processing (1)
  • scripts/test_scripts/sdk/python/main.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/test_scripts/sdk/python/main.py

Walkthrough

This PR adds a standalone Python SDK smoke-test runner for testing OpenRAG SaaS deployments. The implementation includes project configuration, async test harness, CLI entry point with reporting, a suite registry, shared test helpers, and ordered check suites covering settings, models, documents, search, chat, filters, and error scenarios.

Changes

Python SDK Smoke-Test Runner

Layer / File(s) Summary
Project setup and documentation
scripts/test_scripts/sdk/python/.env.example, .gitignore, pyproject.toml, README.md
Project configuration specifying Python ≥3.10 and openrag-sdk ≥0.3.1 dependencies. Example .env with credentials, .gitignore for environment artifacts. Comprehensive README documenting setup, CLI/env credential precedence, full vs. filtered suite runs, end-to-end check order, preflight behavior, cleanup on exit, report artifacts (JSON/MD with metadata), and exit codes.
Suite registry and wiring
scripts/test_scripts/sdk/python/checks/__init__.py
Package initializer importing all per-suite check modules (settings, models, documents, search, chat, filters, errors) and exporting ALL_SUITES as ordered (name, CHECKS) pairs plus derived SUITE_NAMES for CLI --only filtering.
Shared test helpers
scripts/test_scripts/sdk/python/checks/common.py
Utility functions: supports_delete_by_filter_id() via signature inspection, make_doc() creating UUID-embedded markdown files in tmpdir, register_doc_cleanup() scheduling best-effort document deletion via ctx.add_cleanup().
Async harness framework
scripts/test_scripts/sdk/python/harness.py (lines 1–144)
Core harness: PASS/FAIL/SKIP status constants, Skip exception, Check/CheckResult/Context dataclasses. Context.add_cleanup() registers async cleanup callbacks. run_suites() sequentially executes checks, auto-skips unmet dependencies, times execution, records outcomes including limited tracebacks, and executes cleanup in LIFO order with guaranteed execution in finally block. Console formatting helpers for TTY-aware colored status output.
Reporting and CLI entry point
scripts/test_scripts/sdk/python/harness.py (lines 145–244), main.py
Report generation: mask_api_key(), mask_username(), SDK version detection via importlib.metadata, summarize() aggregation, write_reports() producing timestamped JSON and Markdown outputs with per-check tables and failure details. load_dotenv() minimal ENV loader respecting existing variables. parse_config() CLI argument parsing with .env fallback, URL normalization, and suite validation. Preflight settings.get() check (non-fatal unless unreachable). Async amain() runner filtering suites, executing via run_suites(), writing reports, and returning exit codes (0 pass, 1 failures, 2 unreachable). Synchronous main() entrypoint with log teeing, ANSI stripping, KeyboardInterrupt handling, and stdout/stderr restoration.
Settings and models baseline checks
scripts/test_scripts/sdk/python/checks/check_settings.py, check_models.py
Settings: get() retrieves and asserts agent/knowledge presence; update_roundtrip() reads chunk_size, updates, and re-reads for assertion. Models: per-provider factory generating checks for OpenAI, Anthropic, Ollama, Watsonx; converts OpenRAGError to Skip (provider unavailable), asserts language_models/embedding_models are lists.
Documents and search checks
scripts/test_scripts/sdk/python/checks/check_documents.py, check_search.py
Documents: ingest via file path/async poll/file object; re-ingest same filename; delete by filename with success/failure assertion; delete missing filename idempotently; delete by filter_id (capability-gated, ingests two docs, creates scoped filter, asserts correct inclusions). Search: query_basic() retries with delay until results, raises Skip if none; query_limit(), query_score_threshold(), query_no_results(), query_unicode() assertion patterns. Search checks depend on documents.ingest_wait.
Chat, filters, and error checks
scripts/test_scripts/sdk/python/checks/check_chat.py, check_filters.py, check_errors.py
Chat: non-streaming/streaming/context-manager creation storing chat_id in shared context; multi-turn continuity; list/get/delete operations with dependency ordering (list/get after create_nonstream). Filters: crud() creates unique filter, verifies search/retrieval, updates, deletes; scope_setup() ingests alpha/beta docs, creates filter scoped to alpha, stores ids; filter_id_in_search() and filter_id_in_chat() verify beta exclusion (depend on scope_setup). Errors: missing conversation (NotFoundError), delete missing (False), invalid settings (OpenRAGError), missing ingest args (ValueError), bogus filter_id (OpenRAGError), conditional dual-parameter deletion (ValueError/Skip).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • langflow-ai/openrag#1666: Adds Python SDK smoke-test checks for filter_id scoping (documents deletion by filter_id, chat/search scoping, error cases), directly exercising backend/SDK support for filter_id across v1 endpoints.

Suggested reviewers

  • mfortman11
  • phact
  • lucaseduoli
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'feat: sdk scripts' is vague and doesn't convey meaningful information about the changeset; it uses a generic term 'scripts' that could refer to any kind of script addition. Use a more specific title that describes the main purpose, such as 'feat: add OpenRAG SDK smoke-test suite for remote deployments' to clearly communicate the changeset's primary contribution.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sdk-scripts

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 enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/test_scripts/sdk/python/checks/check_chat.py`:
- Around line 48-51: Move the call to _register_chat_cleanup(ctx,
stream.chat_id) so it runs as soon as stream.chat_id is available (i.e.,
immediately after the stream yields/sets chat_id) and before the other
assertions; ensure you only call _register_chat_cleanup after confirming
stream.chat_id is not None (so check/guard for chat_id first), then perform the
remaining asserts on collected and stream.text in the same scope (function/check
in check_chat.py).

In `@scripts/test_scripts/sdk/python/checks/check_documents.py`:
- Around line 68-78: Register the created file for cleanup right after make_doc
by calling register_doc_cleanup(ctx, path) so the document is removed even if
later assertions fail; in delete_by_filename, add that registration before
calling ctx.client.documents.ingest, and then simplify the post-ingest
assertions by removing the unreachable else branch (assume ingest succeeded or
raised), keeping the delete call (ctx.client.documents.delete) and asserting
result.success is True and result.deleted_chunks > 0.

In `@scripts/test_scripts/sdk/python/checks/check_errors.py`:
- Around line 25-30: Narrow the exception handling in invalid_settings_value and
the bogus filter_id checks to catch ValidationError instead of any OpenRAGError:
replace the broad except OpenRAGError with except ValidationError to mark the
test as passing, and if a different OpenRAGError is raised, re-raise or fail the
test (i.e., let non-ValidationError OpenRAGError propagate or explicitly raise
an AssertionError), referencing the invalid_settings_value function and the
bogus filter_id test blocks so the checks only accept HTTP 400/validation
failures.

In `@scripts/test_scripts/sdk/python/checks/check_filters.py`:
- Around line 61-63: scope_setup currently calls ctx.client.documents.ingest
twice without waiting for index readiness, causing filters.filter_id_in_search
and filters.filter_id_in_chat to run against non-searchable docs; after calling
ctx.client.documents.ingest (either after each ingest or once after both), add a
readiness sync step — e.g., call the client’s document-ready or
wait-for-indexing API or poll search until the ingested documents are
discoverable — before returning from scope_setup so the subsequent scoped checks
are deterministic.
- Around line 94-100: The current filter checks (e.g., filter_id_in_search) only
assert that the out-of-scope file ("beta") is not present, which can pass when
the search returns no results; update these functions to also assert that the
expected in-scope file ("alpha") is actually returned. In filter_id_in_search
(and the analogous function around lines 102-117), after asserting
results.results is not None, add a positive assertion that at least one result
has filename == scope["alpha"] (with a clear failure message), and keep the
existing negative assertion for scope["beta"]; this ensures the filter both
includes expected in-scope evidence and excludes out-of-scope items.

In `@scripts/test_scripts/sdk/python/checks/check_models.py`:
- Around line 14-16: The except block catching OpenRAGError in check_models.py
turns all provider errors into Skip; change it to only convert to Skip when the
error indicates credentials not configured by checking e.status_code == 400 and
include the provider in the message, otherwise re-raise the original
OpenRAGError so 401/403/5xx failures surface; update the except OpenRAGError as
e handler to conditionally raise Skip(...) from e only for e.status_code == 400
and use plain raise for other status codes.

In `@scripts/test_scripts/sdk/python/checks/check_settings.py`:
- Around line 13-18: The current "no-op" roundtrip in update_roundtrip can
mutate shared state because chunk_size is set to 1000 when
current.knowledge.chunk_size is falsy; instead, read current via
ctx.client.settings.get() and only include "chunk_size" in the payload passed to
ctx.client.settings.update(...) when current.knowledge.chunk_size is explicitly
set (not None/falsy). Update the logic around variables current and chunk_size
so that if current.knowledge.chunk_size is None/absent you call update with an
empty payload (or omit the chunk_size key) to avoid changing the deployment
config.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a9b0275a-4def-480b-9970-6f4ae014aa25

📥 Commits

Reviewing files that changed from the base of the PR and between 453ebdc and 53ea436.

⛔ Files ignored due to path filters (1)
  • scripts/test_scripts/sdk/python/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (15)
  • scripts/test_scripts/sdk/python/.env.example
  • scripts/test_scripts/sdk/python/.gitignore
  • scripts/test_scripts/sdk/python/README.md
  • scripts/test_scripts/sdk/python/checks/__init__.py
  • scripts/test_scripts/sdk/python/checks/check_chat.py
  • scripts/test_scripts/sdk/python/checks/check_documents.py
  • scripts/test_scripts/sdk/python/checks/check_errors.py
  • scripts/test_scripts/sdk/python/checks/check_filters.py
  • scripts/test_scripts/sdk/python/checks/check_models.py
  • scripts/test_scripts/sdk/python/checks/check_search.py
  • scripts/test_scripts/sdk/python/checks/check_settings.py
  • scripts/test_scripts/sdk/python/checks/common.py
  • scripts/test_scripts/sdk/python/harness.py
  • scripts/test_scripts/sdk/python/main.py
  • scripts/test_scripts/sdk/python/pyproject.toml

Comment on lines +48 to +51
assert collected, "text_stream yielded no text"
assert stream.text, "stream.text not accumulated"
assert stream.chat_id is not None, "stream.chat_id not populated after iteration"
_register_chat_cleanup(ctx, stream.chat_id)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Register chat cleanup before assertions in the stream context-manager check.

Cleanup is registered only after assertions. If one of those assertions fails, the conversation can be left behind. Register cleanup immediately after stream.chat_id is available, then run assertions.

Suggested patch
 async def stream_context_manager(ctx: Context) -> None:
     async with ctx.client.chat.stream(
         message="Say 'hello' and nothing else."
     ) as stream:
         collected = ""
         async for text in stream.text_stream:
             collected += text
-        assert collected, "text_stream yielded no text"
-        assert stream.text, "stream.text not accumulated"
-        assert stream.chat_id is not None, "stream.chat_id not populated after iteration"
-        _register_chat_cleanup(ctx, stream.chat_id)
+        assert stream.chat_id is not None, "stream.chat_id not populated after iteration"
+        _register_chat_cleanup(ctx, stream.chat_id)
+        assert collected, "text_stream yielded no text"
+        assert stream.text, "stream.text not accumulated"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert collected, "text_stream yielded no text"
assert stream.text, "stream.text not accumulated"
assert stream.chat_id is not None, "stream.chat_id not populated after iteration"
_register_chat_cleanup(ctx, stream.chat_id)
async def stream_context_manager(ctx: Context) -> None:
async with ctx.client.chat.stream(
message="Say 'hello' and nothing else."
) as stream:
collected = ""
async for text in stream.text_stream:
collected += text
assert stream.chat_id is not None, "stream.chat_id not populated after iteration"
_register_chat_cleanup(ctx, stream.chat_id)
assert collected, "text_stream yielded no text"
assert stream.text, "stream.text not accumulated"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_chat.py` around lines 48 - 51,
Move the call to _register_chat_cleanup(ctx, stream.chat_id) so it runs as soon
as stream.chat_id is available (i.e., immediately after the stream yields/sets
chat_id) and before the other assertions; ensure you only call
_register_chat_cleanup after confirming stream.chat_id is not None (so
check/guard for chat_id first), then perform the remaining asserts on collected
and stream.text in the same scope (function/check in check_chat.py).

Comment thread scripts/test_scripts/sdk/python/checks/check_documents.py
Comment on lines +25 to +30
async def invalid_settings_value(ctx: Context) -> None:
try:
await ctx.client.settings.update({"chunk_size": -999999})
except OpenRAGError:
return
raise AssertionError("invalid settings value did not raise OpenRAGError")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the relevant portion of the file under review
sed -n '1,140p' scripts/test_scripts/sdk/python/checks/check_errors.py | nl -ba | sed -n '1,140p'

# 2) Locate where OpenRAGError / ValidationError are defined or mapped in the repo
echo "---- Searching for exception definitions ----"
rg -n "class ValidationError|ValidationError\(" -S . || true
rg -n "class OpenRAGError|OpenRAGError\(" -S . || true
rg -n "status[_-]?code.*400|400.*ValidationError|ValidationError.*400|404.*NotFoundError|NotFoundError.*404" -S . || true

# 3) Show where the checks are registered / invoked (so we understand harness expectations)
rg -n "CHECKS|invalid_settings_value|bogus_filter_id_in_search|bogus_filter_id_in_chat" -S scripts/test_scripts/sdk/python/checks/check_errors.py || true

# 4) If SDK package exists in repo, search for openrag_sdk.exceptions mapping
rg -n "openrag_sdk\.exceptions" -S . | head -n 50 || true

Repository: langflow-ai/openrag

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the relevant portion of the file under review
sed -n '1,140p' scripts/test_scripts/sdk/python/checks/check_errors.py | nl -ba | sed -n '1,140p'

# 2) Locate where OpenRAGError / ValidationError are defined or mapped in the repo
echo "---- Searching for exception definitions ----"
rg -n "class ValidationError|ValidationError\(" -S . || true
rg -n "class OpenRAGError|OpenRAGError\(" -S . || true
rg -n "status[_-]?code.*400|400.*ValidationError|ValidationError.*400|404.*NotFoundError|NotFoundError.*404" -S . || true

# 3) Show where the checks are registered / invoked (so we understand harness expectations)
rg -n "CHECKS|invalid_settings_value|bogus_filter_id_in_search|bogus_filter_id_in_chat" -S scripts/test_scripts/sdk/python/checks/check_errors.py || true

# 4) If SDK package exists in repo, search for openrag_sdk.exceptions mapping
rg -n "openrag_sdk\.exceptions" -S . | head -n 50 || true

Repository: langflow-ai/openrag

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show relevant portion with line numbers from sed (no `nl`)
echo "---- check_errors.py lines 1-140 ----"
sed -n '1,140p' scripts/test_scripts/sdk/python/checks/check_errors.py | cat -n | sed -n '1,140p'

# 2) Locate where OpenRAGError / ValidationError are defined or mapped in the repo
echo "---- Searching for exception definitions/mappings ----"
rg -n "class ValidationError|ValidationError\(" -S . || true
rg -n "class OpenRAGError|OpenRAGError\(" -S . || true
rg -n "status[_-]?code.*400|400.*ValidationError|ValidationError.*400|404.*NotFoundError|NotFoundError.*404" -S . || true

# 3) Show where the checks are registered / invoked
echo "---- Searching for check functions/registry in check_errors.py ----"
rg -n "CHECKS|invalid_settings_value|bogus_filter_id_in_search|bogus_filter_id_in_chat" -S scripts/test_scripts/sdk/python/checks/check_errors.py || true

# 4) If SDK package exists in repo, search for openrag_sdk.exceptions mapping usage
echo "---- Searching for openrag_sdk.exceptions usage ----"
rg -n "openrag_sdk\.exceptions" -S . | head -n 50 || true

Repository: langflow-ai/openrag

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Small, targeted excerpts (line-numbered where possible without `nl`)
echo "---- sdks/python/openrag_sdk/exceptions.py (1-120) ----"
sed -n '1,160p' sdks/python/openrag_sdk/exceptions.py | cat -n

echo "---- sdks/python/openrag_sdk/client.py (180-280) ----"
sed -n '180,280p' sdks/python/openrag_sdk/client.py | cat -n

echo "---- check_errors.py (20-90) ----"
sed -n '20,95p' scripts/test_scripts/sdk/python/checks/check_errors.py | cat -n

Repository: langflow-ai/openrag

Length of output: 7077


Tighten expected exception type in SDK error checks to avoid false positives

invalid_settings_value (25-30) and the bogus filter_id checks (59-66, 69-76) currently treat any OpenRAGError as success, which can mask auth/rate-limit/server failures. The SDK maps HTTP 400 to ValidationError; narrow these checks to ValidationError (and fail if a different OpenRAGError is raised).

Proposed fix
-from openrag_sdk.exceptions import NotFoundError, OpenRAGError
+from openrag_sdk.exceptions import NotFoundError, OpenRAGError, ValidationError
@@
 async def invalid_settings_value(ctx: Context) -> None:
     try:
         await ctx.client.settings.update({"chunk_size": -999999})
-    except OpenRAGError:
+    except ValidationError:
         return
+    except OpenRAGError as e:
+        raise AssertionError(
+            f"expected ValidationError, got {type(e).__name__}: {e}"
+        ) from e
     raise AssertionError("invalid settings value did not raise OpenRAGError")
@@
 async def bogus_filter_id_in_search(ctx: Context) -> None:
     try:
         await ctx.client.search.query(
             "anything", filter_id=f"does-not-exist-{uuid.uuid4().hex}"
         )
-    except OpenRAGError:
+    except ValidationError:
         return
+    except OpenRAGError as e:
+        raise AssertionError(
+            f"expected ValidationError, got {type(e).__name__}: {e}"
+        ) from e
     raise AssertionError("search with a bogus filter_id did not raise OpenRAGError")
@@
 async def bogus_filter_id_in_chat(ctx: Context) -> None:
     try:
         await ctx.client.chat.create(
             message="hi", filter_id=f"does-not-exist-{uuid.uuid4().hex}"
         )
-    except OpenRAGError:
+    except ValidationError:
         return
+    except OpenRAGError as e:
+        raise AssertionError(
+            f"expected ValidationError, got {type(e).__name__}: {e}"
+        ) from e
     raise AssertionError("chat with a bogus filter_id did not raise OpenRAGError")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_errors.py` around lines 25 - 30,
Narrow the exception handling in invalid_settings_value and the bogus filter_id
checks to catch ValidationError instead of any OpenRAGError: replace the broad
except OpenRAGError with except ValidationError to mark the test as passing, and
if a different OpenRAGError is raised, re-raise or fail the test (i.e., let
non-ValidationError OpenRAGError propagate or explicitly raise an
AssertionError), referencing the invalid_settings_value function and the bogus
filter_id test blocks so the checks only accept HTTP 400/validation failures.

Comment on lines +61 to +63
await ctx.client.documents.ingest(file_path=str(alpha))
await ctx.client.documents.ingest(file_path=str(beta))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

scope_setup ingests documents without readiness sync, making scoped checks flaky.

The setup immediately proceeds after ingest. If indexing is async, filters.filter_id_in_search and filters.filter_id_in_chat can run before docs are searchable, causing nondeterministic outcomes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_filters.py` around lines 61 -
63, scope_setup currently calls ctx.client.documents.ingest twice without
waiting for index readiness, causing filters.filter_id_in_search and
filters.filter_id_in_chat to run against non-searchable docs; after calling
ctx.client.documents.ingest (either after each ingest or once after both), add a
readiness sync step — e.g., call the client’s document-ready or
wait-for-indexing API or poll search until the ingested documents are
discoverable — before returning from scope_setup so the subsequent scoped checks
are deterministic.

Comment on lines +94 to +100
async def filter_id_in_search(ctx: Context) -> None:
scope = ctx.shared["scope"]
results = await ctx.client.search.query("animals", filter_id=scope["filter_id"])
assert results.results is not None
leaked = [r.filename for r in results.results if r.filename == scope["beta"]]
assert not leaked, f"filter leaked: search returned out-of-scope file {leaked}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Scoped filter checks can pass vacuously; add positive in-scope assertions.

Both checks only verify that out-of-scope (beta) is absent. They still pass when retrieval is empty or broken. Add assertions that in-scope (alpha) evidence is actually returned.

Suggested patch
 async def filter_id_in_search(ctx: Context) -> None:
     scope = ctx.shared["scope"]
     results = await ctx.client.search.query("animals", filter_id=scope["filter_id"])
     assert results.results is not None
+    assert len(results.results) > 0, "scoped search returned no results"
+    filenames = [r.filename for r in results.results]
+    assert scope["alpha"] in filenames, (
+        f"scoped search did not return expected in-scope file {scope['alpha']}: {filenames}"
+    )
-    leaked = [r.filename for r in results.results if r.filename == scope["beta"]]
+    leaked = [name for name in filenames if name == scope["beta"]]
     assert not leaked, f"filter leaked: search returned out-of-scope file {leaked}"
@@
 async def filter_id_in_chat(ctx: Context) -> None:
     scope = ctx.shared["scope"]
     response = await ctx.client.chat.create(
         message="What animals appear in these documents?",
         filter_id=scope["filter_id"],
@@
-    assert response.sources is not None
+    assert response.sources is not None, "chat returned no sources collection"
+    assert len(response.sources) > 0, "scoped chat returned no sources"
     source_names = [s.filename for s in response.sources]
+    assert scope["alpha"] in source_names, (
+        f"scoped chat did not cite expected in-scope file {scope['alpha']}: {source_names}"
+    )
     assert scope["beta"] not in source_names, (
         f"filter leaked: chat cited out-of-scope file in {source_names}"
     )

Also applies to: 102-117

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_filters.py` around lines 94 -
100, The current filter checks (e.g., filter_id_in_search) only assert that the
out-of-scope file ("beta") is not present, which can pass when the search
returns no results; update these functions to also assert that the expected
in-scope file ("alpha") is actually returned. In filter_id_in_search (and the
analogous function around lines 102-117), after asserting results.results is not
None, add a positive assertion that at least one result has filename ==
scope["alpha"] (with a clear failure message), and keep the existing negative
assertion for scope["beta"]; this ensures the filter both includes expected
in-scope evidence and excludes out-of-scope items.

Comment on lines +14 to +16
except OpenRAGError as e:
# SaaS deployments typically enable only a subset of providers.
raise Skip(f"provider '{provider}' not available: {e}") from e

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the target file and show the relevant section
FILE="scripts/test_scripts/sdk/python/checks/check_models.py"
echo "=== Target snippet ($FILE) ==="
nl -ba "$FILE" | sed -n '1,120p'

# Search for OpenRAGError definition and any mention of status_code/provider-unavailable semantics
echo
echo "=== Search for OpenRAGError definition ==="
rg -n "class OpenRAGError|OpenRAGError\(" -S . | head -n 50

# If OpenRAGError is in a Python package, locate it
echo
echo "=== Search for 'status_code' on OpenRAGError ==="
rg -n "OpenRAGError.*status_code|status_code.*OpenRAGError|def .*status_code" -S . | head -n 100

# Find all occurrences of 'provider.*not available' or Skip usage patterns
echo
echo "=== Search for Skip(...) related to provider availability ==="
rg -n "Skip\\(.*provider|provider.*not available|not available: \\{e\\}" -S . | head -n 100

# Show any other Skip conversions from OpenRAGError near similar code
echo
echo "=== Search for 'except OpenRAGError' blocks ==="
rg -n "except OpenRAGError" -S . | head -n 100

Repository: langflow-ai/openrag

Length of output: 204


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="scripts/test_scripts/sdk/python/checks/check_models.py"

echo "=== Target snippet ($FILE) ==="
# Prefer cat -n (available in most environments); fallback to awk for line numbers
if command -v cat >/dev/null 2>&1; then
  cat -n "$FILE" | sed -n '1,160p'
else
  awk 'NR<=160{printf "%5d\t%s\n", NR, $0}' "$FILE"
fi

echo
echo "=== Search for OpenRAGError definition and constructor usage ==="
rg -n "class OpenRAGError|def __init__\(.*OpenRAGError|OpenRAGError\(" -S . | head -n 80

echo
echo "=== Search for status_code references near OpenRAGError ==="
rg -n "status_code" -S . | head -n 120

echo
echo "=== Search for provider-not-available / Skip patterns ==="
rg -n "Skip\\(.*provider|provider.*not available|not available: \\{e\\}|except OpenRAGError" -S scripts/test_scripts/sdk/python/checks . | head -n 120

Repository: langflow-ai/openrag

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== OpenRAGError exception definition ==="
FILE="sdks/python/openrag_sdk/exceptions.py"
rg -n "class OpenRAGError" "$FILE"
start=$(rg -n "class OpenRAGError" "$FILE" | head -n1 | cut -d: -f1)
end=$((start+120))
sed -n "${start},${end}p" "$FILE" | cat -n

echo
echo "=== Where OpenRAGError is raised with status_code ==="
FILE="sdks/python/openrag_sdk/client.py"
rg -n "raise OpenRAGError\\(.*status_code|raise OpenRAGError" "$FILE"
# show a small window around the first match
line=$(rg -n "raise OpenRAGError\\(.*status_code|raise OpenRAGError" "$FILE" | head -n1 | cut -d: -f1)
start=$((line-40))
end=$((line+60))
sed -n "${start},${end}p" "$FILE" | cat -n

echo
echo "=== check_errors.py existing handling of OpenRAGError ==="
FILE="scripts/test_scripts/sdk/python/checks/check_errors.py"
if [ -f "$FILE" ]; then
  rg -n "except OpenRAGError" "$FILE"
  # show around each match
  rg -n "except OpenRAGError" "$FILE" | cut -d: -f1 | while read -r ln; do
    start=$((ln-10)); end=$((ln+25));
    echo "--- context around line $ln ---"
    sed -n "${start},${end}p" "$FILE" | cat -n
    echo
  done
else
  echo "File not found: $FILE"
fi

Repository: langflow-ai/openrag

Length of output: 7839


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for endpoint/handler for listing models per provider
rg -n "models\\.list|list\\(provider\\)|/models|models\\b.*provider|provider.*models" src sdks plugins scripts tests -S --hidden 2>/dev/null | head -n 200

# Specifically find where "provider" is used in a models route
rg -n "provider.*models|models.*provider" src -S --hidden 2>/dev/null | head -n 200

# Find routes mentioning "models" and "provider"
rg -n "APIRouter|router\\.|@.*models|/models" src -S --hidden 2>/dev/null | head -n 200

Repository: langflow-ai/openrag

Length of output: 13291


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/api/v1/models.py"
echo "=== File header (first 140 lines) ==="
sed -n '1,140p' "$FILE" | cat -n

echo
echo "=== Search for list_models_endpoint and provider-not-available handling ==="
rg -n "list_models_endpoint|_fetch_models|enabled|not available|unavailable|disabled|Skip|HTTPException|status_code|404|400|403" "$FILE" -S

# Print the main endpoint function region
# (Try to cover from near list_models_endpoint declaration down ~120 lines)
line=$(rg -n "def list_models_endpoint" "$FILE" | head -n1 | cut -d: -f1)
start=$((line-20)); end=$((line+140))
echo
echo "=== Around list_models_endpoint (lines $start-$end) ==="
sed -n "${start},${end}p" "$FILE" | cat -n

# Print the _fetch_models helper region
line=$(rg -n "async def _fetch_models" "$FILE" | head -n1 | cut -d: -f1)
start=$((line-20)); end=$((line+160))
echo
echo "=== Around _fetch_models (lines $start-$end) ==="
sed -n "${start},${end}p" "$FILE" | cat -n

Repository: langflow-ai/openrag

Length of output: 11627


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Inspect sdks/python/openrag_sdk/models.py list() implementation ==="
FILE="sdks/python/openrag_sdk/models.py"
rg -n "class Models|async def list|models\\.list" "$FILE"
line=$(rg -n "async def list" "$FILE" | head -n1 | cut -d: -f1)
start=$((line-40)); end=$((line+140))
sed -n "${start},${end}p" "$FILE" | cat -n

echo
echo "=== Inspect scripts/test_scripts/sdk/python/README.md (models section) ==="
FILE="scripts/test_scripts/sdk/python/README.md"
# print around the models row/description
rg -n "models\\b|unavailable providers" "$FILE" | head -n 50
line=$(rg -n "\\|\\s*`models`|models\\s+\\|" "$FILE" | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-10)); end=$((line+20))
  sed -n "${start},${end}p" "$FILE" | cat -n
fi

Repository: langflow-ai/openrag

Length of output: 172


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="sdks/python/openrag_sdk/models.py"
echo "=== File exists? ==="
ls -l "$FILE" || true

echo
echo "=== Search within models.py for v1/models or list method ==="
rg -n "\"/v1/models/\\{provider\\}\"|/api/v1/models/\\{provider\\}|models\\.list\\(|def list\\b|async def list\\b|list_models|list_\\w*models" "$FILE" -S

echo
echo "=== Print relevant region around any list_...models function ==="
# Try common candidates
for pat in "list_models" "list_" "models" ; do
  line=$(rg -n "${pat}" "$FILE" | head -n1 | cut -d: -f1 || true)
  if [ -n "${line:-}" ]; then
    start=$((line-40)); end=$((line+160));
    echo "--- candidate pattern '${pat}' at line ${line}: showing ${start}-${end} ---"
    sed -n "${start},${end}p" "$FILE" | cat -n
    break
  fi
done

echo
echo "=== Show top of models.py (first 260 lines) ==="
sed -n '1,260p' "$FILE" | cat -n

Repository: langflow-ai/openrag

Length of output: 229


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for /api/v1/models/{provider} usage in Python SDK ==="
rg -n "\"/api/v1/models/\\{provider\\}\"|/api/v1/models/\\{provider\\}|models/\\{provider\\}\" -S sdks/python/openrag_sdk | head -n 50

echo
echo "=== Search for list_models method implementation ==="
rg -n "list_models|models\\.list|def list\\(|async def list\\(|class Models" -S sdks/python/openrag_sdk | head -n 100

echo
echo "=== Inspect sdks/python/openrag_sdk/client.py around models listing ==="
FILE="sdks/python/openrag_sdk/client.py"
# find the line that contains the endpoint string (best effort)
line=$(rg -n "/api/v1/models/\\{provider\\}" "$FILE" | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-60)); end=$((line+80))
  sed -n "${start},${end}p" "$FILE" | cat -n
else
  # fallback: show the section containing "models" methods
  rg -n "class Models|def models|async def list|models\\b" "$FILE" | head -n 30
fi

echo
echo "=== Inspect tests/integration/sdk/test_models.py ==="
FILE="tests/integration/sdk/test_models.py"
sed -n '1,200p' "$FILE" | cat -n

echo
echo "=== Inspect scripts/test_scripts/sdk/python/README.md models row ==="
FILE="scripts/test_scripts/sdk/python/README.md"
rg -n "models`|unavailable providers|models\\b.*unavailable" "$FILE" -n -S || true

Repository: langflow-ai/openrag

Length of output: 208


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for models endpoint string in Python SDK ==="
rg -n "/api/v1/models/" -S sdks/python/openrag_sdk | head -n 50

echo
echo "=== Search for Models client class/methods in Python SDK ==="
rg -n "class Models|def list|def.*models|async def" -S sdks/python/openrag_sdk | head -n 120

echo
echo "=== Inspect sdks/python/openrag_sdk/client.py around first models endpoint usage ==="
FILE="sdks/python/openrag_sdk/client.py"
line=$(rg -n "/api/v1/models/" "$FILE" -S | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-80)); end=$((line+80))
  sed -n "${start},${end}p" "$FILE" | cat -n
else
  echo "No /api/v1/models/ usage found in $FILE"
fi

echo
echo "=== Inspect sdks/python/openrag_sdk/client.py Models method block (fallback) ==="
rg -n "class Models|models\\b|list\\(" "$FILE" -S | head -n 40

echo
echo "=== Inspect tests/integration/sdk/test_models.py ==="
FILE="tests/integration/sdk/test_models.py"
sed -n '1,200p' "$FILE" | cat -n

echo
echo "=== Inspect scripts/test_scripts/sdk/python/README.md around models row/description ==="
FILE="scripts/test_scripts/sdk/python/README.md"
rg -n "models\\b|unavailable providers" -S "$FILE" | head -n 80
line=$(rg -n "models\\b" "$FILE" -S | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-10)); end=$((line+30))
  sed -n "${start},${end}p" "$FILE" | cat -n
fi

Repository: langflow-ai/openrag

Length of output: 4722


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect sdks/python/openrag_sdk/client.py around ModelsClient.list and request error handling
FILE="sdks/python/openrag_sdk/client.py"
echo "=== client.py: first 120 lines ==="
sed -n '1,120p' "$FILE" | cat -n

echo
echo "=== client.py: around ModelsClient.list (search hit line) ==="
line=$(rg -n "class ModelsClient|async def list\\(self, provider" "$FILE" | head -n1 | cut -d: -f1)
start=1
end=$((line+120))
sed -n "${start},${end}p" "$FILE" | cat -n

echo
echo "=== client.py: around _request/_handle_error mapping ==="
# show section containing _handle_error (already saw earlier, but re-show bounded)
line=$(rg -n "def _handle_error" "$FILE" | head -n1 | cut -d: -f1)
start=$((line-40)); if [ $start -lt 1 ]; then start=1; fi
end=$((line+120))
sed -n "${start},${end}p" "$FILE" | cat -n

# 2) Integration test expectations
echo
echo "=== tests/integration/sdk/test_models.py ==="
sed -n '1,120p' tests/integration/sdk/test_models.py | cat -n

# 3) Test-script README models row
echo
echo "=== scripts/test_scripts/sdk/python/README.md (models row/description) ==="
FILE="scripts/test_scripts/sdk/python/README.md"
# print lines around the "models" row
rg -n "\|\s*`models`\s*\|" "$FILE" -n || true
line=$(rg -n "\|\s*`models`\s*\|" "$FILE" | head -n1 | cut -d: -f1 || true)
if [ -n "${line:-}" ]; then
  start=$((line-5)); if [ $start -lt 1 ]; then start=1; fi
  end=$((line+15))
  sed -n "${start},${end}p" "$FILE" | cat -n
else
  # fallback: show around first "models" mention
  line=$(rg -n "models.*unavailable|models.*skipped|models.*provider" "$FILE" | head -n1 | cut -d: -f1 || true)
  if [ -n "${line:-}" ]; then
    start=$((line-5)); if [ $start -lt 1 ]; then start=1; fi
    end=$((line+15))
    sed -n "${start},${end}p" "$FILE" | cat -n
  fi
fi

Repository: langflow-ai/openrag

Length of output: 15715


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect src/services/models_service.py for error handling / status mapping patterns
FILE="src/services/models_service.py"
echo "=== models_service.py: search for 'status_code' and HTTPException / JSONResponse ==="
rg -n "status_code|HTTPException|JSONResponse|raise .*Exception\\(|not configured|not available|unavailable|disabled" "$FILE" -S || true

echo
echo "=== models_service.py: search for 400/404/403/500 literals near provider fetches ==="
rg -n "status_code\\s*=\\s*(400|404|403|500)|\\b400\\b|\\b404\\b|\\b403\\b|\\b500\\b" "$FILE" -S | head -n 80

echo
echo "=== src/api/v1/models.py: confirm missing-credential cases only return 400 ==="
rg -n "status_code=400|not configured|Set it in Settings" src/api/v1/models.py -S

# 2) Inspect any router/mcp mapping that could return 404 for missing provider models endpoint
echo
echo "=== Search for '/v1/models/{provider}' in routes to see if 404 is possible elsewhere ==="
rg -n "/v1/models/\\{provider\\}|/api/v1/models/\\{provider\\}|VALID_PROVIDERS|Not Found" src -S | head -n 80

Repository: langflow-ai/openrag

Length of output: 1476


Restrict “provider not available” SKIPs to HTTP 400 only in check_models.py.

check_models.py currently converts any OpenRAGError into Skip, which can mask real failures (e.g., 401/403 auth errors and >=500 server/upstream errors) as “provider not available.” The backend /v1/models/{provider} uses 400 for “provider credentials not configured” cases and 500 for other failures—so skip should allowlist only e.status_code == 400 and re-raise otherwise.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_models.py` around lines 14 - 16,
The except block catching OpenRAGError in check_models.py turns all provider
errors into Skip; change it to only convert to Skip when the error indicates
credentials not configured by checking e.status_code == 400 and include the
provider in the message, otherwise re-raise the original OpenRAGError so
401/403/5xx failures surface; update the except OpenRAGError as e handler to
conditionally raise Skip(...) from e only for e.status_code == 400 and use plain
raise for other status codes.

Comment on lines +13 to +18
# Safe no-op: re-set the current chunk_size and read it back, so the
# deployment's configuration is never actually changed.
current = await ctx.client.settings.get()
chunk_size = current.knowledge.chunk_size or 1000

result = await ctx.client.settings.update({"chunk_size": chunk_size})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

update_roundtrip is not actually a no-op when chunk_size is unset.

Line 16 (current.knowledge.chunk_size or 1000) can overwrite instance config (e.g., None/0 becomes 1000), which contradicts the non-destructive intent in Lines 13-15 and can mutate shared SaaS state.

Proposed fix
-from harness import Check, Context
+from harness import Check, Context, Skip
@@
 async def update_roundtrip(ctx: Context) -> None:
@@
-    chunk_size = current.knowledge.chunk_size or 1000
+    chunk_size = current.knowledge.chunk_size
+    if chunk_size is None:
+        raise Skip("knowledge.chunk_size is unset; skipping destructive roundtrip")
 
     result = await ctx.client.settings.update({"chunk_size": chunk_size})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_settings.py` around lines 13 -
18, The current "no-op" roundtrip in update_roundtrip can mutate shared state
because chunk_size is set to 1000 when current.knowledge.chunk_size is falsy;
instead, read current via ctx.client.settings.get() and only include
"chunk_size" in the payload passed to ctx.client.settings.update(...) when
current.knowledge.chunk_size is explicitly set (not None/falsy). Update the
logic around variables current and chunk_size so that if
current.knowledge.chunk_size is None/absent you call update with an empty
payload (or omit the chunk_size key) to avoid changing the deployment config.

@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026
Comment thread scripts/test_scripts/sdk/python/main.py Fixed
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
scripts/test_scripts/sdk/python/main.py (1)

69-74: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate timeout is strictly positive at parse time.

--timeout currently accepts 0 or negative values (Line 69), which are propagated into Config (Line 125) and then into the SDK client timeout. Fail fast in CLI parsing with a > 0 check to avoid runtime-side failures and clearer operator feedback.

Suggested patch
+def _positive_float(value: str) -> float:
+    v = float(value)
+    if v <= 0:
+        raise argparse.ArgumentTypeError("--timeout must be > 0")
+    return v
+
 def parse_config(argv: list[str]) -> Config:
@@
     parser.add_argument(
         "--timeout",
-        type=float,
+        type=_positive_float,
         default=120.0,
         help="Per-request timeout in seconds (default: 120; streaming chat "
         "routinely exceeds the SDK's 30s default)",
     )

Also applies to: 125-125

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/main.py` around lines 69 - 74, The CLI
currently allows non-positive timeouts; update the "--timeout" parsing to
enforce a strictly positive value by adding a validator (e.g., positive_float)
and using it as the add_argument type or by checking args.timeout immediately
after parse_args and calling parser.error if <= 0; also add the same guard when
constructing Config (the Config constructor / assignment at the Config creation
site) to raise a ValueError if timeout <= 0 so invalid values cannot propagate
into the SDK client.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/test_scripts/sdk/python/main.py`:
- Around line 69-74: The CLI currently allows non-positive timeouts; update the
"--timeout" parsing to enforce a strictly positive value by adding a validator
(e.g., positive_float) and using it as the add_argument type or by checking
args.timeout immediately after parse_args and calling parser.error if <= 0; also
add the same guard when constructing Config (the Config constructor / assignment
at the Config creation site) to raise a ValueError if timeout <= 0 so invalid
values cannot propagate into the SDK client.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d322c9b-0bb0-4265-9643-df671d0c05ef

📥 Commits

Reviewing files that changed from the base of the PR and between 53ea436 and 4a7b900.

📒 Files selected for processing (1)
  • scripts/test_scripts/sdk/python/main.py

lucaseduoli and others added 3 commits June 11, 2026 16:59
* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.
@github-actions github-actions Bot added backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) tests enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
scripts/test_scripts/sdk/python/checks/check_filters.py (2)

60-62: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add readiness synchronization after ingestion in scope_setup.

Line 60-Line 61 ingest files and immediately proceed; if indexing is async, downstream scoped checks become flaky/non-deterministic.

#!/bin/bash
set -euo pipefail

echo "== Inspect ingest API for wait/readiness options =="
fd -i 'documents.py' | xargs -I{} sh -c '
  echo "--- {} ---"
  rg -n -C3 "async def ingest|def ingest|wait|ready|poll|timeout" "{}"
'

echo
echo "== Inspect smoke checks for readiness patterns after ingest =="
rg -n --type=py -C2 "documents\\.ingest\\(|wait|poll|ready|search\\.query\\(" scripts/test_scripts/sdk/python/checks

Expected verification result: either documents.ingest is non-blocking (confirming this issue), or it blocks by default (then this can be downgraded).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_filters.py` around lines 60 -
62, The scope_setup currently calls ctx.client.documents.ingest for alpha and
beta and proceeds immediately; add a readiness synchronization step after each
ingest so downstream scoped checks aren't flaky: after calling
ctx.client.documents.ingest(...) in scope_setup, poll for document availability
(e.g., repeatedly call the search/query API or any provided readiness API until
the newly ingested document(s) return in results or a timeout elapses) and only
then return from scope_setup; reference ctx.client.documents.ingest and the
project’s search/query or indexing readiness method (or implement a small poll
loop using ctx.client.documents.search/query) to confirm indexing completion
before continuing.

93-99: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Scoped filter assertions are vacuous without positive in-scope checks.

Line 97-Line 98 and Line 114-Line 116 only prove beta is absent. These checks still pass when retrieval is empty/broken. Assert that alpha is present in both search and chat sources.

Suggested patch
 async def filter_id_in_search(ctx: Context) -> None:
     scope = ctx.shared["scope"]
     results = await ctx.client.search.query("animals", filter_id=scope["filter_id"])
     assert results.results is not None
-    leaked = [r.filename for r in results.results if r.filename == scope["beta"]]
+    filenames = [r.filename for r in results.results]
+    assert scope["alpha"] in filenames, (
+        f"scoped search did not return expected in-scope file {scope['alpha']}: {filenames}"
+    )
+    leaked = [name for name in filenames if name == scope["beta"]]
     assert not leaked, f"filter leaked: search returned out-of-scope file {leaked}"
@@
 async def filter_id_in_chat(ctx: Context) -> None:
@@
     assert response.sources is not None
     source_names = [s.filename for s in response.sources]
+    assert scope["alpha"] in source_names, (
+        f"scoped chat did not cite expected in-scope file {scope['alpha']}: {source_names}"
+    )
     assert scope["beta"] not in source_names, (
         f"filter leaked: chat cited out-of-scope file in {source_names}"
     )

Also applies to: 112-116

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test_scripts/sdk/python/checks/check_filters.py` around lines 93 -
99, The tests only assert that the out-of-scope file (scope["beta"]) is absent,
which allows a broken/empty retrieval to pass; update the scoped-filter tests to
also assert that the in-scope file (scope["alpha"]) is actually returned. In
filter_id_in_search, after fetching results via
ctx.client.search.query("animals", filter_id=scope["filter_id"]), add a positive
assertion that at least one result.filename equals scope["alpha"] (e.g., check
any(r.filename == scope["alpha"]) and assert True with a helpful message). Do
the analogous change in the chat-related test (the function handling chat/query
with filter_id) to assert the chat response includes or references
scope["alpha"] (check response content/messages for scope["alpha"] or an
identifier indicating the alpha file) so both search and chat tests verify
presence of in-scope entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@scripts/test_scripts/sdk/python/checks/check_filters.py`:
- Around line 60-62: The scope_setup currently calls ctx.client.documents.ingest
for alpha and beta and proceeds immediately; add a readiness synchronization
step after each ingest so downstream scoped checks aren't flaky: after calling
ctx.client.documents.ingest(...) in scope_setup, poll for document availability
(e.g., repeatedly call the search/query API or any provided readiness API until
the newly ingested document(s) return in results or a timeout elapses) and only
then return from scope_setup; reference ctx.client.documents.ingest and the
project’s search/query or indexing readiness method (or implement a small poll
loop using ctx.client.documents.search/query) to confirm indexing completion
before continuing.
- Around line 93-99: The tests only assert that the out-of-scope file
(scope["beta"]) is absent, which allows a broken/empty retrieval to pass; update
the scoped-filter tests to also assert that the in-scope file (scope["alpha"])
is actually returned. In filter_id_in_search, after fetching results via
ctx.client.search.query("animals", filter_id=scope["filter_id"]), add a positive
assertion that at least one result.filename equals scope["alpha"] (e.g., check
any(r.filename == scope["alpha"]) and assert True with a helpful message). Do
the analogous change in the chat-related test (the function handling chat/query
with filter_id) to assert the chat response includes or references
scope["alpha"] (check response content/messages for scope["alpha"] or an
identifier indicating the alpha file) so both search and chat tests verify
presence of in-scope entries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e57f9d82-d7d9-4437-a311-12bd664b83c0

📥 Commits

Reviewing files that changed from the base of the PR and between 4a7b900 and 209a19d.

📒 Files selected for processing (10)
  • scripts/test_scripts/sdk/python/README.md
  • scripts/test_scripts/sdk/python/checks/check_chat.py
  • scripts/test_scripts/sdk/python/checks/check_documents.py
  • scripts/test_scripts/sdk/python/checks/check_errors.py
  • scripts/test_scripts/sdk/python/checks/check_filters.py
  • scripts/test_scripts/sdk/python/checks/check_models.py
  • scripts/test_scripts/sdk/python/checks/check_search.py
  • scripts/test_scripts/sdk/python/checks/common.py
  • scripts/test_scripts/sdk/python/harness.py
  • scripts/test_scripts/sdk/python/main.py
✅ Files skipped from review due to trivial changes (1)
  • scripts/test_scripts/sdk/python/README.md
🚧 Files skipped from review as they are similar to previous changes (7)
  • scripts/test_scripts/sdk/python/checks/check_models.py
  • scripts/test_scripts/sdk/python/checks/check_errors.py
  • scripts/test_scripts/sdk/python/checks/check_search.py
  • scripts/test_scripts/sdk/python/checks/check_documents.py
  • scripts/test_scripts/sdk/python/main.py
  • scripts/test_scripts/sdk/python/checks/check_chat.py
  • scripts/test_scripts/sdk/python/harness.py

@github-actions github-actions Bot added the lgtm label Jun 12, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 12, 2026
…f sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 12, 2026
@edwinjosechittilappilly edwinjosechittilappilly merged commit 027a11a into main Jun 12, 2026
18 checks passed
@github-actions github-actions Bot deleted the sdk-scripts branch June 12, 2026 04:43
ricofurtado pushed a commit that referenced this pull request Jun 12, 2026
* sdk scripts

* Update main.py

* fix: put correct file type in langflow-less ingestion (#1842)

* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: add Python SDK smoke-test suite for remote/IBM SaaS deployments

Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.

* style: ruff autofix (auto)

* Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
ricofurtado added a commit that referenced this pull request Jun 12, 2026
…dingly (#1851)

* fix: handle document processing errors and update task statuses accordingly

* fix: add OCR handling for raster images during file ingestion

* style: ruff autofix (auto)

* fix: google to support WEBHOOK_BASE_URL (#1849)

* Update connector.py

* update env in settings

* fix webhook url of sharepoint

* feat: crd report scaleddown phase status (#1846)

* crd report scaleddown phase status

* improve status message

* chore: release 0.4.0.dev0 of sdks (#1847)

* release 0.4.1 of sdks

* dev 0

* dev 0

* 0.4.0-dev0

* feat: sdk scripts (#1848)

* sdk scripts

* Update main.py

* fix: put correct file type in langflow-less ingestion (#1842)

* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: add Python SDK smoke-test suite for remote/IBM SaaS deployments

Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.

* style: ruff autofix (auto)

* Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <[email protected]>
Co-authored-by: ming <[email protected]>
Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Vchen7629 pushed a commit to Vchen7629/openrag that referenced this pull request Jun 15, 2026
* sdk scripts

* Update main.py

* fix: put correct file type in langflow-less ingestion (langflow-ai#1842)

* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: add Python SDK smoke-test suite for remote/IBM SaaS deployments

Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.

* style: ruff autofix (auto)

* Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Vchen7629 pushed a commit to Vchen7629/openrag that referenced this pull request Jun 15, 2026
…dingly (langflow-ai#1851)

* fix: handle document processing errors and update task statuses accordingly

* fix: add OCR handling for raster images during file ingestion

* style: ruff autofix (auto)

* fix: google to support WEBHOOK_BASE_URL (langflow-ai#1849)

* Update connector.py

* update env in settings

* fix webhook url of sharepoint

* feat: crd report scaleddown phase status (langflow-ai#1846)

* crd report scaleddown phase status

* improve status message

* chore: release 0.4.0.dev0 of sdks (langflow-ai#1847)

* release 0.4.1 of sdks

* dev 0

* dev 0

* 0.4.0-dev0

* feat: sdk scripts (langflow-ai#1848)

* sdk scripts

* Update main.py

* fix: put correct file type in langflow-less ingestion (langflow-ai#1842)

* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: add Python SDK smoke-test suite for remote/IBM SaaS deployments

Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.

* style: ruff autofix (auto)

* Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <[email protected]>
Co-authored-by: ming <[email protected]>
Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
ricofurtado pushed a commit that referenced this pull request Jun 15, 2026
* sdk scripts

* Update main.py

* fix: put correct file type in langflow-less ingestion (#1842)

* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: add Python SDK smoke-test suite for remote/IBM SaaS deployments

Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.

* style: ruff autofix (auto)

* Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
ricofurtado added a commit that referenced this pull request Jun 15, 2026
…dingly (#1851)

* fix: handle document processing errors and update task statuses accordingly

* fix: add OCR handling for raster images during file ingestion

* style: ruff autofix (auto)

* fix: google to support WEBHOOK_BASE_URL (#1849)

* Update connector.py

* update env in settings

* fix webhook url of sharepoint

* feat: crd report scaleddown phase status (#1846)

* crd report scaleddown phase status

* improve status message

* chore: release 0.4.0.dev0 of sdks (#1847)

* release 0.4.1 of sdks

* dev 0

* dev 0

* 0.4.0-dev0

* feat: sdk scripts (#1848)

* sdk scripts

* Update main.py

* fix: put correct file type in langflow-less ingestion (#1842)

* FIxed no langflow ingestion

* style: ruff autofix (auto)

* add fallback for mime types

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* feat: add Python SDK smoke-test suite for remote/IBM SaaS deployments

Standalone uv project under scripts/test_scripts/sdk/python that exercises
every openrag-sdk functionality (settings, models, documents, search, chat,
knowledge filters, error handling) against a remote instance using IBM SaaS
header auth (X-Username / X-Api-Key), with pass/fail/skip reporting to
console, markdown, JSON, and a run log.

* style: ruff autofix (auto)

* Potential fix for pull request finding 'CodeQL / Clear-text logging of sensitive information'

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* style: ruff autofix (auto)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Edwin Jose <[email protected]>
Co-authored-by: ming <[email protected]>
Co-authored-by: Lucas Oliveira <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) enhancement 🔵 New feature or request lgtm tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants