feat(jobs): add watch command to stream job and deployment events - #1031
feat(jobs): add watch command to stream job and deployment events#1031ironcommit wants to merge 2 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR adds synchronous and asynchronous job watching with typed status, log, and warning events. It integrates watch and wait modes into job and deployment creation, adds generated-command support, updates CLI rendering and validation, and documents the new lifecycle options. ChangesJob Watch
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant JobsClient
participant watch_job
participant PlatformAPI
User->>CLI: Run jobs watch or create --watch
CLI->>JobsClient: Start watch_job
JobsClient->>watch_job: Pass filters, timeout, and polling
watch_job->>PlatformAPI: Poll status and fetch logs
PlatformAPI-->>watch_job: Status and log responses
watch_job-->>JobsClient: Emit JobWatchEvent values
JobsClient-->>CLI: Return event stream
CLI-->>User: Render status, logs, warnings, and completion
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py (1)
156-203: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winFix: string-replace corrupts generated code when the resource name contains
--wait.
_render_lifecycle_codebuilds the prelude with the literal text--wait, then doesprelude.replace("--wait", "--watch")forplatform_job. This replace is not scoped to the error message. It also rewrites any occurrence of--waitinside the interpolated resource-name literal. If a job'snamecontains the substring--wait(for examplenightly--wait-job), the generated code's quoted name literal is silently corrupted tonightly--watch-job.Compute the flag name once from
lifecycle_typeand interpolate it directly instead of doing a blind substring replace after the fact.🐛 Proposed fix
resource_name = 'getattr(response, "name", None)' if args.get("name") is not None: resource_name = f"{resource_name} or {_format_python_literal(args['name'])}" + flag_name = "--watch" if lifecycle_type == "platform_job" else "--wait" prelude = dedent( f""" resource_name = {resource_name} if not resource_name: - raise RuntimeError("Unable to determine created resource name for --wait") + raise RuntimeError("Unable to determine created resource name for {flag_name}") """ ).strip() if lifecycle_type == "inference_deployment": ... if lifecycle_type == "platform_job": - prelude = prelude.replace("--wait", "--watch") return "\n\n".join( [ prelude, _render_platform_job_watch_code(args, timeout, poll_interval), ] ) raise ValueError(f"Unsupported lifecycle config type: {lifecycle_type!r}")🤖 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/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py` around lines 156 - 203, Update _render_lifecycle_code to compute the lifecycle flag name from lifecycle_type before constructing prelude, using --watch for platform_job and --wait otherwise, then interpolate that value into the error message. Remove the prelude.replace("--wait", "--watch") call so resource-name literals containing --wait remain unchanged.tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2 (1)
32-41: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winReject methods that configure both
waitandwatch.Both configurations are accepted independently. The template then emits duplicate
timeoutandpoll_intervalparameters, causing a PythonSyntaxError.🤖 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 `@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2` around lines 32 - 41, Update the template conditions around the watch_config and wait_config blocks so generated commands cannot enable both configurations simultaneously. Preserve each configuration’s existing parameters when used alone, and ensure timeout and poll_interval are emitted only once to avoid duplicate function parameters.
🧹 Nitpick comments (1)
packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py (1)
199-228: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMove the function-local imports to module scope.
Line 28 already imports from
nemo_platform_ext.jobs.watchat module level, so the deferred imports on Line 213 and Line 408 cannot break an import cycle. Importwatch_jobandasync_watch_jobnormally.Also add docstrings; every other public method on this client is documented.
As per coding guidelines: "prefer concrete type hints over string-based type hints, and do not import those types only under `TYPE_CHECKING`; import them normally when possible."♻️ Proposed change
-from nemo_platform_ext.jobs.watch import JobWatchEvent +from nemo_platform_ext.jobs.watch import JobWatchEvent, async_watch_job, watch_job) -> Iterator[JobWatchEvent]: - from nemo_platform_ext.jobs.watch import watch_job - return watch_job(🤖 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/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py` around lines 199 - 228, Move watch_job and async_watch_job imports from their methods to module scope alongside the existing nemo_platform_ext.jobs.watch import, then remove the function-local imports. Add concise docstrings to the public watch_job and async_watch_job client methods while preserving their current delegation and parameters.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.
Inline comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py`:
- Around line 312-334: Update _drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:312-334 to track
visited cursors, return when _next_page produces a cursor already seen or
otherwise fails to advance, and enforce the deadline on every loop iteration.
Apply the same cursor-advance guard and per-iteration deadline check in
_async_drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:352-374.
- Around line 126-150: Update the polling loop around _drain_logs to persist and
reuse the latest next_page cursor across cycles instead of resetting to the
original page_cursor. When the server invalidates that cursor, fall back to the
existing full re-scan behavior; otherwise advance the cursor after each
successful drain while preserving terminal-status handling.
- Around line 126-146: Update the log-draining flow around _drain_logs so
history_seen becomes true immediately after the first page is recorded,
including when pagination later raises a transient error. Preserve suppression
of pre-existing history for include_history=False while allowing newly fetched
lines to emit on the retry, and remove reliance on setting history_seen only
after the entire drain succeeds.
- Around line 102-105: Make both watcher entry points validate eagerly by
converting watch_job at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:102-105 and
async_watch_job at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py:168-171 into
non-generator wrappers. Keep the poll_interval checks and _sync_jobs_client or
_async_jobs_client resolution in each wrapper, then return inner generator or
async-generator functions containing the existing iteration logic.
---
Outside diff comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py`:
- Around line 156-203: Update _render_lifecycle_code to compute the lifecycle
flag name from lifecycle_type before constructing prelude, using --watch for
platform_job and --wait otherwise, then interpolate that value into the error
message. Remove the prelude.replace("--wait", "--watch") call so resource-name
literals containing --wait remain unchanged.
In
`@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2`:
- Around line 32-41: Update the template conditions around the watch_config and
wait_config blocks so generated commands cannot enable both configurations
simultaneously. Preserve each configuration’s existing parameters when used
alone, and ensure timeout and poll_interval are emitted only once to avoid
duplicate function parameters.
---
Nitpick comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py`:
- Around line 199-228: Move watch_job and async_watch_job imports from their
methods to module scope alongside the existing nemo_platform_ext.jobs.watch
import, then remove the function-local imports. Add concise docstrings to the
public watch_job and async_watch_job client methods while preserving their
current delegation and parameters.
🪄 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: Enterprise
Run ID: 75f56093-22d4-4101-9ce3-7b89b2a6a52a
⛔ Files ignored due to path filters (11)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (20)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
|
e7a5748 to
a5ff80c
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py (1)
923-1016: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a watch-only platform-job render test. No test covers a
platform_jobwatch config without a wait config. That case is exactly where the template emits an unusedwait_for_platform_jobimport (see the template comment).🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 923 - 1016, Add a test alongside test_create_platform_job_watch_config_renders_wait_and_watch covering a create configuration with watch type platform_job but no wait block. Render the command and assert watch-related options/imports and job-watch behavior are present while the wait_for_platform_job import and wait-only rendering are absent, matching the template’s watch-only output.
🤖 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
`@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2`:
- Around line 24-30: Update the conditional import for wait_for_platform_job in
the create command template so it is generated only when has_platform_job_wait
is enabled; keep the separate job-watch imports unchanged, since the watch-only
branch does not use wait_for_platform_job.
---
Nitpick comments:
In `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py`:
- Around line 923-1016: Add a test alongside
test_create_platform_job_watch_config_renders_wait_and_watch covering a create
configuration with watch type platform_job but no wait block. Render the command
and assert watch-related options/imports and job-watch behavior are present
while the wait_for_platform_job import and wait-only rendering are absent,
matching the template’s watch-only output.
🪄 Autofix
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: Enterprise
Run ID: 7a009706-6d46-4524-9341-85bd84fb0ee0
⛔ Files ignored due to path filters (15)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (24)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (10)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
a5ff80c to
18140ca
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py (1)
794-811: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winFixture annotations do not match the real
watch_jobcontract.
watch_jobreturnsIterator[JobWatchEvent]andasync_watch_jobreturnsAsyncIterator[JobWatchEvent], not a bareJobWatchEvent. The fixture is a stand-in forenhanced.py, so a wrong annotation here weakens the vendor-rewrite test. It also leaves line 826 asserting thatAsyncIteratorandIteratorare imported while the fixture never uses either name, so that assertion no longer proves anything about the rewritten watch signatures.Use the real return types, then assert each signature separately instead of
count(...) == 2on line 837.♻️ Suggested fixture change
- def watch_job(self, name: str) -> JobWatchEvent: + def watch_job(self, name: str) -> Iterator[JobWatchEvent]: \"\"\"Watch a job.\"\"\" return watch_job(self, name)- def watch_job(self, name: str) -> JobWatchEvent: + def watch_job(self, name: str) -> AsyncIterator[JobWatchEvent]: \"\"\"Watch a job asynchronously.\"\"\" return async_watch_job(self, name)Add the matching import to the fixture source and update the assertions:
- assert updated.count("def watch_job(self, name: str) -> JobWatchEvent:") == 2 + assert "def watch_job(self, name: str) -> Iterator[JobWatchEvent]:" in updated + assert "def watch_job(self, name: str) -> AsyncIterator[JobWatchEvent]:" in updated🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py` around lines 794 - 811, Update the fixture’s NeMoPlatform.watch_job and AsyncNeMoPlatform.watch_job annotations to use Iterator[JobWatchEvent] and AsyncIterator[JobWatchEvent], respectively, matching the real enhanced.py contract. Add Iterator and AsyncIterator to the fixture imports, then replace the combined import-count assertion with separate signature assertions for the synchronous and asynchronous methods.
🧹 Nitpick comments (5)
packages/nemo_platform_ext/tests/cli/core/test_code_generator.py (2)
243-253: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe label test does not assert what its name claims.
test_generate_python_code_with_platform_job_watch_ignores_label_formattingpasses a label with quotes and{label}, then only checkscompileand the--watcherror string. Neither assertion proves the label was escaped or ignored. Assert that the raw label does not leak into the generated code.💚 Suggested assertion
compile(code, "<generated-code>", "exec") assert 'raise RuntimeError("Unable to determine created resource name for --watch")' in code + assert 'customization "job" {label}' not in code🤖 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/nemo_platform_ext/tests/cli/core/test_code_generator.py` around lines 243 - 253, Update test_generate_python_code_with_platform_job_watch_ignores_label_formatting to assert that the raw watch_config resource_label, including its quotes and {label} placeholder, is absent from the generated code. Keep the existing compilation and RuntimeError assertions unchanged.
209-240: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAdd coverage for missing
watchtimeout validation.
_require_timeoutvalidateswatchmode, but the test covers only thewaiterror path. Add the proposedwatch_options={"poll_interval": 10}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/nemo_platform_ext/tests/cli/core/test_code_generator.py` around lines 209 - 240, Add a test beside test_generate_python_code_with_inference_deployment_wait_requires_timeout covering create generation with watch_config for inference_deployment and watch_options containing only poll_interval. Assert generate_python_code raises ValueError with the watch lifecycle timeout validation message, exercising _require_timeout for watch mode.packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py (1)
393-426: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff
seen_logsretains one entry per log line for the whole watch. Both drain functions share the same unbounded dedupe map. Now that the cursor advances between polls, only the recent page window needs dedupe coverage.
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L393-L426: bound theseen_logsmap in_drain_logs, for example by evicting keys behind the advanced cursor.packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L429-L477: apply the same bounding in_async_drain_logs.🤖 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/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py` around lines 393 - 426, Bound the shared seen_logs deduplication map to the active recent page window instead of retaining every log key indefinitely. Update both _drain_logs at packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L393-L426 and _async_drain_logs at packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L429-L477 to evict keys that fall behind the advanced page cursor while preserving deduplication for logs still covered by the current window.tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py (2)
963-964: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueTighten the timeout-default assertions.
assert "] = None" in renderedandassert "] = 1200" in renderedmatch any parameter default in the file, not thetimeoutparameter. They pass even iftimeoutloses its default. Assert the full annotated declaration instead.Also applies to: 1004-1005
🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 963 - 964, In the timeout generation assertions around the existing `rendered` checks, replace the broad substring checks for `] = None` and `] = 1200` with assertions matching the complete `timeout` annotated parameter declaration and its expected default. Apply the same tightening to both affected test cases so unrelated parameter defaults cannot satisfy the assertions.
700-709: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winShare the Jinja environment setup between production and tests.
Extract the inline setup from
SimpleGenerator.__init__into a factory and use it in_render_create_command. The test currently uses a differentto_kebabimplementation than production.🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 700 - 709, Extract the Jinja Environment configuration from SimpleGenerator.__init__ into a shared factory, preserving the production loader, options, and filters. Update _render_create_command to obtain its environment through that factory and remove the duplicate inline setup so both production and tests use the same to_kebab behavior.
🤖 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/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py`:
- Around line 170-186: Cap retries for terminal-status log draining in both the
synchronous watcher loop at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L170-L186 and the
asynchronous watcher loop at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L271-L288. Track
failures from the final drain, emit a warning when the configured cap is
reached, and return instead of continuing indefinitely when timeout is None;
apply the same behavior consistently to both loops.
In `@packages/nemo_platform_ext/tests/jobs/test_watch.py`:
- Around line 484-488: Update the monotonic_values fixture in the watch_job
timeout test to provide a fallback value after the scripted 0.0, 0.0, and 10.0
readings, preventing unrelated calls to watch_module.time.monotonic from
exhausting the iterator. Preserve the existing timeout assertion and timing
sequence while ensuring additional calls do not raise StopIteration.
---
Outside diff comments:
In `@tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py`:
- Around line 794-811: Update the fixture’s NeMoPlatform.watch_job and
AsyncNeMoPlatform.watch_job annotations to use Iterator[JobWatchEvent] and
AsyncIterator[JobWatchEvent], respectively, matching the real enhanced.py
contract. Add Iterator and AsyncIterator to the fixture imports, then replace
the combined import-count assertion with separate signature assertions for the
synchronous and asynchronous methods.
---
Nitpick comments:
In `@packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py`:
- Around line 393-426: Bound the shared seen_logs deduplication map to the
active recent page window instead of retaining every log key indefinitely.
Update both _drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L393-L426 and
_async_drain_logs at
packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py#L429-L477 to
evict keys that fall behind the advanced page cursor while preserving
deduplication for logs still covered by the current window.
In `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py`:
- Around line 243-253: Update
test_generate_python_code_with_platform_job_watch_ignores_label_formatting to
assert that the raw watch_config resource_label, including its quotes and
{label} placeholder, is absent from the generated code. Keep the existing
compilation and RuntimeError assertions unchanged.
- Around line 209-240: Add a test beside
test_generate_python_code_with_inference_deployment_wait_requires_timeout
covering create generation with watch_config for inference_deployment and
watch_options containing only poll_interval. Assert generate_python_code raises
ValueError with the watch lifecycle timeout validation message, exercising
_require_timeout for watch mode.
In `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py`:
- Around line 963-964: In the timeout generation assertions around the existing
`rendered` checks, replace the broad substring checks for `] = None` and `] =
1200` with assertions matching the complete `timeout` annotated parameter
declaration and its expected default. Apply the same tightening to both affected
test cases so unrelated parameter defaults cannot satisfy the assertions.
- Around line 700-709: Extract the Jinja Environment configuration from
SimpleGenerator.__init__ into a shared factory, preserving the production
loader, options, and filters. Update _render_create_command to obtain its
environment through that factory and remove the duplicate inline setup so both
production and tests use the same to_kebab behavior.
🪄 Autofix
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: Enterprise
Run ID: 0127b6ea-560c-48e8-b381-796c88784c7b
⛔ Files ignored due to path filters (15)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (24)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (19)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.py
- packages/nemo_platform_ext/tests/cli/telemetry/test_job_events.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/init.py
- packages/nemo_platform_ext/tests/cli/core/test_waiters.py
- packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py
- tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.py
- docs/cli/reference.mdx
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2
- packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
18140ca to
dfa04bc
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/nemo_platform_ext/tests/cli/core/test_code_generator.py (1)
243-253: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the escaping this test claims to verify.
The test name states label formatting is ignored, but the assertions only check compilation and the error string. A generator that interpolated the label unescaped into a docstring or comment could still pass. Add an assertion that the raw label is not injected outside a quoted literal.
♻️ Suggested assertion
compile(code, "<generated-code>", "exec") assert 'raise RuntimeError("Unable to determine created resource name for --watch")' in code + assert 'customization "job" {label}' not in code🤖 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/nemo_platform_ext/tests/cli/core/test_code_generator.py` around lines 243 - 253, Strengthen test_generate_python_code_with_platform_job_watch_ignores_label_formatting by asserting that the raw resource_label text is not injected into the generated source outside a quoted literal, while retaining the existing compilation and RuntimeError assertions.tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py (1)
700-709: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the production Jinja environment in
_render_create_command.Extract the environment setup into a shared factory. The test currently replaces
caseutil.to_kebabwith a lambda that only replaces underscores, so it can render different command paths.🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py` around lines 700 - 709, Update _render_create_command to obtain its Jinja Environment from the same shared production environment factory used by the CLI generator, rather than constructing a test-specific environment with a local to_kebab lambda. Preserve loading create_command.py.j2 and rendering with the existing context, and remove the duplicated environment/filter setup.
🤖 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 `@packages/nemo_platform_ext/tests/cli/core/test_code_generator.py`:
- Around line 243-253: Strengthen
test_generate_python_code_with_platform_job_watch_ignores_label_formatting by
asserting that the raw resource_label text is not injected into the generated
source outside a quoted literal, while retaining the existing compilation and
RuntimeError assertions.
In `@tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.py`:
- Around line 700-709: Update _render_create_command to obtain its Jinja
Environment from the same shared production environment factory used by the CLI
generator, rather than constructing a test-specific environment with a local
to_kebab lambda. Preserve loading create_command.py.j2 and rendering with the
existing context, and remove the duplicated environment/filter setup.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 050f3e33-c204-48d3-b41d-a24a883ee02b
⛔ Files ignored due to path filters (15)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/jobs/watch.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (26)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.pypackages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/client/adapter.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/client.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (21)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.py
- packages/nemo_platform_ext/tests/cli/core/test_waiters.py
- packages/nemo_platform_ext/tests/cli/telemetry/test_job_events.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
- tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.py
- packages/nemo_platform_ext/src/nemo_platform_ext/client/enhanced.py
- packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py
- docs/cli/reference.mdx
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/jobs/watch.py
dfa04bc to
9fe6249
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py (1)
814-826: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winSeed stale symbols in the target fixture.
The fixture does not contain
AsyncIterator,Iterator,jobs.watch, ordef watch_job. These assertions pass if stale cleanup does nothing. Add stale imports and methods toclient_pathbefore invoking_replace_client_methods.🤖 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 `@tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py` around lines 814 - 826, Update the fixture setup for client_path before invoking _replace_client_methods to add stale AsyncIterator and Iterator imports plus a watch_job method and jobs.watch reference. Keep the existing assertions unchanged so the test verifies these stale symbols are actually removed rather than passing when no cleanup is needed.tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py (1)
2120-2125: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy liftRun stale cleanup when no replacement methods exist.
When
collector.class_methodsis empty, return at line 2118 skips_ClientMethodReplacerand_ClientStaleImportRemover. Continue with empty replacements so stalewatch_jobmethods and imports are removed.🤖 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 `@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py` around lines 2120 - 2125, Update the control flow around _ClientMethodReplacer so an empty collector.class_methods collection does not return before stale cleanup. Always visit the target tree with _ClientMethodReplacer and then _ClientStaleImportRemover, allowing stale watch_job methods and imports to be removed even when no replacement methods exist.
🧹 Nitpick comments (1)
packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py (1)
101-104: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDrop the quoted return annotation.
from __future__ import annotationsis active on line 4, so the forward reference is unnecessary.♻️ Proposed change
- def from_timeout(cls, job_name: str, timeout: float | None) -> "_WatchDeadline": + def from_timeout(cls, job_name: str, timeout: float | None) -> _WatchDeadline:As per coding guidelines: "Prefer concrete type hints over string-based type hints".
🤖 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/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py` around lines 101 - 104, Update the return annotation on the _WatchDeadline.from_timeout classmethod to use the concrete _WatchDeadline type directly instead of a quoted string, relying on the active future annotations import.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.
Inline comments:
In `@packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py`:
- Around line 340-353: Update _status_event to propagate
PlatformJobStatusResponse.error_details into the returned JobStatusEvent,
preserving the existing status and status_details mappings so failed-job
renderers can display the failure reason.
- Around line 480-496: The _new_log_events function lets state.seen_logs grow
indefinitely; bound its retained entries so deduplication covers only the
current and previous drain, or entries newer than the persisted cursor. Update
the surrounding _WatchState bookkeeping as needed while preserving
occurrence-based suppression of already-seen log events.
- Around line 33-35: Update the terminal-status definitions near
_SUCCESSFUL_TERMINAL_STATUSES, _FAILED_TERMINAL_STATUSES, and _TERMINAL_STATUSES
to account for the paused PlatformJobStatus. Ensure nemo jobs watch and create
--watch stop polling when a job is paused, or emit the required warning event if
paused is intentionally non-terminal.
---
Outside diff comments:
In
`@tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py`:
- Around line 2120-2125: Update the control flow around _ClientMethodReplacer so
an empty collector.class_methods collection does not return before stale
cleanup. Always visit the target tree with _ClientMethodReplacer and then
_ClientStaleImportRemover, allowing stale watch_job methods and imports to be
removed even when no replacement methods exist.
In `@tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py`:
- Around line 814-826: Update the fixture setup for client_path before invoking
_replace_client_methods to add stale AsyncIterator and Iterator imports plus a
watch_job method and jobs.watch reference. Keep the existing assertions
unchanged so the test verifies these stale symbols are actually removed rather
than passing when no cleanup is needed.
---
Nitpick comments:
In `@packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py`:
- Around line 101-104: Update the return annotation on the
_WatchDeadline.from_timeout classmethod to use the concrete _WatchDeadline type
directly instead of a quoted string, relying on the active future annotations
import.
🪄 Autofix
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: Enterprise
Run ID: 9870e250-8e31-4048-be78-6615fe0b836e
⛔ Files ignored due to path filters (14)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (26)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/client/adapter.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/client.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch_types.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (14)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- packages/nemo_platform_ext/tests/cli/test_app.py
- packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py
- packages/nemo_platform_plugin/src/nemo_platform_plugin/client/adapter.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/init.py
- tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.py
- docs/cli/reference.mdx
- packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/init.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
9fe6249 to
1847407
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py (1)
367-374: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winSet
verbose=Falsefor the--waitassertion.create_deploymentspassesverbose=watch, so--waitis quiet and--watchremainsverbose=True.🤖 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/nemo_platform_ext/tests/cli/commands/test_create_wait.py` around lines 367 - 374, Update the wait-mode assertion for create_deployments to expect verbose=False, reflecting that --wait passes verbose=watch and remains quiet; preserve verbose=True for the --watch assertion.
🧹 Nitpick comments (3)
packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py (2)
167-170: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDrop the string-based return annotation.
The module has
from __future__ import annotations, so use_WatchDeadlinedirectly.♻️ Proposed change
- def from_timeout(cls, job_name: str, timeout: float | None) -> "_WatchDeadline": + def from_timeout(cls, job_name: str, timeout: float | None) -> _WatchDeadline:As per coding guidelines: "Prefer concrete type hints over string-based type hints".
🤖 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/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py` around lines 167 - 170, Update the _WatchDeadline.from_timeout classmethod return annotation to reference _WatchDeadline directly instead of using a quoted string, while preserving the existing timeout and return behavior.Source: Coding guidelines
444-459: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAccess
error_detailsdirectly.
PlatformJobStatusResponsedeclareserror_detailsas a field. Thegetattrfallback hides schema drift fromtyand reads as if the field is optional on the model.♻️ Proposed change
- error_details = getattr(status_response, "error_details", None) + error_details = status_response.error_details🤖 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/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py` around lines 444 - 459, Update _status_event to access status_response.error_details directly instead of using getattr, preserving the existing None handling and conversion to a dictionary for the JobStatusEvent error_details field.packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py (1)
66-76: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe renderer imports a private symbol from
waiters.
_emit_job_run_eventis private towaiters. Promote it to a public helper, or move it to a shared telemetry module, so the coupling survives refactors ofwaiters.🤖 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/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py` around lines 66 - 76, Update _emit_terminal_job_run_event to stop importing the private waiters._emit_job_run_event symbol directly. Promote _emit_job_run_event to a public helper or relocate it to a shared telemetry module, then update both its definition and callers to use the public/shared API while preserving the existing event arguments and behavior.
🤖 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/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py`:
- Around line 107-109: The _time_label function must render aware timestamps in
local time to match status and warning lines; convert the provided timestamp
with astimezone() before strftime while preserving datetime.now() behavior for
omitted timestamps. In
packages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.py lines
34-56, add an assertion that the log line’s time prefix matches the expected
local-time conversion.
In `@packages/nemo_platform_ext/tests/jobs/test_watch.py`:
- Around line 1-27: Update the pytest configuration used by the repository to
set pytest’s import mode to importlib, preventing import-file mismatches when
both test_watch.py modules are collected. Add the setting in the root pytest
configuration rather than changing the test module imports.
In `@packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py`:
- Around line 680-685: Update _is_invalid_page_cursor_error to rely on a stable
documented machine-readable invalid-cursor code instead of exact
NemoHTTPError.detail text; if no such code is available, add a narrowly scoped
compatibility check covering the known PageCursor.decode signal and tests for
the fallback through _can_retry_log_scan_from_start.
---
Outside diff comments:
In `@packages/nemo_platform_ext/tests/cli/commands/test_create_wait.py`:
- Around line 367-374: Update the wait-mode assertion for create_deployments to
expect verbose=False, reflecting that --wait passes verbose=watch and remains
quiet; preserve verbose=True for the --watch assertion.
---
Nitpick comments:
In
`@packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.py`:
- Around line 66-76: Update _emit_terminal_job_run_event to stop importing the
private waiters._emit_job_run_event symbol directly. Promote _emit_job_run_event
to a public helper or relocate it to a shared telemetry module, then update both
its definition and callers to use the public/shared API while preserving the
existing event arguments and behavior.
In `@packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.py`:
- Around line 167-170: Update the _WatchDeadline.from_timeout classmethod return
annotation to reference _WatchDeadline directly instead of using a quoted
string, while preserving the existing timeout and return behavior.
- Around line 444-459: Update _status_event to access
status_response.error_details directly instead of using getattr, preserving the
existing None handling and conversion to a dictionary for the JobStatusEvent
error_details field.
🪄 Autofix
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: Enterprise
Run ID: ae2a3306-9806-473a-9609-852f4795139f
⛔ Files ignored due to path filters (14)
sdk/python/nemo-platform/src/nemo_platform/_client.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/inference/deployments/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/src/nemo_platform/cli/core/waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/commands/test_create_wait.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_code_generator.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_job_watch_renderer.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/core/test_waiters.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/telemetry/test_job_events.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/cli/test_app.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/__init__.pyis excluded by!sdk/**sdk/python/nemo-platform/tests/vendored/nemo_platform_ext/jobs/test_watch.pyis excluded by!sdk/**
📒 Files selected for processing (27)
docs/cli/reference.mdxpackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/job_watch_renderer.pypackages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.pypackages/nemo_platform_ext/tests/cli/commands/test_create_wait.pypackages/nemo_platform_ext/tests/cli/core/test_code_generator.pypackages/nemo_platform_ext/tests/cli/core/test_job_watch_renderer.pypackages/nemo_platform_ext/tests/cli/core/test_waiters.pypackages/nemo_platform_ext/tests/cli/telemetry/test_job_events.pypackages/nemo_platform_ext/tests/cli/test_app.pypackages/nemo_platform_ext/tests/jobs/test_watch.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/client/adapter.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/client.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch.pypackages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch_types.pypackages/nemo_platform_plugin/tests/jobs/test_watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yamltools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.pytools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.pytools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_generator.pytools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
🚧 Files skipped from review as they are similar to previous changes (18)
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/overrides/jobs/watch.py
- packages/nemo_platform_ext/tests/cli/test_app.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/context_collectors/create_collector.py
- packages/nemo_platform_plugin/src/nemo_platform_plugin/client/adapter.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/cli_config.yaml
- packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/watch_types.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/inference/deployments/init.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/init.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/config.py
- tools/nemo-platform-sdk-tools/tests/sdk/vendor/test_vendor_package.py
- tools/nemo-platform-sdk-tools/tests/sdk/cli_generator/test_config.py
- packages/nemo_platform_plugin/src/nemo_platform_plugin/jobs/client.py
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/code_generator.py
- docs/cli/reference.mdx
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/vendor/vendor_package.py
- packages/nemo_platform_ext/tests/cli/telemetry/test_job_events.py
- tools/nemo-platform-sdk-tools/src/nemo_platform_sdk_tools/sdk/cli_generator/templates/create_command.py.j2
- packages/nemo_platform_ext/src/nemo_platform_ext/cli/core/waiters.py
1847407 to
58580df
Compare
mckornfield
left a comment
There was a problem hiding this comment.
some questions but lg
Fresh open inline threads (not replies on resolved conversations):
Still open
Fixed since prior review (no action)R3 Live timer, R4 Optional / debt
|
tylersbray
left a comment
There was a problem hiding this comment.
+1'ing Matt's approval so you are not blocked. Will be a nice feature to ship.
58580df to
cc46405
Compare
|
Addressed the human review feedback in cc46405:
Validation:
|
cc46405 to
2784e4b
Compare
|
Small correction to my previous validation comment: after a cleanup pass, the final commit |
2c533b9 to
984a97c
Compare
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
Signed-off-by: Ryan S <267728323+ironcommit@users.noreply.github.com>
984a97c to
674025a
Compare
Summary
Adds a
nemo jobs watchCLI command and corresponding SDK watcher methods that stream job lifecycle events - status transitions, log lines, and warnings - directly to the terminal or programmatic consumers. The sync and async Jobs SDK clients both exposewatch_job(...); the async client returns an async iterator backed byasync_watch_job(...).Changes
Core watch engine (
jobs/watch.py)JobWatchEventobjects (status, log, warning)attempt_id,step_id, andtask_idpoll_intervalCLI command (
nemo jobs watch)--timeout,--poll-interval,--history/--no-history,--attempt-id,--step-id,--task-id,--limit,--workspaceinclude_logs=Falseis SDK-only--watchflag on create commandsnemo jobs create --watchandnemo inference deployments create --watchautomatically watch after creation--waitflag--watchsupport for configured create commands viacli_config.yamlSDK client integration
client.jobs.watch_job(name, ...)-> sync iterator ofJobWatchEventasync_client.jobs.watch_job(name, ...)-> async iterator ofJobWatchEventNeMoPlatformclients through the Jobs resourceWaiters refactor
Testing
test_watch.py)nemo jobs watchand--watchon create commands (test_app.py,test_create_wait.py)test_job_watch_renderer.py)test_code_generator.py,test_config.py)Summary by CodeRabbit
jobs watchto stream job status, logs, warnings, and completion results.--watchsupport for job and inference deployment creation, with timeout and polling controls.--waitand--watchtogether.