openrunner-sdk 2.37.7__tar.gz → 2.37.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/PKG-INFO +1 -1
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/__init__.py +1 -1
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/api_client.py +108 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/cli.py +179 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/install_commands.py +82 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/pyproject.toml +1 -1
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/.gitignore +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/=6.0 +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/=8.1 +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/README.md +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/CLAUDE.md +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/_safepath.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/_secret_rules.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/artifact.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/autoresearch.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/buffer.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/cache.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/config.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/cost.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/dataset.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/datasets.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/environment.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/evaluation.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/feedback.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/git_info.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/api_integration.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/cost_guard.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/gpu_types.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/price_compare.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/provider_base.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/providers/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/providers/lambda_cloud.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/providers/modal_provider.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/providers/ovhcloud.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/providers/runpod.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/providers/vastai.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/runner.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/gpu/workspace_sync.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/guardrails.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/handover.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/hooks/patent-lab-post-commit +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/accelerate.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/anthropic_tracer.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/catboost.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/diffusers.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/fastai.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/forced_alignment.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/gladia.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/gymnasium.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/huggingface.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/hydra.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/ignite.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/jax.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/keras.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/langchain.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/lightgbm.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/lightning.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/llamaindex.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/openai_finetune.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/openai_tracer.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/optuna.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/pytorch.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/sb3.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/sklearn.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/skypilot.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/tensorflow.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/trl.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/tts.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/ultralytics.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/voice_agent.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/whisper.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/integration/xgboost.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/launch.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/machine.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/mcp_server.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/media.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/migrate.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/model.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/model_card.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/offline.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/patent_scan.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/pii.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/plot.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/projects.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/prompt.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/query_api.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/redact.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/reload.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/research.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/research_policy.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/run.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/scorers.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/sender.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/session.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/settings.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/summary.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/sweep.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/sync.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/system_metrics.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/tensorboard.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/tools/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/tools/patent_report.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/trace.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/transcript_formatter.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/wal.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/wandb_compat/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/wandb_compat/_shim.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/openrunner/wer.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/scripts/gen_betterleaks_rules.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/conftest.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/integration/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/integration/conftest.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/integration/test_artifact_round_trip.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_alert.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_aliases.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_api_client.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_artifact.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_buffer.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_cache.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_class_scorers.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_cli.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_config.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_evaluation.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_finish.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_git_info.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/__init__.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/conftest.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_cost_guard.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_gpu_types.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_lambda.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_modal.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_ovhcloud.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_price_compare.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_provider_base.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_runner.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_runpod.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_sdk_gpu_api.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_vastai.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_gpu/test_workspace_sync.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_init.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_install_commands.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_fastai.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_huggingface.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_keras.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_langchain.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_lightning.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_pytorch.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_sklearn.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_integration_xgboost.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_launch.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_log.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_log_code.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_mcp_decisions.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_mcp_monitor.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_mcp_predictions.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_media.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_migrate.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_offline.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_offline_sync.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_pii.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_plot.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_query_api.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_resume.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_sdk_features.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_sender.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_session_sync.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_summary.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_sweep.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_system_metrics.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_trace.py +0 -0
- {openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/test_wandb_compat.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrunner-sdk
|
|
3
|
-
Version: 2.37.
|
|
3
|
+
Version: 2.37.9
|
|
4
4
|
Summary: OpenRunner SDK - W&B-compatible ML experiment tracking client
|
|
5
5
|
Project-URL: Homepage, https://github.com/jqueguiner/openrunner
|
|
6
6
|
Project-URL: Repository, https://github.com/jqueguiner/openrunner
|
|
@@ -181,7 +181,7 @@ launch.from_run = _launch_from_run # type: ignore[attr-defined]
|
|
|
181
181
|
# openrunner.trace.patch_openai() syntax
|
|
182
182
|
trace.patch_openai = _patch_openai # type: ignore[attr-defined]
|
|
183
183
|
|
|
184
|
-
__version__ = "2.37.
|
|
184
|
+
__version__ = "2.37.9"
|
|
185
185
|
|
|
186
186
|
logger = logging.getLogger("openrunner")
|
|
187
187
|
|
|
@@ -429,6 +429,114 @@ class APIClient:
|
|
|
429
429
|
logger.warning("list_projects failed: %s", e)
|
|
430
430
|
return []
|
|
431
431
|
|
|
432
|
+
# -- Deployments + project images ---------------------------------------
|
|
433
|
+
|
|
434
|
+
def list_project_images(self, project_id: str) -> list[dict[str, Any]]:
|
|
435
|
+
"""GET /projects/{id}/images -- images linked to a project (deploy gate)."""
|
|
436
|
+
try:
|
|
437
|
+
r = self._request("get", f"/projects/{project_id}/images")
|
|
438
|
+
r.raise_for_status()
|
|
439
|
+
return r.json()
|
|
440
|
+
except Exception as e:
|
|
441
|
+
logger.warning("list_project_images failed: %s", e)
|
|
442
|
+
return []
|
|
443
|
+
|
|
444
|
+
def link_project_image(
|
|
445
|
+
self,
|
|
446
|
+
project_id: str,
|
|
447
|
+
image: str,
|
|
448
|
+
registry_id: str | None = None,
|
|
449
|
+
repository: str | None = None,
|
|
450
|
+
tag: str | None = None,
|
|
451
|
+
) -> dict[str, Any] | None:
|
|
452
|
+
"""POST /projects/{id}/images -- link a deployable image to a project."""
|
|
453
|
+
try:
|
|
454
|
+
body: dict[str, Any] = {"image": image}
|
|
455
|
+
if registry_id:
|
|
456
|
+
body["registry_id"] = registry_id
|
|
457
|
+
if repository:
|
|
458
|
+
body["repository"] = repository
|
|
459
|
+
if tag:
|
|
460
|
+
body["tag"] = tag
|
|
461
|
+
r = self._request("post", f"/projects/{project_id}/images", json=body)
|
|
462
|
+
r.raise_for_status()
|
|
463
|
+
return r.json()
|
|
464
|
+
except Exception as e:
|
|
465
|
+
logger.warning("link_project_image failed: %s", e)
|
|
466
|
+
return None
|
|
467
|
+
|
|
468
|
+
def list_deployments(self, project_id: str) -> list[dict[str, Any]]:
|
|
469
|
+
"""GET /projects/{id}/deployments -- list a project's GPU deployments."""
|
|
470
|
+
try:
|
|
471
|
+
r = self._request("get", f"/projects/{project_id}/deployments")
|
|
472
|
+
r.raise_for_status()
|
|
473
|
+
return r.json()
|
|
474
|
+
except Exception as e:
|
|
475
|
+
logger.warning("list_deployments failed: %s", e)
|
|
476
|
+
return []
|
|
477
|
+
|
|
478
|
+
def create_deployment(
|
|
479
|
+
self, project_id: str, body: dict[str, Any]
|
|
480
|
+
) -> dict[str, Any] | None:
|
|
481
|
+
"""POST /projects/{id}/deployments -- create a serverless GPU deployment.
|
|
482
|
+
|
|
483
|
+
``body`` keys: name, image, provider, gpu_type, gpu_count, min_nodes,
|
|
484
|
+
max_nodes, scale_metric?, scale_target?, container_port. The image must
|
|
485
|
+
already be linked to the project.
|
|
486
|
+
"""
|
|
487
|
+
try:
|
|
488
|
+
r = self._request("post", f"/projects/{project_id}/deployments", json=body)
|
|
489
|
+
r.raise_for_status()
|
|
490
|
+
return r.json()
|
|
491
|
+
except Exception as e:
|
|
492
|
+
logger.warning("create_deployment failed: %s", e)
|
|
493
|
+
return None
|
|
494
|
+
|
|
495
|
+
def scale_deployment(
|
|
496
|
+
self, project_id: str, deployment_id: str, desired_nodes: int
|
|
497
|
+
) -> dict[str, Any] | None:
|
|
498
|
+
"""POST /projects/{id}/deployments/{dep}/scale -- set desired replicas."""
|
|
499
|
+
try:
|
|
500
|
+
r = self._request(
|
|
501
|
+
"post",
|
|
502
|
+
f"/projects/{project_id}/deployments/{deployment_id}/scale",
|
|
503
|
+
json={"desired_nodes": desired_nodes},
|
|
504
|
+
)
|
|
505
|
+
r.raise_for_status()
|
|
506
|
+
return r.json()
|
|
507
|
+
except Exception as e:
|
|
508
|
+
logger.warning("scale_deployment failed: %s", e)
|
|
509
|
+
return None
|
|
510
|
+
|
|
511
|
+
def delete_deployment(
|
|
512
|
+
self, project_id: str, deployment_id: str
|
|
513
|
+
) -> dict[str, Any] | None:
|
|
514
|
+
"""DELETE /projects/{id}/deployments/{dep} -- tear down a deployment."""
|
|
515
|
+
try:
|
|
516
|
+
r = self._request(
|
|
517
|
+
"delete", f"/projects/{project_id}/deployments/{deployment_id}"
|
|
518
|
+
)
|
|
519
|
+
r.raise_for_status()
|
|
520
|
+
return r.json()
|
|
521
|
+
except Exception as e:
|
|
522
|
+
logger.warning("delete_deployment failed: %s", e)
|
|
523
|
+
return None
|
|
524
|
+
|
|
525
|
+
def deployment_replicas(
|
|
526
|
+
self, project_id: str, deployment_id: str
|
|
527
|
+
) -> list[dict[str, Any]]:
|
|
528
|
+
"""GET /projects/{id}/deployments/{dep}/replicas -- a deployment's pods."""
|
|
529
|
+
try:
|
|
530
|
+
r = self._request(
|
|
531
|
+
"get",
|
|
532
|
+
f"/projects/{project_id}/deployments/{deployment_id}/replicas",
|
|
533
|
+
)
|
|
534
|
+
r.raise_for_status()
|
|
535
|
+
return r.json()
|
|
536
|
+
except Exception as e:
|
|
537
|
+
logger.warning("deployment_replicas failed: %s", e)
|
|
538
|
+
return []
|
|
539
|
+
|
|
432
540
|
def list_runs(self, project_id: str) -> list[dict[str, Any]]:
|
|
433
541
|
"""GET /projects/{project_id}/runs -- list runs in a project.
|
|
434
542
|
|
|
@@ -4450,5 +4450,184 @@ def drift_ask_cmd(question, project) -> None:
|
|
|
4450
4450
|
click.echo("No answer (LLM provider may be unconfigured).")
|
|
4451
4451
|
return
|
|
4452
4452
|
click.echo(f"[{r.get('action')}] {r.get('interpretation')}")
|
|
4453
|
+
|
|
4454
|
+
|
|
4455
|
+
# ---------------------------------------------------------------------------
|
|
4456
|
+
# deploy group — vendor-agnostic serverless GPU deployments
|
|
4457
|
+
# ---------------------------------------------------------------------------
|
|
4458
|
+
|
|
4459
|
+
|
|
4460
|
+
def _project_org(client, pid: str) -> str | None:
|
|
4461
|
+
"""Best-effort resolve a project's org id (for the GPU price lookup)."""
|
|
4462
|
+
try:
|
|
4463
|
+
r = client._request("get", f"/projects/{pid}")
|
|
4464
|
+
r.raise_for_status()
|
|
4465
|
+
return r.json().get("org_id")
|
|
4466
|
+
except Exception:
|
|
4467
|
+
return None
|
|
4468
|
+
|
|
4469
|
+
|
|
4470
|
+
@main.group("deploy")
|
|
4471
|
+
def deploy_group() -> None:
|
|
4472
|
+
"""Serverless GPU deployments (link image, pick GPU, deploy, scale)."""
|
|
4473
|
+
pass
|
|
4474
|
+
|
|
4475
|
+
|
|
4476
|
+
@deploy_group.command("images")
|
|
4477
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4478
|
+
def deploy_images(project) -> None:
|
|
4479
|
+
"""List images linked to a project (the deploy gate)."""
|
|
4480
|
+
client, pid = _drift_client_project(project)
|
|
4481
|
+
imgs = client.list_project_images(pid)
|
|
4482
|
+
client.close()
|
|
4483
|
+
if not imgs:
|
|
4484
|
+
click.echo("No linked images. Link one: openrunner deploy link IMAGE -p ORG/NAME")
|
|
4485
|
+
return
|
|
4486
|
+
for i in imgs:
|
|
4487
|
+
click.echo(f"- {i['image']} (tag={i.get('tag') or 'latest'}, digest={(i.get('digest') or '-')[:19]})")
|
|
4488
|
+
|
|
4489
|
+
|
|
4490
|
+
@deploy_group.command("link")
|
|
4491
|
+
@click.argument("image")
|
|
4492
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4493
|
+
@click.option("--registry-id", default=None, help="Connected registry UUID (private pull)")
|
|
4494
|
+
def deploy_link(image, project, registry_id) -> None:
|
|
4495
|
+
"""Link a deployable image to a project."""
|
|
4496
|
+
client, pid = _drift_client_project(project)
|
|
4497
|
+
rec = client.link_project_image(pid, image, registry_id=registry_id)
|
|
4498
|
+
client.close()
|
|
4499
|
+
if not rec:
|
|
4500
|
+
click.echo("Error: failed to link image.", err=True)
|
|
4501
|
+
raise SystemExit(1)
|
|
4502
|
+
click.echo(f"Linked {rec['image']} — Deploy is now active for this project.")
|
|
4503
|
+
|
|
4504
|
+
|
|
4505
|
+
@deploy_group.command("gpus")
|
|
4506
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4507
|
+
@click.option("--provider", default="runpod", help="Filter by provider (default: runpod)")
|
|
4508
|
+
def deploy_gpus(project, provider) -> None:
|
|
4509
|
+
"""List deployable GPU offers (provider · GPU · VRAM · price) for recommendations."""
|
|
4510
|
+
client, pid = _drift_client_project(project)
|
|
4511
|
+
org = _project_org(client, pid)
|
|
4512
|
+
if not org:
|
|
4513
|
+
client.close()
|
|
4514
|
+
click.echo("Error: could not resolve org for prices.", err=True)
|
|
4515
|
+
raise SystemExit(1)
|
|
4516
|
+
try:
|
|
4517
|
+
r = client._request("get", "/gpu/prices", params={"org_id": org})
|
|
4518
|
+
r.raise_for_status()
|
|
4519
|
+
offers = r.json()
|
|
4520
|
+
except Exception as e:
|
|
4521
|
+
client.close()
|
|
4522
|
+
click.echo(f"Error fetching prices: {e}", err=True)
|
|
4523
|
+
raise SystemExit(1)
|
|
4524
|
+
client.close()
|
|
4525
|
+
seen = set()
|
|
4526
|
+
for o in offers:
|
|
4527
|
+
if provider and o.get("provider") != provider:
|
|
4528
|
+
continue
|
|
4529
|
+
key = (o.get("provider"), o.get("gpu_type_normalized"))
|
|
4530
|
+
if key in seen:
|
|
4531
|
+
continue
|
|
4532
|
+
seen.add(key)
|
|
4533
|
+
click.echo(
|
|
4534
|
+
f"- {o.get('provider')} · {o.get('gpu_type_normalized')} · "
|
|
4535
|
+
f"{o.get('gpu_memory_gb')}GB · ${o.get('price_per_hour')}/hr"
|
|
4536
|
+
)
|
|
4537
|
+
|
|
4538
|
+
|
|
4539
|
+
@deploy_group.command("create")
|
|
4540
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4541
|
+
@click.option("--name", "-n", required=True, help="Deployment name")
|
|
4542
|
+
@click.option("--image", required=True, help="Image (must be linked to the project)")
|
|
4543
|
+
@click.option("--provider", default="runpod", help="Provider (RunPod supported today)")
|
|
4544
|
+
@click.option("--gpu", required=True, help="GPU type, e.g. A100_80GB")
|
|
4545
|
+
@click.option("--gpu-count", default=1, type=int, help="GPUs per replica")
|
|
4546
|
+
@click.option("--min", "min_nodes", default=1, type=int, help="Min replicas")
|
|
4547
|
+
@click.option("--max", "max_nodes", default=1, type=int, help="Max replicas")
|
|
4548
|
+
@click.option("--metric", default=None, type=click.Choice(["gpu_util", "request_rate", "inflight"]), help="Autoscale metric")
|
|
4549
|
+
@click.option("--target", default=None, type=float, help="Autoscale target for --metric")
|
|
4550
|
+
@click.option("--port", default=8000, type=int, help="Container port")
|
|
4551
|
+
def deploy_create(project, name, image, provider, gpu, gpu_count, min_nodes, max_nodes, metric, target, port) -> None:
|
|
4552
|
+
"""Create a serverless GPU deployment for a linked image."""
|
|
4553
|
+
client, pid = _drift_client_project(project)
|
|
4554
|
+
body = {
|
|
4555
|
+
"name": name, "image": image, "provider": provider, "gpu_type": gpu,
|
|
4556
|
+
"gpu_count": gpu_count, "min_nodes": min_nodes, "max_nodes": max_nodes,
|
|
4557
|
+
"container_port": port,
|
|
4558
|
+
}
|
|
4559
|
+
if metric:
|
|
4560
|
+
body["scale_metric"] = metric
|
|
4561
|
+
if target is not None:
|
|
4562
|
+
body["scale_target"] = target
|
|
4563
|
+
dep = client.create_deployment(pid, body)
|
|
4564
|
+
client.close()
|
|
4565
|
+
if not dep:
|
|
4566
|
+
click.echo("Error: failed to create deployment (is the image linked? provider supported?).", err=True)
|
|
4567
|
+
raise SystemExit(1)
|
|
4568
|
+
click.echo(f"Created deployment {dep['name']} [{dep['id']}] status={dep['status']} "
|
|
4569
|
+
f"desired={dep['desired_nodes']} (min {dep['min_nodes']} / max {dep['max_nodes']}).")
|
|
4570
|
+
|
|
4571
|
+
|
|
4572
|
+
@deploy_group.command("ls")
|
|
4573
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4574
|
+
def deploy_ls(project) -> None:
|
|
4575
|
+
"""List a project's deployments."""
|
|
4576
|
+
client, pid = _drift_client_project(project)
|
|
4577
|
+
deps = client.list_deployments(pid)
|
|
4578
|
+
client.close()
|
|
4579
|
+
if not deps:
|
|
4580
|
+
click.echo("No deployments.")
|
|
4581
|
+
return
|
|
4582
|
+
for d in deps:
|
|
4583
|
+
click.echo(
|
|
4584
|
+
f"- {d['name']} [{d['id']}] {d['status']} · {d['provider']}/{d['gpu_type']}×{d['gpu_count']} "
|
|
4585
|
+
f"· {d['desired_nodes']}/{d['max_nodes']} desired · {d['image']}"
|
|
4586
|
+
)
|
|
4587
|
+
|
|
4588
|
+
|
|
4589
|
+
@deploy_group.command("scale")
|
|
4590
|
+
@click.argument("deployment_id")
|
|
4591
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4592
|
+
@click.option("--to", "desired", required=True, type=int, help="Desired replica count")
|
|
4593
|
+
def deploy_scale(deployment_id, project, desired) -> None:
|
|
4594
|
+
"""Set a deployment's desired replica count (clamped to [min,max])."""
|
|
4595
|
+
client, pid = _drift_client_project(project)
|
|
4596
|
+
d = client.scale_deployment(pid, deployment_id, desired)
|
|
4597
|
+
client.close()
|
|
4598
|
+
if not d:
|
|
4599
|
+
click.echo("Error: scale failed.", err=True)
|
|
4600
|
+
raise SystemExit(1)
|
|
4601
|
+
click.echo(f"{d['name']} → desired={d['desired_nodes']} status={d['status']}")
|
|
4602
|
+
|
|
4603
|
+
|
|
4604
|
+
@deploy_group.command("replicas")
|
|
4605
|
+
@click.argument("deployment_id")
|
|
4606
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4607
|
+
def deploy_replicas(deployment_id, project) -> None:
|
|
4608
|
+
"""List a deployment's replica pods."""
|
|
4609
|
+
client, pid = _drift_client_project(project)
|
|
4610
|
+
reps = client.deployment_replicas(pid, deployment_id)
|
|
4611
|
+
client.close()
|
|
4612
|
+
if not reps:
|
|
4613
|
+
click.echo("No replicas.")
|
|
4614
|
+
return
|
|
4615
|
+
for r in reps:
|
|
4616
|
+
host = f"{r.get('ssh_host')}:{r.get('ssh_port')}" if r.get("ssh_host") else "-"
|
|
4617
|
+
click.echo(f"- #{r.get('replica_index')} {r['status']} {host}")
|
|
4618
|
+
|
|
4619
|
+
|
|
4620
|
+
@deploy_group.command("rm")
|
|
4621
|
+
@click.argument("deployment_id")
|
|
4622
|
+
@click.option("--project", "-p", default=None, help="Project org/name or UUID")
|
|
4623
|
+
def deploy_rm(deployment_id, project) -> None:
|
|
4624
|
+
"""Tear down a deployment (terminates all replicas)."""
|
|
4625
|
+
client, pid = _drift_client_project(project)
|
|
4626
|
+
d = client.delete_deployment(pid, deployment_id)
|
|
4627
|
+
client.close()
|
|
4628
|
+
if not d:
|
|
4629
|
+
click.echo("Error: delete failed.", err=True)
|
|
4630
|
+
raise SystemExit(1)
|
|
4631
|
+
click.echo(f"Deployment {d['name']} deleted (replicas terminating).")
|
|
4453
4632
|
import json as _json
|
|
4454
4633
|
click.echo(_json.dumps(r.get("data", {}), indent=2)[:2000])
|
|
@@ -2746,6 +2746,15 @@ the reference). Do each step; ask only when genuinely ambiguous.
|
|
|
2746
2746
|
## Step 2 -- resolve project + mint a DRIFT-ONLY key for the container
|
|
2747
2747
|
- `openrunner login` if needed. Resolve the project id (from the `org/name` arg,
|
|
2748
2748
|
else `APIClient.list_projects()`; ask if ambiguous).
|
|
2749
|
+
- **Auto-create the drift project if missing.** If the target has no drift project
|
|
2750
|
+
yet, but a project of the **same name already exists with runs** (a training
|
|
2751
|
+
project, found via `list_projects()`), create a dedicated drift project with that
|
|
2752
|
+
same name in the same org
|
|
2753
|
+
(`create_project_api(org_id, {{"name": <name>, "description": "Inference drift
|
|
2754
|
+
for <source project> (<id>)"}})`) and use its id for drift + the scoped key.
|
|
2755
|
+
**Link them** so lineage is explicit: record the source project's id in the new
|
|
2756
|
+
project's description and reuse the name as the drift `monitor`. Only auto-create
|
|
2757
|
+
when a same-name run project exists -- never silently create on a typo.
|
|
2749
2758
|
- **Mint a scoped key for this container** -- do NOT reuse the user's full key.
|
|
2750
2759
|
Run `openrunner drift key --project ORG/NAME --name drift-<service>` (add
|
|
2751
2760
|
`--json` to capture it). It returns a key carrying ONLY `drift:read` +
|
|
@@ -2790,6 +2799,77 @@ AFTER the response is produced, insert a wrapped `record_inference(...)`:
|
|
|
2790
2799
|
"""
|
|
2791
2800
|
|
|
2792
2801
|
|
|
2802
|
+
DEPLOY_CMD = """---
|
|
2803
|
+
name: {prefix}deploy
|
|
2804
|
+
description: Interactively deploy a project's model image on serverless GPUs -- reads the model card's measured results to RECOMMEND a GPU (VRAM headroom) + platform (price/availability), asks you to confirm platform + GPU, sets replica bounds/autoscale, creates the deployment and watches it roll out
|
|
2805
|
+
argument-hint: "[project org/name] [--image REF] [--name NAME]"
|
|
2806
|
+
allowed-tools:
|
|
2807
|
+
- Bash
|
|
2808
|
+
- Read
|
|
2809
|
+
- Grep
|
|
2810
|
+
- Glob
|
|
2811
|
+
- AskUserQuestion
|
|
2812
|
+
---
|
|
2813
|
+
|
|
2814
|
+
Deploy a model image on governed, autoscaled GPUs -- with a GPU/platform
|
|
2815
|
+
**recommendation grounded in the model card's measured results**, then an
|
|
2816
|
+
interactive confirm. Never guess sizing; read real numbers.
|
|
2817
|
+
|
|
2818
|
+
## Step 1 -- project + a deployable image
|
|
2819
|
+
- Resolve the project (arg `org/name`, else `openrunner` config / ask).
|
|
2820
|
+
- `openrunner deploy images -p ORG/NAME`. If none linked: take `--image REF`
|
|
2821
|
+
(or ask), then `openrunner deploy link REF -p ORG/NAME` (add `--registry-id`
|
|
2822
|
+
for a private image). A project needs >=1 linked image before it can deploy.
|
|
2823
|
+
|
|
2824
|
+
## Step 2 -- read the model card's MEASURED results (drives the recommendation)
|
|
2825
|
+
Pull the model card + run summary and extract, with numbers only:
|
|
2826
|
+
- parameter count / model size on disk, and serving **precision** (fp16/bf16/int8/
|
|
2827
|
+
fp8) -- from the card or the run `config`/`summary`.
|
|
2828
|
+
- measured **peak VRAM** at inference, **throughput** (req/s or tok/s), **latency**
|
|
2829
|
+
(p50/p95), and the **batch size** they were measured at.
|
|
2830
|
+
- Use MCP when available (`mcp__openrunner__openrunner_search_papers` /
|
|
2831
|
+
model-card tools / `openrunner_get_run_metrics`); else read the card markdown /
|
|
2832
|
+
repo reports. If a figure is missing, say so -- do NOT invent it; estimate VRAM
|
|
2833
|
+
as `params x bytes/param x ~1.2 overhead` and LABEL it an estimate.
|
|
2834
|
+
|
|
2835
|
+
## Step 3 -- recommend a GPU + platform
|
|
2836
|
+
- `openrunner deploy gpus -p ORG/NAME` lists offers (provider · GPU · VRAM · $/hr).
|
|
2837
|
+
- Recommend the **cheapest GPU whose VRAM comfortably fits** measured/estimated
|
|
2838
|
+
peak VRAM with headroom (>=20-30%% for activations/batch growth); prefer the
|
|
2839
|
+
provider with the best price and availability. Note when a bigger GPU is needed
|
|
2840
|
+
for the target batch/throughput, or when int8/fp8 lets a smaller GPU fit.
|
|
2841
|
+
- Summarise the reasoning in 2-3 lines (VRAM need vs GPU VRAM, $/hr, why).
|
|
2842
|
+
|
|
2843
|
+
## Step 4 -- confirm platform + GPU (interactive)
|
|
2844
|
+
Use AskUserQuestion with the recommendation FIRST and marked "(Recommended)":
|
|
2845
|
+
- **Platform**: the supported providers (RunPod today; others are pricing-only).
|
|
2846
|
+
- **GPU**: 3-4 offers spanning the recommendation +/- one size, each labelled with
|
|
2847
|
+
VRAM + $/hr so the trade-off is visible.
|
|
2848
|
+
Then ask replica bounds + autoscale:
|
|
2849
|
+
- **min / max replicas** (min 0 = scale-to-zero: cheap + spiky, but cold start ~
|
|
2850
|
+
minutes; min 1 = always warm).
|
|
2851
|
+
- **autoscale**: manual, or a metric (`gpu_util` / `request_rate` / `inflight`)
|
|
2852
|
+
with a target.
|
|
2853
|
+
|
|
2854
|
+
## Step 5 -- create + watch
|
|
2855
|
+
- `openrunner deploy create -p ORG/NAME --name NAME --image REF --provider P
|
|
2856
|
+
--gpu GPU [--gpu-count N] --min MIN --max MAX [--metric M --target T]`.
|
|
2857
|
+
- Poll `openrunner deploy ls -p ORG/NAME` + `openrunner deploy replicas <id>
|
|
2858
|
+
-p ORG/NAME` until replicas are running; report status + the endpoint URL when
|
|
2859
|
+
the router assigns one. Scale later with `openrunner deploy scale <id> --to N`.
|
|
2860
|
+
|
|
2861
|
+
## Guardrails
|
|
2862
|
+
- Ground every sizing number in the card/run; label anything estimated. Never
|
|
2863
|
+
fabricate VRAM/throughput.
|
|
2864
|
+
- Deploying spends real money at the provider -- show the picked GPU + $/hr and
|
|
2865
|
+
CONFIRM before `create`. Mention scale-to-zero to cap idle cost.
|
|
2866
|
+
- Fit VRAM with headroom; warn if the recommendation is tight for the target
|
|
2867
|
+
batch.
|
|
2868
|
+
- RunPod is the only real provisioning adapter today; other providers are
|
|
2869
|
+
pricing-only -- say so if picked.
|
|
2870
|
+
"""
|
|
2871
|
+
|
|
2872
|
+
|
|
2793
2873
|
BUILD_API_CMD = """---
|
|
2794
2874
|
name: {prefix}build-api
|
|
2795
2875
|
description: Scaffold a production inference API for a model in THIS repo -- FastAPI /predict + /health, typed request/response, Dockerfile (pushable via the OpenRunner registry), env config, and optional baked-in drift monitoring; ready to deploy on governed GPUs
|
|
@@ -2890,6 +2970,7 @@ def install_claude_code() -> list[str]:
|
|
|
2890
2970
|
"drift.md": DRIFT_CMD,
|
|
2891
2971
|
"drift-install.md": DRIFT_INSTALL_CMD,
|
|
2892
2972
|
"build-api.md": BUILD_API_CMD,
|
|
2973
|
+
"deploy.md": DEPLOY_CMD,
|
|
2893
2974
|
}
|
|
2894
2975
|
|
|
2895
2976
|
files = []
|
|
@@ -3095,6 +3176,7 @@ def _install_all_commands_to_dir(cmd_dir: Path, prefix: str = "openrunner:") ->
|
|
|
3095
3176
|
"drift.md": DRIFT_CMD,
|
|
3096
3177
|
"drift-install.md": DRIFT_INSTALL_CMD,
|
|
3097
3178
|
"build-api.md": BUILD_API_CMD,
|
|
3179
|
+
"deploy.md": DEPLOY_CMD,
|
|
3098
3180
|
}
|
|
3099
3181
|
|
|
3100
3182
|
files = []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-aaa/config.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/fixtures/wandb-export-mini/run-bbb/config.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrunner_sdk-2.37.7 → openrunner_sdk-2.37.9}/tests/integration/test_artifact_round_trip.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|