Skip to content

chore: restore reverted test suites, folder structure, logic optimizations, and security patches (v4)#201

Closed
sheepdestroyer wants to merge 12 commits into
masterfrom
chore/restore-reversions-final-v4
Closed

chore: restore reverted test suites, folder structure, logic optimizations, and security patches (v4)#201
sheepdestroyer wants to merge 12 commits into
masterfrom
chore/restore-reversions-final-v4

Conversation

@sheepdestroyer

@sheepdestroyer sheepdestroyer commented Jul 2, 2026

Copy link
Copy Markdown
Owner

This PR comprehensively restores all files, directory organization, logic optimizations, container dependencies, and security patches that were mistakenly deleted or reverted during recent automated merge conflict resolutions on master.

1. Folder Structure & Reorganization Restored

  • Moved 23 test and utility files currently at the root back to their reorganized directories (tests/, scripts/, scripts/verification/, and router/tests/) matching PR Refactor: Reorganize repository structure #181.
  • Removed duplicate test files (e.g. removing router/test_memory_mcp.py and consolidating tests in router/tests/test_memory_mcp.py).

2. Missing Test and Utility Files Recovered

Checked out and restored the following 10 files from past commits in the repository history:

3. Logic Optimizations Re-applied in router/main.py

  • Async Cache: Restored the async annotations caching logic (_read_annotations_async and deepcopy offloading) to prevent blocking the event loop.
  • Token Heuristics: Restored the regex-based _count_tokens_heuristic and updated estimate_prompt_tokens to use it (bringing token estimation accuracy within ±11% of prose, code, and CJK).
  • Valkey URL Connection: Restored URL-based Redis/Valkey client initialization in get_redis to handle client configuration properly.

4. Security & Configuration Patches Restored

  • Category Injection: Restored input sanitization (urllib.parse.quote(category) and unquote) in router/memory_mcp.py to prevent parameter-injection vulnerabilities.
  • Password Placeholders: Restored pod.yaml and start-stack.sh back to secure, placeholder-based credential configurations (avoiding hardcoded default passwords in git).
  • Version Upgrades: Restored LiteLLM v1.90.2 and newer container tags (ClickHouse, Valkey, pgvector, MinIO, and Langfuse).
  • Container Dependencies: Fixed router/Dockerfile to include aiofiles.

5. CI Workflow & Test Collection Fixes

  • Dependency List: Added aiofiles to the pip install action in .github/workflows/test.yml.
  • Path Targets: Updated workflow execution steps to reference corrected tests/ and scripts/ pathways.
  • Import-time Execution: Wrapped tests/test_agy_behavior.py in a __main__ block to prevent immediate execution at import-time during test collection (resolving CI collection crash).

6. Agent Guidelines & Post-Mortem Documentation

  • Added Git Rebase and Conflict Resolution Rules to .agents/AGENTS.md to prevent automated bots from re-introducing folder and logic regressions.
  • Saved the complete post-mortem regression report to .agents/jules_regression_analysis.md.

Verification: All 176 unit and integration tests compile, collect, and pass successfully.

7. Review & Bot Reversion Updates Applied (v2)

  • Fixed missing comma in start-stack.sh python wrapper list rendering.
  • Restored performance-sensitive async _is_quota_exhausted log reader in router/agy_proxy.py and converted tests to async.
  • Restored parallel ThreadPoolExecutor optimization in scripts/benchmark_classifier.py.
  • Fixed test_detect_active_tool.py to import from module level main instead of router.main.
  • Defensively handled potential null statusCheckRollup in scripts/get_pr_status.py and added a regression unit test.
  • Expanded early openssl check in start-stack.sh to prevent command-not-found failures on unset env parameters.
  • Restored Prisma datetime/RobustDatetime serialization patch in litellm/entrypoint.py to fix spend logs serialization failures.
  • Restored complete environment-driven placeholders relocation in pod.yaml and start-stack.sh (for LITELLM_MASTER_KEY, POSTGRES_PASSWORD, OLLAMA_API_KEY, LANGFUSE_PUBLIC_KEY, and LANGFUSE_SECRET_KEY) together with dynamic fallback key generation.
  • Restored offload-aa-scores-sync optimization from PR ⚡ Offload synchronous AA scores loading to thread #98 to offload blocking synchronous disk operations to a background thread pool inside sync_adaptive_router_roster and get_best_free_model.
  • Added a comprehensive branch audit report at .agents/branch_audit_plan.md to track and prevent any future merge conflict regressions.
  • Optimized _is_quota_exhausted in router/agy_proxy.py to use binary mode, seeking to the end, and reading only the last 1KB chunk of cli.log asynchronously, avoiding loading large log files in memory and bypassing the blocking synchronous os.path.exists check.

@sourcery-ai sourcery-ai 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.

Sorry @sheepdestroyer, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@sheepdestroyer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b7e38b5f-97a9-4ba8-abb0-dd043475ef57

📥 Commits

Reviewing files that changed from the base of the PR and between b0a8605 and 186c9d4.

📒 Files selected for processing (7)
  • .agents/jules_regression_analysis.md
  • README.md
  • litellm/entrypoint.py
  • router/main.py
  • router/tests/test_memory_mcp.py
  • scripts/benchmark_classifier.py
  • start-stack.sh
📝 Walkthrough

Walkthrough

This PR converts several router I/O paths to async (quota checks, annotation persistence, AA score loading), reworks token estimation and memory key formatting with new/updated tests, replaces hardcoded credentials in pod.yaml/start-stack.sh with placeholders, fixes a Prisma datetime serialization gap, updates CI/tooling scripts, adds a PR status utility, and adds agent-policy/regression documentation.

Changes

Router Async I/O and Core Logic

Layer / File(s) Summary
Async quota-exhaustion detection
router/agy_proxy.py, router/tests/test_agy_proxy.py, tests/test_agy_behavior.py
_is_quota_exhausted becomes async using aiofiles; callers await it; tests converted to async with AsyncMock.
Regex-based prompt token estimation
router/main.py, router/tests/test_estimate_prompt_tokens.py, scripts/benchmark_tokens.py
estimate_prompt_tokens replaced with a weighted regex heuristic; new benchmark script validates accuracy.
Valkey/Redis connection configuration
router/main.py, router/tests/test_get_redis.py
get_redis() prefers VALKEY_URL over host/port; new test suite covers cooldown, success, failure, and exception paths.
Lazy AA scores loading
router/main.py, tests/test_compute_free_model_score.py, .agents/branch_audit_plan.md
AA score loading moves from eager to on-demand asyncio.to_thread calls in roster sync and get_best_free_model; tests preload the cache explicitly.
Async annotation persistence cache
router/main.py, tests/test_read_annotations_async.py
Adds _annotations_cache with mtime-based invalidation and aiofiles-based reads; new tests cover caching, invalidation, and deep-copy isolation.
Memory key v2 format
router/memory_mcp.py, router/tests/test_memory_mcp.py
_make_key/_parse_key support a URL-encoded v2 key format alongside legacy keys; _is_memory_key rejects non-string inputs; new test suite added.
New router endpoint/utility tests
router/tests/test_detect_active_tool.py, router/tests/test_get_gemini_oauth_status.py, router/tests/test_get_goose_sessions.py
New standalone test modules cover tool detection, OAuth expiry status, and Goose session retrieval.
host_agy_daemon test suite
tests/test_host_agy_daemon.py
New extensive tests cover the daemon's HTTP handler, streaming, timeouts, subprocess errors, and shutdown.
Persisted stats test coverage
router/tests/test_load_persisted_stats.py
New tests cover load_persisted_stats merge, missing-file, and exception scenarios.

Deployment Secrets Hardening

Layer / File(s) Summary
pod.yaml placeholder secrets and image bumps
pod.yaml
Inlined credentials replaced with placeholder env values across multiple containers; several image tags bumped.
start-stack.sh secret generation and pod render
start-stack.sh
Expands openssl precheck, adds generate_uuid(), provisions additional secrets, and updates render_pod_yaml() substitution logic.
README version pin update
README.md
LiteLLM version pin references updated from v1.88.0 to v1.90.2.

LiteLLM Datetime Serialization

Layer / File(s) Summary
Prisma datetime serializer registration
litellm/entrypoint.py
Registers an ISO 8601 datetime serializer for both original_datetime and RobustDatetime.

CI, Scripts, and Tooling Updates

Layer / File(s) Summary
CI workflow and docs path updates
.github/workflows/test.yml, router/Dockerfile, scripts/README.md
Adds aiofiles dependency and updates pytest ignore/verification script paths in CI and docs.
get_pr_status.py script and tests
scripts/get_pr_status.py, tests/test_get_pr_status.py, get_pr_status.py
New gh pr view-based PR status script with tests; older root-level script removed.
Concurrent classifier benchmark
scripts/benchmark_classifier.py
Switches classification benchmarking to a ThreadPoolExecutor-based concurrent run.

Agent Policy and Regression Analysis Docs

Layer / File(s) Summary
Agent conflict-resolution policy and regression analysis
.agents/AGENTS.md, .agents/jules_regression_analysis.md
Adds rebase/conflict-resolution policy rules and a regression root-cause analysis document.

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

Sequence Diagram(s)

sequenceDiagram
  participant TryAgyProxy
  participant IsQuotaExhausted
  participant CliLog

  TryAgyProxy->>IsQuotaExhausted: await _is_quota_exhausted()
  IsQuotaExhausted->>CliLog: aiofiles.open + async seek/read
  CliLog-->>IsQuotaExhausted: log tail content
  IsQuotaExhausted-->>TryAgyProxy: exhausted True/False
Loading
sequenceDiagram
  participant SaveAnnotations
  participant ReadAnnotationsAsync
  participant AnnotationsCache
  participant AiofilesIO

  SaveAnnotations->>ReadAnnotationsAsync: load existing annotations
  ReadAnnotationsAsync->>AnnotationsCache: check mtime/cache
  AnnotationsCache-->>ReadAnnotationsAsync: cache hit or miss
  ReadAnnotationsAsync->>AiofilesIO: async read + parse JSON (on miss)
  AiofilesIO-->>ReadAnnotationsAsync: parsed data
  ReadAnnotationsAsync-->>SaveAnnotations: deep-copied data
  SaveAnnotations->>AnnotationsCache: invalidate entry after write
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is specific and accurately reflects the main changes: restoring tests, structure, optimizations, and security patches.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/restore-reversions-final-v4

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.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces comprehensive updates to address merge regressions, enhance security, and optimize performance. Key changes include implementing a Git rebase and conflict resolution policy, replacing hardcoded credentials in pod.yaml with dynamically generated placeholders in start-stack.sh, upgrading several service images (including LiteLLM to v1.90.2), and offloading blocking synchronous operations (such as AA scores loading and annotations reading) to asynchronous tasks using aiofiles and thread pools. Additionally, token estimation was improved with a regex-based weighted heuristic, memory MCP keys were secured via URL-encoding, and test coverage was significantly expanded. Feedback on these changes highlights a critical issue in start-stack.sh where moving the openssl check down causes the script to crash during early password generation if openssl is missing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread start-stack.sh Outdated
Comment on lines 34 to 35


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.

high

The openssl check was moved from the top of the script to line 98 [1]. However, POSTGRES_PASSWORD is generated at line 56 using openssl rand -hex 16 [1]. If openssl is not installed, the script will crash with a command not found error at line 56 (due to set -e being active) before ever reaching the check at line 98 [1].

To prevent this, the openssl check should be restored at the top of the script (before any password generation occurs) and expanded to cover all the new variables that require it [1].

Suggested change
if [ -z "$POSTGRES_PASSWORD" ] || [ -z "$NEXTAUTH_SECRET" ] || [ -z "$SALT" ] || [ -z "$ENCRYPTION_KEY" ] || [ -z "$LITELLM_MASTER_KEY" ] || [ -z "$ROUTER_API_KEY" ] || [ -z "$MINIO_ROOT_USER" ] || [ -z "$MINIO_ROOT_PASSWORD" ] || [ -z "$LANGFUSE_INIT_USER_PASSWORD" ] || [ -z "$REDIS_AUTH" ] || [ -z "$CLICKHOUSE_PASSWORD" ] || [ -z "$LANGFUSE_PUBLIC_KEY" ] || [ -z "$LANGFUSE_SECRET_KEY" ]; then
if ! command -v openssl &>/dev/null; then
echo "❌ Error: 'openssl' is required to generate secure random keys but was not found in PATH."
exit 1
fi
fi

@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: 4

🧹 Nitpick comments (9)
tests/test_host_agy_daemon.py (1)

75-490: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract a request-helper to reduce duplication.

Nearly every test manually builds a urllib.request.Request and issues urlopen, repeating the same boilerplate (~15 occurrences). A small helper like post_run(daemon_server, payload) returning either the parsed JSON or raw NDJSON lines would cut duplication significantly and make future daemon contract changes easier to update in one place.

♻️ Example helper
def post_run(base_url, payload):
    req = urllib.request.Request(
        f"{base_url}/run",
        data=json.dumps(payload).encode("utf-8"),
        headers={"Content-Type": "application/json"},
    )
    with urllib.request.urlopen(req) as resp:
        return resp.read().decode()
🤖 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 `@tests/test_host_agy_daemon.py` around lines 75 - 490, A lot of the tests in
test_host_agy_daemon.py repeat the same Request/urlopen boilerplate for the /run
endpoint. Add a small helper (for example, around the existing daemon test
setup) that builds the urllib.request.Request, posts the payload, and returns
the response body or parsed result, then replace the repeated setup in the
test_* cases with that helper. Keep the helper generic enough to support both
the JSON response and NDJSON stream cases so future changes only need to be
updated in one place.
.agents/jules_regression_analysis.md (1)

46-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use porcelain git output for the post-conflict check.

git status | grep ... is brittle and can vary with human-readable formatting. A porcelain/status-name-status command will make this verification deterministic.

♻️ Proposed fix
- git status | grep -E "renamed:|deleted:|new file:"
+ git status --porcelain=v1
🤖 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 @.agents/jules_regression_analysis.md around lines 46 - 65, Replace the
post-conflict verification step in the recommended guardrails with a
porcelain-based git status check instead of parsing human-readable output, since
the current grep approach in the File Integrity & Verification Checklist is
brittle. Update the workflow text around the verification script to use a
deterministic status format and make sure the rule still focuses on detecting
unexpected renames, deletions, or new files after conflict resolution.
.agents/AGENTS.md (1)

22-28: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Prefer rebase over merge, don't mandate it absolutely.

This rule conflicts with the fallback merge-driver path described in .agents/jules_regression_analysis.md. Make it a preference or add an explicit exception so the policy stays internally consistent.

♻️ Proposed wording
-1. **Rebase Over Merge**: Always fetch and rebase the topic/feature branch onto the latest `master` base branch (using `git rebase origin/master`) instead of performing `git merge`.
+1. **Prefer Rebase Over Merge**: Fetch and rebase the topic/feature branch onto the latest `master` base branch when possible. If merge is unavoidable, inspect renames and use explicit merge drivers.
🤖 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 @.agents/AGENTS.md around lines 22 - 28, Update the Git conflict policy in
AGENTS.md so “rebase over merge” is a preference rather than an absolute
requirement, and add an explicit exception for the fallback merge-driver path
referenced in jules_regression_analysis.md. Keep the rest of the rules intact,
but rewrite the Rebase Over Merge item to allow merge when that documented
fallback applies, so the policy stays consistent with the existing
conflict-resolution flow.
router/memory_mcp.py (1)

75-79: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding direct test coverage for the non-string guard.

The isinstance check is a good defensive fix, but the provided test suite doesn't appear to exercise _is_memory_key with a non-string input directly.

🤖 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 `@router/memory_mcp.py` around lines 75 - 79, Add direct test coverage for the
non-string guard in _is_memory_key by calling it with a non-string input and
asserting it returns False. Update the tests that cover the PREFIX-based memory
key logic so they explicitly exercise the isinstance(key, str) path, not just
string inputs.
router/main.py (2)

92-145: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant int() wrapping around round().

round(total) on a float already returns an int in Python 3 (no ndigits supplied), so the outer int() at Line 145 is a no-op. Matches the Ruff RUF046 hint.

♻️ Proposed cleanup
-    return max(1, int(round(total)) + 50)
+    return max(1, round(total) + 50)
🤖 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 `@router/main.py` around lines 92 - 145, Remove the redundant int() cast in
estimate_prompt_tokens: round(total) already returns an int in Python 3, so
simplify the final return expression in that function to avoid the no-op and
satisfy the Ruff RUF046 warning. Keep the rest of _count_tokens_heuristic and
estimate_prompt_tokens unchanged.

Source: Linters/SAST tools


3920-3939: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Cache invalidation relies on os.path.getmtime resolution.

External modifications to the annotations file (outside save_annotations, which explicitly invalidates its own cache entry) that occur within the filesystem's mtime resolution window would not be detected, returning stale cached data. This is a narrow edge case given typical Linux mtime precision, but worth noting given the cache never expires 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 `@router/main.py` around lines 3920 - 3939, The cache in
_read_annotations_async only invalidates on os.path.getmtime, so external edits
can be missed when mtime granularity is too coarse. Update the cache
keying/invalidation logic around _annotations_cache and _read_annotations_async
to use a stronger change check (for example, include file size or content hash,
or always refresh when there is any doubt) so the function does not return stale
annotation data. Ensure the existing deepcopy return behavior remains unchanged.
scripts/benchmark_classifier.py (3)

57-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move imports to top of file.

import concurrent.futures / import threading are added mid-script rather than with the other top-level imports.

🤖 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/benchmark_classifier.py` around lines 57 - 58, The new
concurrent.futures and threading imports are placed mid-script instead of with
the other module imports at the top. Move them into the top-level import block
alongside the existing imports in benchmark_classifier.py so the import section
is consistent and easy to locate.

96-103: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate confusion[...] += 1 in both branches.

The increment is repeated in both the if/else branches; hoist it outside to avoid duplication.

♻️ Proposed simplification
-        if expected not in per_tier:
-            confusion[expected][predicted] += 1
-        else:
+        if expected in per_tier:
             per_tier[expected]["total"] += 1
             if predicted == expected:
                 correct += 1
                 per_tier[expected]["correct"] += 1
-            confusion[expected][predicted] += 1
+        confusion[expected][predicted] += 1
🤖 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/benchmark_classifier.py` around lines 96 - 103, The confusion matrix
increment is duplicated in both branches of the classification loop, so simplify
the logic in the benchmark_classifier flow by hoisting the
confusion[expected][predicted] increment out of the if/else. Keep the existing
per_tier bookkeeping and correct counter updates in the expected-in-per_tier
path, but ensure the shared confusion update happens once after the branch in
the same loop.

73-84: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Rate limit only staggers start time, doesn't cap concurrent requests.

rate_limit_lock wraps only time.sleep(0.05), not the classify() call itself, so once each thread's brief sleep completes, up to max_workers=20 requests can hit the local classifier server concurrently. If throttling actual concurrent load was the intent, consider bounding concurrent in-flight requests (e.g., a Semaphore(N) around classify()) rather than just staggering submission.

♻️ Example: bound concurrent classify() calls with a semaphore
-with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
-    rate_limit_lock = threading.Lock()
-
-    def process_item_with_rate_limit(index_and_item):
-        i, item = index_and_item
-        with rate_limit_lock:
-            time.sleep(0.05)
-
-        expected, predicted = process_item(item)
-        return i, item, expected, predicted
+with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:
+    request_semaphore = threading.Semaphore(5)  # cap concurrent in-flight classify() calls
+
+    def process_item_with_rate_limit(index_and_item):
+        i, item = index_and_item
+        with request_semaphore:
+            expected, predicted = process_item(item)
+        return i, item, expected, predicted
🤖 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/benchmark_classifier.py` around lines 73 - 84, The current throttling
in process_item_with_rate_limit only delays thread start and does not limit
simultaneous classify() calls, so concurrent requests can still spike up to
ThreadPoolExecutor capacity. Update benchmark_classifier.py to bound in-flight
work by guarding the actual process_item/classify path with a Semaphore (or
equivalent concurrency limiter) instead of only wrapping time.sleep() with
rate_limit_lock. Keep the change centered around process_item_with_rate_limit
and the executor submission loop so the classifier server sees a fixed maximum
concurrent load.
🤖 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 `@litellm/entrypoint.py`:
- Around line 107-118: The Prisma serializer setup in entrypoint.py is
swallowing registration failures because the blanket except Exception hides
errors from serializer.register and makes the datetime workaround silently do
nothing. Update the try block around prisma.builder import and the _serialize_dt
registration logic to catch only ImportError, and let any serializer.register
failure surface so issues are visible when registering original_datetime and
RobustDatetime.

In `@README.md`:
- Line 272: Update the ClickHouse version pin in the README version-pinning
paragraph so it matches the image tag currently used in pod.yaml. The mismatch
is in the ClickHouse entry within the Version Pinning section; change the
documented ClickHouse version from the old tag to the exact pinned tag used by
the pod configuration, keeping the rest of the paragraph unchanged.

In `@start-stack.sh`:
- Around line 155-165: The generated Redis and ClickHouse secrets in
start-stack.sh are written to the env file but never propagated into the
rendered pod, so the runtime still uses static credentials. Update the startup
flow around the secret generation block to export or substitute REDIS_AUTH and
CLICKHOUSE_PASSWORD into the pod rendering step, and make the pod.yaml template
reference those placeholders instead of hardcoded passwords. Ensure the values
produced in start-stack.sh are the same ones consumed by the pod template and
any validation/replacement logic.
- Around line 469-471: The password encoding in the DATABASE_URL assembly is
incomplete because urllib.parse.quote in start-stack.sh leaves "/" unescaped,
which can break the DSN userinfo. Update the encoding logic around the
POSTGRES_PASSWORD_ENCODED_PLACEHOLDER replacement to use urllib.parse.quote with
safe="" so the encoded password is fully safe for insertion into the postgres
URL.

---

Nitpick comments:
In @.agents/AGENTS.md:
- Around line 22-28: Update the Git conflict policy in AGENTS.md so “rebase over
merge” is a preference rather than an absolute requirement, and add an explicit
exception for the fallback merge-driver path referenced in
jules_regression_analysis.md. Keep the rest of the rules intact, but rewrite the
Rebase Over Merge item to allow merge when that documented fallback applies, so
the policy stays consistent with the existing conflict-resolution flow.

In @.agents/jules_regression_analysis.md:
- Around line 46-65: Replace the post-conflict verification step in the
recommended guardrails with a porcelain-based git status check instead of
parsing human-readable output, since the current grep approach in the File
Integrity & Verification Checklist is brittle. Update the workflow text around
the verification script to use a deterministic status format and make sure the
rule still focuses on detecting unexpected renames, deletions, or new files
after conflict resolution.

In `@router/main.py`:
- Around line 92-145: Remove the redundant int() cast in estimate_prompt_tokens:
round(total) already returns an int in Python 3, so simplify the final return
expression in that function to avoid the no-op and satisfy the Ruff RUF046
warning. Keep the rest of _count_tokens_heuristic and estimate_prompt_tokens
unchanged.
- Around line 3920-3939: The cache in _read_annotations_async only invalidates
on os.path.getmtime, so external edits can be missed when mtime granularity is
too coarse. Update the cache keying/invalidation logic around _annotations_cache
and _read_annotations_async to use a stronger change check (for example, include
file size or content hash, or always refresh when there is any doubt) so the
function does not return stale annotation data. Ensure the existing deepcopy
return behavior remains unchanged.

In `@router/memory_mcp.py`:
- Around line 75-79: Add direct test coverage for the non-string guard in
_is_memory_key by calling it with a non-string input and asserting it returns
False. Update the tests that cover the PREFIX-based memory key logic so they
explicitly exercise the isinstance(key, str) path, not just string inputs.

In `@scripts/benchmark_classifier.py`:
- Around line 57-58: The new concurrent.futures and threading imports are placed
mid-script instead of with the other module imports at the top. Move them into
the top-level import block alongside the existing imports in
benchmark_classifier.py so the import section is consistent and easy to locate.
- Around line 96-103: The confusion matrix increment is duplicated in both
branches of the classification loop, so simplify the logic in the
benchmark_classifier flow by hoisting the confusion[expected][predicted]
increment out of the if/else. Keep the existing per_tier bookkeeping and correct
counter updates in the expected-in-per_tier path, but ensure the shared
confusion update happens once after the branch in the same loop.
- Around line 73-84: The current throttling in process_item_with_rate_limit only
delays thread start and does not limit simultaneous classify() calls, so
concurrent requests can still spike up to ThreadPoolExecutor capacity. Update
benchmark_classifier.py to bound in-flight work by guarding the actual
process_item/classify path with a Semaphore (or equivalent concurrency limiter)
instead of only wrapping time.sleep() with rate_limit_lock. Keep the change
centered around process_item_with_rate_limit and the executor submission loop so
the classifier server sees a fixed maximum concurrent load.

In `@tests/test_host_agy_daemon.py`:
- Around line 75-490: A lot of the tests in test_host_agy_daemon.py repeat the
same Request/urlopen boilerplate for the /run endpoint. Add a small helper (for
example, around the existing daemon test setup) that builds the
urllib.request.Request, posts the payload, and returns the response body or
parsed result, then replace the repeated setup in the test_* cases with that
helper. Keep the helper generic enough to support both the JSON response and
NDJSON stream cases so future changes only need to be updated in one place.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4bd49b8-9188-4c44-89f8-87bcc81141d2

📥 Commits

Reviewing files that changed from the base of the PR and between c304f3d and b0a8605.

⛔ Files ignored due to path filters (1)
  • debug-homepage.png is excluded by !**/*.png
📒 Files selected for processing (51)
  • .agents/AGENTS.md
  • .agents/branch_audit_plan.md
  • .agents/jules_regression_analysis.md
  • .github/workflows/test.yml
  • README.md
  • get_pr_status.py
  • litellm/entrypoint.py
  • pod.yaml
  • router/Dockerfile
  • router/agy_proxy.py
  • router/main.py
  • router/memory_mcp.py
  • router/test_memory_mcp.py
  • router/tests/test_agy_proxy.py
  • router/tests/test_detect_active_tool.py
  • router/tests/test_estimate_prompt_tokens.py
  • router/tests/test_get_gemini_oauth_status.py
  • router/tests/test_get_goose_sessions.py
  • router/tests/test_get_redis.py
  • router/tests/test_load_persisted_stats.py
  • router/tests/test_memory_mcp.py
  • scripts/README.md
  • scripts/benchmark_classifier.py
  • scripts/benchmark_tokens.py
  • scripts/get_pr_status.py
  • scripts/host_agy_daemon.py
  • scripts/sync_gemini_token.py
  • scripts/test_quota_reset.sh
  • scripts/verification/verify_breaker.py
  • scripts/watch_quota.sh
  • start-stack.sh
  • test_memory_mcp.py
  • tests/test_a2_verify.py
  • tests/test_agy_behavior.py
  • tests/test_agy_tiers.py
  • tests/test_antigravity.py
  • tests/test_atomic_write.py
  • tests/test_check_http_endpoint.py
  • tests/test_circuit_breaker.py
  • tests/test_classifier_accuracy.py
  • tests/test_compute_free_model_score.py
  • tests/test_get_pr_status.py
  • tests/test_host_agy_daemon.py
  • tests/test_map_tool_to_category.py
  • tests/test_models_proxy.py
  • tests/test_pie_chart_gradient.py
  • tests/test_read_annotations_async.py
  • tests/test_record_tool_usage.py
  • tests/test_src_badge.py
  • tests/test_stream_latency.py
  • tests/test_sync_gemini_token.py
💤 Files with no reviewable changes (3)
  • router/test_memory_mcp.py
  • test_memory_mcp.py
  • get_pr_status.py

Comment thread litellm/entrypoint.py Outdated
Comment thread README.md Outdated
Comment thread start-stack.sh
Comment on lines +155 to +165
if [ -z "$REDIS_AUTH" ]; then
REDIS_AUTH="$(openssl rand -hex 16)"
echo "REDIS_AUTH=\"$REDIS_AUTH\"" >> "$ENV_FILE"
echo "✓ Generated new REDIS_AUTH and saved to $ENV_FILE"
fi

if [ -z "$CLICKHOUSE_PASSWORD" ]; then
CLICKHOUSE_PASSWORD="$(openssl rand -hex 16)"
echo "CLICKHOUSE_PASSWORD=\"$CLICKHOUSE_PASSWORD\"" >> "$ENV_FILE"
echo "✓ Generated new CLICKHOUSE_PASSWORD and saved to $ENV_FILE"
fi

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Wire generated Redis and ClickHouse secrets into the rendered pod.

REDIS_AUTH and CLICKHOUSE_PASSWORD are generated but never exported, validated as placeholders, or substituted, so the rendered pod keeps the static Redis/ClickHouse credentials and the new .env values drift from runtime config.

Proposed fix
-    export WORKDIR HOME LITELLM_MASTER_KEY POSTGRES_PASSWORD NEXTAUTH_SECRET SALT ENCRYPTION_KEY LANGFUSE_INIT_USER_PASSWORD MINIO_ROOT_USER MINIO_ROOT_PASSWORD OLLAMA_API_KEY LANGFUSE_PUBLIC_KEY LANGFUSE_SECRET_KEY
+    export WORKDIR HOME LITELLM_MASTER_KEY POSTGRES_PASSWORD NEXTAUTH_SECRET SALT ENCRYPTION_KEY LANGFUSE_INIT_USER_PASSWORD MINIO_ROOT_USER MINIO_ROOT_PASSWORD OLLAMA_API_KEY LANGFUSE_PUBLIC_KEY LANGFUSE_SECRET_KEY REDIS_AUTH CLICKHOUSE_PASSWORD
@@
     "MINIO_USER_PLACEHOLDER",
     "MINIO_PASSWORD_PLACEHOLDER",
-    "LANGFUSE_INIT_USER_PASSWORD_PLACEHOLDER"
+    "LANGFUSE_INIT_USER_PASSWORD_PLACEHOLDER",
+    "REDIS_AUTH_PLACEHOLDER",
+    "CLICKHOUSE_PASSWORD_PLACEHOLDER"
 ]
@@
 text = text.replace("MINIO_PASSWORD_PLACEHOLDER", os.environ["MINIO_ROOT_PASSWORD"])
 text = text.replace("LANGFUSE_INIT_USER_PASSWORD_PLACEHOLDER", os.environ["LANGFUSE_INIT_USER_PASSWORD"])
+text = text.replace("REDIS_AUTH_PLACEHOLDER", os.environ["REDIS_AUTH"])
+text = text.replace("CLICKHOUSE_PASSWORD_PLACEHOLDER", os.environ["CLICKHOUSE_PASSWORD"])

Also update the corresponding pod.yaml template values from the static Redis/ClickHouse passwords to those placeholders.

Also applies to: 437-480

🤖 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 `@start-stack.sh` around lines 155 - 165, The generated Redis and ClickHouse
secrets in start-stack.sh are written to the env file but never propagated into
the rendered pod, so the runtime still uses static credentials. Update the
startup flow around the secret generation block to export or substitute
REDIS_AUTH and CLICKHOUSE_PASSWORD into the pod rendering step, and make the
pod.yaml template reference those placeholders instead of hardcoded passwords.
Ensure the values produced in start-stack.sh are the same ones consumed by the
pod template and any validation/replacement logic.

Comment thread start-stack.sh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant