Skip to content

Health Probes: For llm_call endpoints - #1021

Open
Prajna1999 wants to merge 11 commits into
mainfrom
feat/api-health-probes
Open

Health Probes: For llm_call endpoints#1021
Prajna1999 wants to merge 11 commits into
mainfrom
feat/api-health-probes

Conversation

@Prajna1999

@Prajna1999 Prajna1999 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Issue #987

Summary

A cron job that wakes up every 5 mins and make API calls with a small payload to every major models. If any error occurs i.e inference for the model is down it shows up in Sentry Issues. The call traces are logged in sentry too.

Added automated health probes for configured text, speech-to-text, and text-to-speech providers.

  • Health probes now run on a scheduled basis and report success, failures, latency, and skipped status.

Models count 13

Probe(provider="openai", model="gpt-4o-mini", modality="text"),
    Probe(provider="google", model="gemini-2.5-flash", modality="text"),
    Probe(provider="google", model="gemini-2.5-pro", modality="text"),
    # TTS
    Probe(provider="google", model="gemini-2.5-flash-preview-tts", modality="tts"),
    Probe(provider="google", model="gemini-3.1-flash-preview-tts", modality="tts"),
    Probe(provider="google", model="gemini-2.5-pro-preview-tts", modality="tts"),
    Probe(provider="sarvamai", model="bulbul:v3", modality="tts"),
    Probe(provider="elevenlabs", model="eleven_v3", modality="tts"),
    # STT
    Probe(provider="google", model="gemini-2.5-pro", modality="stt"),
    Probe(provider="google", model="gemini-2.5-flash", modality="stt"),
    Probe(provider="google", model="gemini-3.1-pro-preview", modality="stt"),
    Probe(provider="sarvamai", model="saaras:v3", modality="stt"),
    Probe(provider="elevenlabs", model="scribe_v2", modality="stt"),

The job happens inside Celery task.
env addition

HEALTH_PROBE_ORG_ID= 1
HEALTH_PROBE_PROJECT_ID=2
HEALTH_PROBE_INTERVAL_MINUTES=1

The superuser org_id and project_id against whose creds are to be used to make the provider calls. This to be set during deployment.

Checklist

Before submitting a pull request, please ensure that you mark these task.

  • Ran fastapi run --reload app/main.py or docker compose up in the repository root and test.
  • If you've fixed a bug or added code that is tested and has test cases.

Summary by CodeRabbit

  • New Features

    • Added automated health probes for text, speech generation, and speech recognition services.
    • Health probes now report latency, success or failure details, and Sentry monitoring status.
    • Added scheduled execution and a restricted manual trigger for authorized administrators.
    • Added configuration options for probe projects, organizations, and execution intervals.
  • Bug Fixes

    • Improved trace propagation for monitored operations.
  • Tests

    • Added coverage for probe execution, failures, monitoring, task scheduling, and access controls.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds configurable text, TTS, and STT health probes with concurrent execution, Sentry check-ins, a traced Celery task, and a hidden superuser-only cron endpoint registered with the cron invoker.

Changes

Health probe execution

Layer / File(s) Summary
Probe configuration and runner
backend/app/core/config.py, backend/app/services/health_probes.py, backend/app/tests/services/test_health_probes.py
Adds probe settings, modality-specific inputs, provider caching, concurrent execution, structured results, failure handling, Sentry check-ins, and service coverage.
Celery task and tracing
backend/app/core/telemetry.py, backend/app/celery/tasks/job_execution.py, backend/app/tests/celery/test_run_health_probes.py
Adds global Sentry trace propagation and a Celery task that invokes health probe execution, with task result coverage.
Cron endpoint and scheduling
backend/app/api/routes/cron.py, scripts/python/invoke-cron.py, backend/app/tests/api/routes/test_cron_health_probes.py
Adds the hidden superuser-only endpoint, registers it with the cron invoker, and tests authorization, enqueueing, and OpenAPI exclusion.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: akhileshnegi, ayush8923

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is related to the main change: adding health probes for llm_call-related endpoints and provider checks.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/api-health-probes

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.

@github-actions github-actions Bot changed the title resolve merge conflict chore(api): Resolve merge conflicts Jul 9, 2026
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

OpenAPI changes   ⚪ No API surface changes

Note

This PR does not modify the API contract.

main766223b3 · generated by oasdiff

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.87500% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/app/services/health_probes.py 93.57% 9 Missing ⚠️
backend/app/core/telemetry.py 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

@Prajna1999 Prajna1999 changed the title chore(api): Resolve merge conflicts Health Probes: For llm_call endpoints Jul 10, 2026
@Prajna1999 Prajna1999 self-assigned this Jul 10, 2026
@Prajna1999 Prajna1999 linked an issue Jul 10, 2026 that may be closed by this pull request

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (5)
backend/app/services/health_probes.py (1)

211-220: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a uniqueness assertion to the __main__ self-check.

The __main__ block validates modalities and config building but doesn't check for duplicate probes. Adding assert len(_PROBES) == len(set(_PROBES)) would have caught the duplicate at lines 40-41.

♻️ Proposed addition
 if __name__ == "__main__":
     assert _PROBES, "probe list must not be empty"
+    assert len(_PROBES) == len(set(_PROBES)), "duplicate probe entries detected"
     modalities = {p.modality for p in _PROBES}
🤖 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 `@backend/app/services/health_probes.py` around lines 211 - 220, Add a
duplicate-probe validation to the __main__ self-check in health_probes.py: after
asserting _PROBES is nonempty, assert len(_PROBES) == len(set(_PROBES)) before
validating modalities and config construction.
backend/app/tests/services/test_health_probes.py (1)

131-138: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the obscure generator-throw lambda with a named function for consistency.

lambda **_k: (_ for _ in ()).throw(RuntimeError("bad")) is unreadable. The ValueError test above (line 117) uses a clear named function _boom — follow the same pattern here.

♻️ Proposed fix
-        monkeypatch.setattr(
-            health_probes,
-            "get_llm_provider",
-            lambda **_k: (_ for _ in ()).throw(RuntimeError("bad")),
-        )
+        def _boom(**_kwargs):
+            raise RuntimeError("bad")
+
+        monkeypatch.setattr(health_probes, "get_llm_provider", _boom)
🤖 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 `@backend/app/tests/services/test_health_probes.py` around lines 131 - 138,
Replace the generator-throw lambda in
test_get_llm_provider_runtime_error_marks_client_init_failed with a local named
function, such as _boom, that accepts arbitrary keyword arguments and raises
RuntimeError("bad"), then monkeypatch get_llm_provider with that function,
matching the pattern used by the ValueError test.
backend/app/celery/tasks/job_execution.py (1)

411-423: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider using dict[str, Any] instead of bare dict for return types.

The upstream run_probes returns dict[str, Any]. Using -> dict[str, Any] on both run_health_probes and the nested _do closure would match that contract and improve type precision.

♻️ Proposed type hint refinement
-def run_health_probes(self, trace_id: str = DEFAULT_TRACE_ID) -> dict:
+def run_health_probes(self, trace_id: str = DEFAULT_TRACE_ID) -> dict[str, Any]:
     from sqlmodel import Session
 
     from app.core.db import engine
     from app.services.health_probes import run_probes
 
     _set_trace(trace_id)
 
-    def _do() -> dict:
+    def _do() -> dict[str, Any]:
         with Session(engine) as session:
             return run_probes(session=session)
 
     return _run_with_otel_parent(self, _do)
🤖 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 `@backend/app/celery/tasks/job_execution.py` around lines 411 - 423, Update the
return annotations of both `run_health_probes` and its nested `_do` closure from
bare `dict` to `dict[str, Any]`, importing `Any` as needed, so they match the
`run_probes` return contract.
backend/app/api/routes/cron.py (2)

35-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract shared monitor config values into constants.

checkin_margin, failure_issue_threshold, and recovery_threshold are duplicated between EVALUATION_CRON_MONITOR_CONFIG and the new HEALTH_PROBES_CRON_MONITOR_CONFIG with identical values. As per coding guidelines, repeated literals should be extracted into constants.

♻️ Proposed refactor
+CRON_CHECKIN_MARGIN = 2
+CRON_FAILURE_ISSUE_THRESHOLD = 2
+CRON_RECOVERY_THRESHOLD = 1
+
 EVALUATION_CRON_MONITOR_CONFIG: MonitorConfig = {
     "schedule": {
         "type": "interval",
         "value": settings.CRON_INTERVAL_MINUTES,
         "unit": "minute",
     },
     "timezone": "UTC",
-    "checkin_margin": 2,
+    "checkin_margin": CRON_CHECKIN_MARGIN,
     "max_runtime": 2 * settings.CRON_INTERVAL_MINUTES,
-    "failure_issue_threshold": 2,
-    "recovery_threshold": 1,
+    "failure_issue_threshold": CRON_FAILURE_ISSUE_THRESHOLD,
+    "recovery_threshold": CRON_RECOVERY_THRESHOLD,
 }

 HEALTH_PROBES_CRON_MONITOR_CONFIG: MonitorConfig = {
     "schedule": {
         "type": "interval",
         "value": settings.HEALTH_PROBE_INTERVAL_MINUTES,
         "unit": "minute",
     },
     "timezone": "UTC",
-    "checkin_margin": 2,
+    "checkin_margin": CRON_CHECKIN_MARGIN,
     "max_runtime": 2 * settings.HEALTH_PROBE_INTERVAL_MINUTES,
-    "failure_issue_threshold": 2,
-    "recovery_threshold": 1,
+    "failure_issue_threshold": CRON_FAILURE_ISSUE_THRESHOLD,
+    "recovery_threshold": CRON_RECOVERY_THRESHOLD,
 }
🤖 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 `@backend/app/api/routes/cron.py` around lines 35 - 47, Extract the duplicated
monitor settings into shared constants and use them in both
EVALUATION_CRON_MONITOR_CONFIG and HEALTH_PROBES_CRON_MONITOR_CONFIG. Replace
the repeated checkin_margin, failure_issue_threshold, and recovery_threshold
literals with the new constants while preserving their current values.

Source: Coding guidelines


148-151: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add error handling for consistency with other cron endpoints.

evaluation_cron_job and pending_jobs_cron_job both wrap their logic in try/except, logging the error and capturing it in Sentry before re-raising. health_probes_cron_job has no such guard — if run_health_probes.delay() fails (e.g., broker unavailable), the exception propagates without structured logging or explicit Sentry capture.

🛡️ Proposed error handling
 def health_probes_cron_job() -> dict:
     logger.info("[health_probes_cron_job] Cron job invoked — enqueueing task")
-    async_result = run_health_probes.delay()
-    return {"enqueued": True, "task_id": async_result.id}
+    try:
+        async_result = run_health_probes.delay()
+        return {"enqueued": True, "task_id": async_result.id}
+    except Exception as e:
+        logger.error(
+            f"[health_probes_cron_job] Error enqueueing health probes: {e}",
+            exc_info=True,
+        )
+        sentry_sdk.capture_exception(e)
+        raise
🤖 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 `@backend/app/api/routes/cron.py` around lines 148 - 151, Wrap the logic in
health_probes_cron_job with a try/except matching evaluation_cron_job and
pending_jobs_cron_job: log the exception with context, capture it in Sentry,
then re-raise it. Keep the existing enqueue and response behavior inside the try
block.
🤖 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 `@backend/app/services/health_probes.py`:
- Around line 40-41: Remove the duplicate Probe entry for provider "google",
model "gemini-2.5-flash", and modality "text" from the probe configuration, or
replace it with the intended distinct model while preserving the existing Probe
structure.
- Around line 134-147: Wrap the _build_config_and_input(probe) call in a
dedicated try-except that catches validation and decoding errors, records an
appropriate per-probe error in result, and returns it without propagating to
ThreadPoolExecutor.map. Preserve the existing stt_audio_not_configured handling
for a None result, while keeping provider.execute’s existing exception handling
separate.

In `@backend/app/tests/celery/test_run_health_probes.py`:
- Line 12: Add the missing None return annotations to
_NonClosingSession.__init__ and both test functions, preserving their existing
parameters and behavior.

---

Nitpick comments:
In `@backend/app/api/routes/cron.py`:
- Around line 35-47: Extract the duplicated monitor settings into shared
constants and use them in both EVALUATION_CRON_MONITOR_CONFIG and
HEALTH_PROBES_CRON_MONITOR_CONFIG. Replace the repeated checkin_margin,
failure_issue_threshold, and recovery_threshold literals with the new constants
while preserving their current values.
- Around line 148-151: Wrap the logic in health_probes_cron_job with a
try/except matching evaluation_cron_job and pending_jobs_cron_job: log the
exception with context, capture it in Sentry, then re-raise it. Keep the
existing enqueue and response behavior inside the try block.

In `@backend/app/celery/tasks/job_execution.py`:
- Around line 411-423: Update the return annotations of both `run_health_probes`
and its nested `_do` closure from bare `dict` to `dict[str, Any]`, importing
`Any` as needed, so they match the `run_probes` return contract.

In `@backend/app/services/health_probes.py`:
- Around line 211-220: Add a duplicate-probe validation to the __main__
self-check in health_probes.py: after asserting _PROBES is nonempty, assert
len(_PROBES) == len(set(_PROBES)) before validating modalities and config
construction.

In `@backend/app/tests/services/test_health_probes.py`:
- Around line 131-138: Replace the generator-throw lambda in
test_get_llm_provider_runtime_error_marks_client_init_failed with a local named
function, such as _boom, that accepts arbitrary keyword arguments and raises
RuntimeError("bad"), then monkeypatch get_llm_provider with that function,
matching the pattern used by the ValueError test.
🪄 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: 4862ba33-39e8-4bae-b167-cbf6f204e8c9

📥 Commits

Reviewing files that changed from the base of the PR and between 102b61c and cdc3ac6.

📒 Files selected for processing (9)
  • backend/app/api/routes/cron.py
  • backend/app/celery/tasks/job_execution.py
  • backend/app/core/config.py
  • backend/app/core/telemetry.py
  • backend/app/services/health_probes.py
  • backend/app/tests/api/routes/test_cron_health_probes.py
  • backend/app/tests/celery/test_run_health_probes.py
  • backend/app/tests/services/test_health_probes.py
  • scripts/python/invoke-cron.py

Comment thread backend/app/services/health_probes.py Outdated
Comment thread backend/app/services/health_probes.py Outdated
Comment thread backend/app/tests/celery/test_run_health_probes.py Outdated
Prajna1999 and others added 3 commits July 10, 2026 09:57
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@Prajna1999 Prajna1999 added enhancement New feature or request and removed chore labels Jul 10, 2026
@Prajna1999 Prajna1999 moved this to In Review in Kaapi-dev Jul 10, 2026
@Prajna1999 Prajna1999 removed this from Kaapi-dev Jul 10, 2026

@vprashrex vprashrex left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I have approved the PR so it doesn't block the merge, but I added comments that should be addressed before this goes in:
Database sessions should never be opened at the task level. They should be short-lived and opened only within the child functions that perform the database operations.

Comment thread backend/app/api/routes/cron.py Outdated
HEALTH_PROBES_CRON_MONITOR_CONFIG: MonitorConfig = {
"schedule": {
"type": "interval",
# not required eventbridge is aleady 5 mins. So not required.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove this comment

_set_trace(trace_id)

def _do() -> dict:
with Session(engine) as session:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Opening a DB session at the task level isn't a good approach because it keeps the connection open for the entire task duration. Sessions should be short-lived. Instead, open and close the session within the child functions where the database operations actually happen.

Comment thread backend/app/services/health_probes.py Outdated
_PROBE_MAX_TOKENS = 1
_PROBE_WORKERS = 4

# "Hello" ~1sec

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Instead of inlining the Base64 payload in the source file, consider storing it in a separate file and reading it at runtime. This keeps the source code clean, improves maintainability, and avoids checking large static blobs into the code.

like this u can do

with open("tests/assets/hello.wav", "rb") as f:
    audio_b64 = base64.b64encode(f.read()).decode()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

+1


_PROBES: list[Probe] = [
# Text
Probe(provider="openai", model="gpt-4o-mini", modality="text"),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

use anthropic provider as well to test

@Prajna1999
Prajna1999 requested a review from kartpop July 20, 2026 04:38

@kartpop kartpop left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

found at least two major issues - please fix

Comment thread backend/app/services/health_probes.py Outdated
_PROBE_MAX_TOKENS = 1
_PROBE_WORKERS = 4

# "Hello" ~1sec

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

+1

Comment thread backend/app/services/health_probes.py Outdated
Comment on lines +75 to +116
def _build_config_and_input(
probe: Probe,
) -> tuple[KaapiCompletionConfig, str | AudioRef] | None:
if probe.modality == "text":
cfg = KaapiCompletionConfig.model_validate(
{
"provider": probe.provider,
"type": "text",
"params": {
"model": probe.model,
"temperature": 0.0,
"max_output_tokens": _PROBE_MAX_TOKENS,
},
}
)
return cfg, _PROBE_INPUT

if probe.modality == "tts":
cfg = KaapiCompletionConfig.model_validate(
{
"provider": probe.provider,
"type": "tts",
"params": {"model": probe.model},
}
)
return cfg, _PROBE_INPUT

# stt
if not _STT_AUDIO_B64:
return None
cfg = KaapiCompletionConfig.model_validate(
{
"provider": probe.provider,
"type": "stt",
"params": {"model": probe.model},
}
)
audio = AudioRef(
bytes_=base64.b64decode(_STT_AUDIO_B64),
mime_type=_STT_AUDIO_MIME,
)
return cfg, audio

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not sure this will work!!!

shouldn't transform_kaapi_config_to_native be called like it gets called in the llm_call flow?

passing KappiCompletionConfig will probably send malformed requests - did we test this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes this was working manually. I will retest and confirm

Comment on lines +139 to +151
@router.get(
"/cron/health-probes",
include_in_schema=False,
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
)
@sentry_sdk.monitor(
monitor_slug="health-probes-cron-job",
monitor_config=HEALTH_PROBES_CRON_MONITOR_CONFIG,
)
def health_probes_cron_job() -> dict:
logger.info("[health_probes_cron_job] Cron job invoked — enqueueing task")
async_result = run_health_probes.delay()
return {"enqueued": True, "task_id": async_result.id}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this just checks whether the task is enqueued right? is it doing anything useful? i think this will mark SUCCESS irrespective of what happens in the celery task

@vprashrex can you confirm?

there should be a sentry monitor on the task also, because the real work is happening inside the celery task.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@sentry_sdk.monitor is currently on the route, so it reports OK as soon as the Celery task is queued, not when it actually finishes. Probe failures only appear via logger.error, which isn't real monitoring and misses warning/skipped cases. Need to move the check-in into run_health_probes using capture_checkin, so the monitor reports OK only when all probes succeed and ERROR otherwise.

@Ayush8923

Ayush8923 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

I have updated the PR label from ready-for-review to reviewed since @kartpop and @vprashrex have both reviewed it. please address the review comments. Once they are resolved, remove the reviewed label and add ready-for-review again.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (3)
backend/app/tests/services/test_health_probes.py (1)

21-50: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add missing -> None return type hints on __init__ methods.

_NonClosingSession.__init__ (line 25) and _FakeProvider.__init__ (lines 41-46) lack return type annotations.

As per coding guidelines, "provide narrow type hints for every function parameter and return value."

✏️ Proposed fix
-    def __init__(self, session: Session):
+    def __init__(self, session: Session) -> None:
         self._session = session
     def __init__(
         self,
         response: Any = None,
         error: str | None = None,
         raise_exc: Exception | None = None,
-    ):
+    ) -> None:
🤖 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 `@backend/app/tests/services/test_health_probes.py` around lines 21 - 50, Add
the explicit -> None return annotation to the __init__ methods of
_NonClosingSession and _FakeProvider, preserving their existing parameters and
initialization logic.

Source: Coding guidelines

backend/app/services/health_probes.py (1)

160-241: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Previous critical concern resolved — config build now inside try-except in _prepare_probes.

_build_config_and_input is now called inside a dedicated try-except (lines 227-236) rather than unguarded inside _run_probe, so a ValidationError/decode failure on one probe no longer aborts the whole run.

Separately, several probe outcomes use hard-coded string literals ("client_init_failed", "stt_audio_not_configured", "no_response", "not_prepared") that are also asserted against by string equality in the test suite. Consider a small ProbeErrorEnum (or module-level constants) shared between this module and its tests to avoid silent drift between producer and consumer strings.

As per coding guidelines, "Do not use magic values; extract repeated literals into constants, enums, or settings" and "Use an Enum suffix for enum class names."

♻️ Proposed refactor
+class ProbeErrorEnum(str, Enum):
+    CLIENT_INIT_FAILED = "client_init_failed"
+    STT_AUDIO_NOT_CONFIGURED = "stt_audio_not_configured"
+    NO_RESPONSE = "no_response"
+    NOT_PREPARED = "not_prepared"
🤖 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 `@backend/app/services/health_probes.py` around lines 160 - 241, Extract the
repeated probe error literals used by _run_probe and
_prepare_probes—"client_init_failed", "stt_audio_not_configured", "no_response",
and "not_prepared"—into shared module-level constants or a ProbeErrorEnum, using
the required Enum suffix if defining an enum. Replace the producer-side literals
with those shared symbols and update tests to assert against the same symbols
while preserving the existing serialized string values.

Source: Coding guidelines

backend/app/celery/tasks/job_execution.py (1)

248-266: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing type hints on run_prompt_improvement.

Return type and **kwargs are untyped, unlike the sibling run_health_probes task.

As per coding guidelines, "provide narrow type hints for every function parameter and return value; do not use -> Any as a substitute for a specific annotation."

✏️ Proposed fix
-def run_prompt_improvement(self, project_id: int, job_id: str, trace_id: str, **kwargs):
+def run_prompt_improvement(
+    self, project_id: int, job_id: str, trace_id: str, **kwargs: Any
+) -> dict:
🤖 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 `@backend/app/celery/tasks/job_execution.py` around lines 248 - 266, Update
run_prompt_improvement with narrow type annotations for its **kwargs parameter
and return value, matching the typing approach used by the sibling
run_health_probes task; avoid using Any and preserve the existing task execution
behavior.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@backend/app/celery/tasks/job_execution.py`:
- Around line 248-266: Update run_prompt_improvement with narrow type
annotations for its **kwargs parameter and return value, matching the typing
approach used by the sibling run_health_probes task; avoid using Any and
preserve the existing task execution behavior.

In `@backend/app/services/health_probes.py`:
- Around line 160-241: Extract the repeated probe error literals used by
_run_probe and _prepare_probes—"client_init_failed", "stt_audio_not_configured",
"no_response", and "not_prepared"—into shared module-level constants or a
ProbeErrorEnum, using the required Enum suffix if defining an enum. Replace the
producer-side literals with those shared symbols and update tests to assert
against the same symbols while preserving the existing serialized string values.

In `@backend/app/tests/services/test_health_probes.py`:
- Around line 21-50: Add the explicit -> None return annotation to the __init__
methods of _NonClosingSession and _FakeProvider, preserving their existing
parameters and initialization logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 468b52fd-540d-451e-bdb0-74d9f25c4b25

📥 Commits

Reviewing files that changed from the base of the PR and between cdc3ac6 and 1ebef3d.

⛔ Files ignored due to path filters (1)
  • backend/app/assets/health_probe_hello.ogg is excluded by !**/*.ogg
📒 Files selected for processing (7)
  • backend/app/api/routes/cron.py
  • backend/app/celery/tasks/job_execution.py
  • backend/app/core/config.py
  • backend/app/services/health_probes.py
  • backend/app/tests/api/routes/test_cron_health_probes.py
  • backend/app/tests/celery/test_run_health_probes.py
  • backend/app/tests/services/test_health_probes.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/app/tests/api/routes/test_cron_health_probes.py
  • backend/app/core/config.py

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

Labels

enhancement New feature or request ready-for-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Monitoring: Health checks for endpoints

4 participants