Skip to content

fix(depends): allow a CPU-only dependency resolve, opt-in - #1708

Open
kwit75 wants to merge 1 commit into
developfrom
fix/cpu-only-torch-for-cloud
Open

fix(depends): allow a CPU-only dependency resolve, opt-in#1708
kwit75 wants to merge 1 commit into
developfrom
fix/cpu-only-torch-for-cloud

Conversation

@kwit75

@kwit75 kwit75 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

The cloud ALB carries 6.6 GB of CUDA it cannot executenvidia 4.3G, torch 1.7G, triton 639M: 80% of its 8.2 GB site-packages. The pod is an m7i-flex.large with no GPU capacity and no /dev/nvidia*, and it holds no models — inference goes out to the H100. That runtime is downloaded and written on every pod start and has never once run. It is the root of the DiskPressure incidents (#1697).

Adds ROCKETRIDE_CPU_ONLY_DEPS. When set, the compile input gains --extra-index-url https://download.pytorch.org/whl/cpu, so torch resolves to +cpu (~200 MB) and the nvidia-* packages are never selected.

Three things had to line up — I knew about two

  1. torch — no node declares it; it arrives transitively via gliner / transformers / accelerate, and PyPIs default wheel is the CUDA build.
  2. anonymize declares onnxruntime-gpu; platform_system != Darwin.
  3. This file excluded plain onnxruntime on every non-Darwin host — which would have defeated a fix to (2) outright. The CPU build could not be installed even if something asked for it.

(3) I found while implementing, not while diagnosing, and it is the one worth reviewing: "not a Mac" was being used as a proxy for "has CUDA", which is wrong on every Linux box without a GPU. The exclusion now honours the flag, and on a CPU-only host excludes the GPU build instead — same clobbering logic, correct direction.

Opt-in, deliberately not auto-detected

Inferring "no GPU visible, therefore CPU" would silently downgrade a host whose driver simply has not loaded yet. A silent downgrade of an inference machine is far worse than an oversized install. The cloud sets the flag; self-hosted users with a GPU are untouched — which is the point, and why this is not a hardcoded CPU default in node requirements.

Verification — what is proven and what is not

Proven

  • The resolve: uv pip compile over the four torch-pulling nodes, targeting x86_64-manylinux2014/cp312 — 119 packages / 13 nvidia-* on the default index, 105 / 0 with this exact flag. No conflicts.
  • The line the code emits is byte-identical to the flag I resolved with.

Not proven

  • That _combine_requirements() runs correctly here. The module imports engine dependencies I dont have locally, so both branches of the flag are unexercised — I read the diff rather than ran it.
  • That the four nodes still work on torch+cpu. torch+cpu raises when CUDA is actually requested, not at import, so a green resolve is not evidence.

Do not set the flag in the cloud until that functional run is done. The saving (8.2 GB → ~1.8 GB, node 84% → ~15-20%) is worth having, and not worth guessing at.

Refs #1697.

Summary by CodeRabbit

  • New Features
    • Added an opt-in CPU-only dependency installation mode.
    • CPU-only mode directs PyTorch installation toward CPU wheels instead of CUDA-enabled builds.
    • Updated runtime package selection to avoid installing GPU-specific ONNX Runtime packages in CPU-only environments.

@github-actions

Copy link
Copy Markdown
Contributor
🤖 Internal: Discord sync marker

Auto-managed by the Discord notification workflow. Stores the linked Discord message ID and forum thread ID. Do not edit or delete.

@github-actions github-actions Bot added module:server C++ engine and server components module:nodes Python pipeline nodes labels Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Dependency resolution now supports an environment-controlled CPU-only mode that adds CPU PyTorch wheel directives and adjusts non-macOS ONNX Runtime exclusions.

Changes

CPU-only dependency resolution

Layer / File(s) Summary
CPU-only requirement and exclusion handling
packages/server/engine-lib/rocketlib-python/lib/depends.py
ROCKETRIDE_CPU_ONLY_DEPS enables CPU PyTorch resolution directives and causes non-macOS installation exclusions to target onnxruntime-gpu instead of onnxruntime.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: jmaionchi, stepmikhaylov, rod-christensen

🚥 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 clearly describes the main change: an opt-in CPU-only dependency resolution mode in depends.py.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cpu-only-torch-for-cloud

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.

@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

🤖 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 `@nodes/src/nodes/tool_google_workspace/gmail/IInstance.py`:
- Line 149: The Gmail connection check in the IInstance implementation currently
probes users.getProfile unconditionally, which fails for send-only
configurations. Update the _check_connection_impl call and its probe logic to
use an API permitted by the configured access tier, or return an unknown
diagnostic for gmail.send-only access while preserving the existing profile
probe for broader scopes.

In `@nodes/src/nodes/tool_google_workspace/IInstance.py`:
- Around line 103-114: Update the API probe block in execute() so
out['checked'].append('api') occurs before calling probe(service). Preserve the
existing exception handling and error/errorReason extraction, ensuring failed
probes still record the API check while reporting the raised diagnostic.

In `@packages/server/engine-lib/rocketlib-python/lib/depends.py`:
- Around line 691-704: The ensure_constraints() cache key currently hashes only
requirement files, so changes to _cpu_only() can reuse stale CPU/GPU
constraints. Include the normalized CPU-only state in that key, and add
regression coverage for both GPU-to-CPU and CPU-to-GPU transitions while
preserving the existing cache behavior for unchanged inputs.
- Around line 699-704: Update the CPU-only dependency output in the code
generating this block so PyTorch packages resolve exclusively from the CPU index
rather than competing with PyPI candidates under unsafe-best-match. Use the
existing ROCKETRIDE_CPU_ONLY_DEPS path and explicitly constrain torch and
related PyTorch packages to the CPU index, while preserving the current non-CPU
dependency behavior.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: c97b7df2-2ccd-401a-be92-2b58a1c0d17d

📥 Commits

Reviewing files that changed from the base of the PR and between 1483794 and 24b8f58.

📒 Files selected for processing (4)
  • nodes/src/nodes/tool_google_workspace/IInstance.py
  • nodes/src/nodes/tool_google_workspace/drive/IInstance.py
  • nodes/src/nodes/tool_google_workspace/gmail/IInstance.py
  • packages/server/engine-lib/rocketlib-python/lib/depends.py

def check_connection(self, args: dict) -> dict:
"""Check Gmail connection status and whether granted OAuth scopes cover the configured access tier. Read-only."""
return self._check_connection_impl()
return self._check_connection_impl(probe=lambda s: execute(s.users().getProfile(userId='me')))

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
fd -a 'IInstance.py' . || true

echo "== target file excerpt =="
file="$(fd 'IInstance.py' . | head -n1 || true)"
if [ -n "${file:-}" ]; then
  wc -l "$file"
  sed -n '1,220p' "$file" | cat -n
fi

echo "== search for Gmail probe/send requirements =="
rg -n "gmail|getProfile|_require_send|connection_ok|probe=lambda|require_send" . --glob '*.py' || true

Repository: rocketride-org/rocketride-server

Length of output: 37844


🌐 Web query:

Gmail API users.getProfile required OAuth scopes gmail.send gmail.compose gmail.modify gmail.readonly gmail.metadata

💡 Result:

The Gmail API method users.getProfile requires at least one of the following OAuth 2.0 scopes [1][2]: - https://mail.google.com/ - https://www.googleapis.com/auth/gmail.modify - https://www.googleapis.com/auth/gmail.compose - https://www.googleapis.com/auth/gmail.readonly - https://www.googleapis.com/auth/gmail.metadata You do not need to request all of these scopes simultaneously. To adhere to the principle of least privilege, you should select the narrowest scope that meets your application's requirements [3]. If your application only needs to read profile information (such as the user's email address and message counts), the gmail.metadata or gmail.readonly scope is typically sufficient [1][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file='nodes/src/nodes/tool_google_workspace/gmail/IInstance.py'
echo "== target excerpt 70-155 =="
sed -n '70,155p' "$file" | cat -n

echo "== target excerpt 590-630 =="
sed -n '590,630p' "$file" | cat -n

echo "== implementation helpers in parent/base if applicable =="
base='nodes/src/nodes/tool_google_workspace/IInstance.py'
sed -n '70,145p' "$base" | cat -n

echo "== google access scope definitions =="
sed -n '120,175p' nodes/src/nodes/core/google_access.py | cat -n

Repository: rocketride-org/rocketride-server

Length of output: 14351


Do not probe Gmail with users.getProfile for send-only connections.

users.getProfile requires mail.google.com, gmail.modify, gmail.compose, gmail.readonly, or gmail.metadata; gmail.send alone is not accepted. Since _require_send only checks for gmail.send or full access, a send-only config can satisfy the required scopes for operations but still report connection_ok: false from the diagnostics probe. Use a probe allowed by the configured access tier, or return unknown for send-only checks instead of running this unsupported API call.

🤖 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 `@nodes/src/nodes/tool_google_workspace/gmail/IInstance.py` at line 149, The
Gmail connection check in the IInstance implementation currently probes
users.getProfile unconditionally, which fails for send-only configurations.
Update the _check_connection_impl call and its probe logic to use an API
permitted by the configured access tier, or return an unknown diagnostic for
gmail.send-only access while preserving the existing profile probe for broader
scopes.

Comment on lines +103 to +114
try:
probe(service)
out['checked'].append('api')
except Exception as exc:
out['connection_ok'] = False
out['error'] = str(exc)[:200]
# Google distinguishes accessNotConfigured (API disabled) from
# forbidden (permission) from rateLimitExceeded, and that word
# alone names the fix. Losing it costs the reader the diagnosis.
reason = getattr(exc, 'reason', None) or getattr(exc, '_get_reason', lambda: None)()
if reason:
out['errorReason'] = str(reason).strip()[:120]

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file =="
fd -a 'IInstance\.py$' . || true

echo "== file exists? =="
if [ -f nodes/src/nodes/tool_google_workspace/IInstance.py ]; then
  wc -l nodes/src/nodes/tool_google_workspace/IInstance.py
  echo "== relevant section =="
  sed -n '1,180p' nodes/src/nodes/tool_google_workspace/IInstance.py | cat -n
fi

echo "== searches for google_client and probe =="
rg -n "google_client|execute\(|probe\(|checked|errorReason|_get_reason|reason" nodes/src/nodes/tool_google_workspace IInstance.py . --glob '*.py' || true

Repository: rocketride-org/rocketride-server

Length of output: 50389


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== google_client execute implementation =="
sed -n '380,435p' nodes/src/nodes/tool_google_workspace/google_client.py | cat -n

echo "== google_client imports and _is_rate_limit_403 imports =="
sed -n '1,80p' nodes/src/nodes/tool_google_workspace/google_client.py | cat -n

echo "== Python probe-except behavior from source =="
python3 - <<'PY'
import ast
from pathlib import Path

p = Path('nodes/src/nodes/tool_google_workspace/google_client.py')
tree = ast.parse(p.read_text())
for node in tree.body:
    if isinstance(node, ast.FunctionDef) and node.name == 'execute':
        print(node.name, node.lineno, 'to', node.end_lineno)
        for stmt in node.body:
            print(' ', ast.get_source_segment(p.read_text(), stmt))
PY

echo "== behavioral probe: current source pattern =="
python3 - <<'PY'
def current_probe_impl():
    class Original(Exception):
        reason = 'apiDisabled'
        def _get_reason(self):
            return 'neverCalled'

    def probe(service):
        raise Original

    out = {}
    try:
        probe(service={})
        out['checked'].append('api')
    except Exception as exc:
        out['connection_ok'] = False
        out['error'] = str(exc)[:200]
        reason = getattr(exc, 'reason', None) or getattr(exc, '_get_reason', lambda: None)()
        if reason:
            out['errorReason'] = str(reason).strip()[:120]
    return out

def proposed_probe_impl():
    class Original(Exception):
        reason = 'apiDisabled'
        def _get_reason(self):
            return 'neverCalled'

    def probe(service):
        raise Original

    exc = None
    try:
        raise RuntimeError('probe ran')
    except Exception as e:
        exc = e

    out = {}
    try:
        out['checked'].append('api')
        raise exc
    except Exception as exc2:
        out['connection_ok'] = False
        out['error'] = str(exc2)[:200]
        cause = getattr(exc2, '__cause__', None) or exc2
        # simulate current cause being the original wrapper is gone from exc2
        # by keeping exc as the preserved exc.__cause__ is None / exc2 itself here.
        reason = getattr(cause, 'reason', None)
        if not reason:
            get_reason = getattr(cause, '_get_reason', None)
            reason = get_reason() if callable(get_reason) else None
        if reason:
            out['errorReason'] = str(reason).strip()[:120]
    return out

print('current', current_probe_impl())
# Build a wrapper around the exact original so exc.__cause__ is the Original exception.
orig = Original = type('Original', (Exception,), {'reason': 'apiDisabled', '_get_reason': lambda self: 'neverCalled'})
try:
    try:
        raise orig
    except Exception as inner:
        raise ValueError('wrapper') from inner
except Exception as exc:
    print('wrapper cause present:', exc.__cause__ is not None and getattr(exc.__cause__, 'reason', None))
PY

Repository: rocketride-org/rocketride-server

Length of output: 9089


Record the API probe result before checking it fails.

execute() wraps Google API HttpErrors in ValueError with the original exception available as __cause__, but also includes the diagnostic detail like accessNotConfigured/rate-limit reasons in the raised message. If probe(service) raises, checked currently stays at ['client', 'scopes'], making a failed live request look unprobed. Call probe only after appending "api" to checked.

🤖 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 `@nodes/src/nodes/tool_google_workspace/IInstance.py` around lines 103 - 114,
Update the API probe block in execute() so out['checked'].append('api') occurs
before calling probe(service). Preserve the existing exception handling and
error/errorReason extraction, ensuring failed probes still record the API check
while reporting the raised diagnostic.

Comment thread packages/server/engine-lib/rocketlib-python/lib/depends.py
Comment thread packages/server/engine-lib/rocketlib-python/lib/depends.py
The cloud ALB carries 6.6 GB of CUDA it cannot execute — nvidia 4.3G, torch
1.7G, triton 639M, which is 80% of its 8.2 GB site-packages. The pod runs on an
m7i-flex.large with no GPU capacity and no /dev/nvidia*, and it holds no models
at all: inference goes out to the H100 behind model.rocketride.dev. That
runtime is downloaded and written on every pod start and has never once been
executed. It is the root of the DiskPressure incidents (#1697).

Adds ROCKETRIDE_CPU_ONLY_DEPS. When set, the compile input gains
`--extra-index-url https://download.pytorch.org/whl/cpu`, so torch resolves to
+cpu (~200 MB) and the nvidia-* packages are never selected.

THREE things had to line up, and I only knew about two when I filed the issue:

  1. torch — no node declares it; it arrives transitively through gliner /
     transformers / accelerate. PyPI's default wheel is the CUDA build.
  2. anonymize declares `onnxruntime-gpu; platform_system != 'Darwin'`.
  3. THIS FILE excluded plain `onnxruntime` on every non-Darwin host, which
     would have defeated a fix to (2) — the CPU build could not be installed
     even if something asked for it. Found while implementing, not while
     diagnosing.

(3) is the interesting one: "not a Mac" was being used as a proxy for "has
CUDA", and that is wrong on every Linux box without a GPU. The exclusion now
honours the flag, and on a CPU-only host it excludes the GPU build instead —
same clobbering logic, correct direction.

Opt-in, NOT auto-detected. Inferring "no GPU visible, therefore CPU" would
silently downgrade a host whose driver merely has not loaded yet, and a silent
downgrade of an inference machine is far worse than an oversized install. The
cloud sets the flag; self-hosted users with a GPU are untouched, which is the
whole point — this must not become a hardcoded CPU default in node
requirements.

VERIFICATION, stated precisely:

  * PROVEN — the resolve. `uv pip compile` over the four nodes that pull torch,
    targeting x86_64-manylinux2014/cp312: 119 packages / 13 nvidia-* with the
    default index, 105 / 0 with this exact flag string. No conflicts.
  * PROVEN — the emitted line is byte-identical to the flag I resolved with.
  * NOT PROVEN — that _combine_requirements() runs correctly here. The module
    imports engine dependencies I do not have locally, so both branches of the
    flag are unexercised; I read the diff rather than ran it.
  * NOT PROVEN — that the four nodes still work on torch+cpu. torch+cpu raises
    when CUDA is actually requested, not at import, so a green resolve is not
    evidence. This needs a functional run before it is enabled anywhere.

Do not set the flag in the cloud until that functional run is done. The
measured saving (8.2 GB -> ~1.8 GB) is worth having, but not worth guessing at.

Refs #1697.
@kwit75
kwit75 force-pushed the fix/cpu-only-torch-for-cloud branch from 24b8f58 to ae0b3f0 Compare July 28, 2026 20:43
@github-actions github-actions Bot removed the module:nodes Python pipeline nodes label Jul 28, 2026
@kwit75

kwit75 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator Author

The functional verification this was waiting on — done

The PR body says a clean dependency resolve is not proof, because torch+cpu raises when CUDA is requested, not at import. So I built the resolve and executed the paths.

Environment: fresh venv, the four nodes' combined requirements installed through https://download.pytorch.org/whl/cpu — i.e. exactly what this PR's --extra-index-url produces.

torch 2.13.0+cpu
nvidia-* / triton / cuda packages none
site-packages 1.3 GB (the live ALB carries 8.2 GB)

Executed, not imported:

PASS  torch cpu matmul          2.13.0+cpu, cuda.is_available()=False, 64x64 matmul ok
PASS  transformers forward pass hidden=(1, 6, 384), device=cpu
PASS  embedding produced        dim=384, norm=6.782
PASS  accelerate init           Accelerator device=cpu
PASS  langchain text splitter   8 chunks
PASS  onnxruntime providers     1.20.1, ['AzureExecutionProvider', 'CPUExecutionProvider']
PASS  gliner entity prediction  3 entities: ['Dmitrii', 'RocketRide', 'San Francisco']

The gliner line is the one that matters most — anonymize is the node with the explicit onnxruntime-gpu pin, and it ran a real entity extraction on CPU.

Also checked in the node sources rather than assumed: none of the four hardcodes a device. No .cuda(), no .to('cuda'), no CUDAExecutionProvider. The device_lock in embedding_video is a threading mutex, not a CUDA device. The "capabilities": ["gpu"] in three services.json files is metadata — nothing in packages/ai consumes it as a scheduling constraint.

One honest caveat on my own test: the first run reported a transformers failure. That was my harness, not the CPU stack — I picked prajjwal1/bert-tiny, whose slow tokenizer needs sentencepiece to convert. Re-ran with a fast-tokenizer model and it passed. Worth stating because a failure I caused would otherwise sit in this thread looking like evidence against the change.


Separately: this branch had a duplicate of #1707 on it, now removed

The branch carried 2e16ee10 fix(google-workspace): stop reporting connection_ok… — the same three IInstance.py files as #1707, byte-identical — without #1707's tests.

That mattered: today I found and fixed three test failures that change causes, including a real defect (drive gained an about().get probe, FakeDrive has no about(), so the probe raised AttributeError and the node reported connection_ok=False). This branch had the source change and none of the fixes. Merging this first would have broken the google-workspace tests on develop — and PR CI would not have caught it, because the ./builder test lane is a monthly cron.

Rebased onto develop dropping that commit. This PR is now one commit, one file: depends.py, +35/-1. #1707 remains the only home for the google-workspace change, and the two are now independent in either merge order.

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

♻️ Duplicate comments (2)
packages/server/engine-lib/rocketlib-python/lib/depends.py (2)

677-704: 🎯 Functional Correctness | 🟠 Major

Include CPU-only mode in the constraints cache key.

_cpu_only() changes the generated requirements, but ensure_constraints() hashes only req_files. Toggling ROCKETRIDE_CPU_ONLY_DEPS can therefore reuse stale CPU/GPU constraints and install the wrong dependency set. Include the normalized CPU-only state in the cache key and cover both mode transitions with a regression test.

🤖 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 `@packages/server/engine-lib/rocketlib-python/lib/depends.py` around lines 677
- 704, The constraints cache key in ensure_constraints must incorporate the
normalized state returned by _cpu_only(), since that state changes generated
requirements. Update the hash inputs so CPU-only and GPU/default modes produce
distinct cache entries, and add a regression test covering both transitions to
ensure stale constraints are not reused.

691-704: 🎯 Functional Correctness | 🟠 Major

Make CPU PyTorch resolution exclusive.

The new --extra-index-url directive still competes with PyPI because _install_dry_run() uses unsafe-best-match. A regular CUDA torch candidate can therefore win and reintroduce nvidia-* packages. Use an index strategy or explicit package-to-index directives that force PyTorch packages to the CPU index, then verify clean resolutions in both modes.

🤖 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 `@packages/server/engine-lib/rocketlib-python/lib/depends.py` around lines 691
- 704, The CPU-only branch in _install_dry_run must force PyTorch packages to
resolve exclusively from the CPU index rather than merely adding it as an extra
source. Update the directive emitted by the _cpu_only() path to use the
supported index strategy or explicit torch package-to-index rules, while
preserving normal PyPI resolution for unrelated packages and verifying clean
CPU-only and default resolutions.
🤖 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 `@packages/server/engine-lib/rocketlib-python/lib/depends.py`:
- Around line 810-820: Update the onnxruntime-gpu exclusion branch in
_write_excludes_file to remain gated by platform.system() != 'Darwin', matching
the documented non-Darwin scope; preserve the existing CPU-only behavior on
non-Darwin hosts.

---

Duplicate comments:
In `@packages/server/engine-lib/rocketlib-python/lib/depends.py`:
- Around line 677-704: The constraints cache key in ensure_constraints must
incorporate the normalized state returned by _cpu_only(), since that state
changes generated requirements. Update the hash inputs so CPU-only and
GPU/default modes produce distinct cache entries, and add a regression test
covering both transitions to ensure stale constraints are not reused.
- Around line 691-704: The CPU-only branch in _install_dry_run must force
PyTorch packages to resolve exclusively from the CPU index rather than merely
adding it as an extra source. Update the directive emitted by the _cpu_only()
path to use the supported index strategy or explicit torch package-to-index
rules, while preserving normal PyPI resolution for unrelated packages and
verifying clean CPU-only and default resolutions.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: f5a66e1e-71e1-4288-bc83-1490113aa57c

📥 Commits

Reviewing files that changed from the base of the PR and between 24b8f58 and ae0b3f0.

📒 Files selected for processing (1)
  • packages/server/engine-lib/rocketlib-python/lib/depends.py

Comment on lines +810 to +820
# The onnxruntime exclusion keys on OS, which is not the question being
# asked. "Not a Mac" was used as a proxy for "has CUDA", and it is wrong on
# every Linux box without a GPU — including the cloud ALB, where it forces
# the GPU build and blocks the CPU one from ever being installed. Excluding
# it there would defeat the CPU-only resolve above, so honour that flag.
if platform.system() != 'Darwin' and not _cpu_only():
excludes += 'onnxruntime\n'
elif _cpu_only():
# Mirror image: on a CPU-only host the GPU build is the one that must
# not win, for the same clobbering reason the original comment gives.
excludes += 'onnxruntime-gpu\n'

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file and inspect the relevant function and surrounding documentation/tests.
sed -n '760,840p' packages/server/engine-lib/rocketlib-python/lib/depends.py

printf '\n--- _cpu_only definition/usages ---\n'
rg -n "def _cpu_only|_cpu_only\(|cpu_only|onnxruntime-gpu|excludes" packages/server/engine-lib/rocketlib-python/lib/depends.py

printf '\n--- related docs/comments ---\n'
rg -n -C 3 "CUDA|cpu|Darwin|onnxruntime-gpu|onnxruntime" packages/server/engine-lib/rocketlib-python/lib/depends.py packages/server/engine-lib -g '*.py' -g '*.md' | head -n 200

Repository: rocketride-org/rocketride-server

Length of output: 15816


Keep the CPU-only exclusion OS-gated as documented.

_write_excludes_file() says the onnxruntime exclusions apply to non-Darwin hosts, but elif _cpu_only() excludes onnxruntime-gpu on Darwin too. If macOS CPU-only hosts may require the GPU build, either gate this branch with platform.system() != 'Darwin' or update the docstring/comments to make macOS behavior an explicit contract.

🧰 Tools
🪛 ast-grep (0.45.0)

[warning] 820-820: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(excludes_path, 'w', encoding='utf-8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)

🤖 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 `@packages/server/engine-lib/rocketlib-python/lib/depends.py` around lines 810
- 820, Update the onnxruntime-gpu exclusion branch in _write_excludes_file to
remain gated by platform.system() != 'Darwin', matching the documented
non-Darwin scope; preserve the existing CPU-only behavior on non-Darwin hosts.

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

Labels

module:server C++ engine and server components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant