openrunner-sdk 2.41.6__tar.gz → 2.41.7__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.41.6 → openrunner_sdk-2.41.7}/PKG-INFO +1 -1
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/CLAUDE.md +42 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/__init__.py +9 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/cli.py +38 -6
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/datasets.py +47 -2
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/__init__.py +55 -18
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/install_commands.py +89 -0
- openrunner_sdk-2.41.7/openrunner/llms-full.txt +258 -0
- openrunner_sdk-2.41.7/openrunner/llms.py +49 -0
- openrunner_sdk-2.41.7/openrunner/llms.txt +42 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/sweep.py +31 -27
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/pyproject.toml +7 -1
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_datasets_module.py +31 -1
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_gpu_cluster.py +46 -8
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_sdk_gpu_api.py +20 -3
- openrunner_sdk-2.41.7/tests/test_llms.py +43 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sweep.py +55 -2
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/.gitignore +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/=6.0 +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/=8.1 +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/README.md +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/_native.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/_retry_transport.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/_safepath.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/_secret_rules.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/api_client.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/artifact.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/autoresearch.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/buffer.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/cache.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/config.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/cost.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/dataset.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/environment.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/evaluation.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/feedback.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/git_info.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/api_integration.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/cost_guard.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/gpu_types.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/price_compare.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/provider_base.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/forge_provider.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/lambda_cloud.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/modal_provider.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/ovhcloud.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/runpod.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/providers/vastai.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/runner.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/gpu/workspace_sync.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/guardrails.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/handover.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/hooks/patent-lab-post-commit +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/accelerate.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/anthropic_tracer.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/catboost.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/diffusers.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/fastai.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/forced_alignment.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/gladia.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/gymnasium.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/huggingface.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/hydra.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/ignite.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/jax.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/keras.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/langchain.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/lightgbm.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/lightning.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/llamaindex.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/openai_finetune.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/openai_tracer.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/optuna.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/pytorch.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/sb3.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/sklearn.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/skypilot.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/tensorflow.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/trl.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/tts.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/ultralytics.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/voice_agent.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/whisper.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/integration/xgboost.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/launch.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/machine.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/mcp_server.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/media.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/migrate.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/model.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/model_card.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/offline.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/patent_scan.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/pii.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/plot.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/projects.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/prompt.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/query_api.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/redact.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/reload.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/research.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/research_policy.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/run.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/scorers.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/sender.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/session.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/settings.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/summary.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/sync.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/system_metrics.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/tensorboard.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/tools/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/tools/patent_report.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/trace.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/transcript_formatter.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/wal.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/wandb_compat/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/wandb_compat/_shim.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/openrunner/wer.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/scripts/gen_betterleaks_rules.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/conftest.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/integration/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/integration/conftest.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/integration/test_artifact_round_trip.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_alert.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_aliases.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_api_client.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_api_client_methods.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_api_client_transport.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_artifact.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_buffer.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cache.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_class_scorers.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli_artifact_sweep.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli_datasets.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli_gpu_registry_deploy.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli_infra.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli_remainder.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_cli_topup.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_config.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_evaluation.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_finish.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_git_info.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/__init__.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/conftest.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_cost_guard.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_engine_serverside.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_forge.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_governed_jobs.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_gpu_types.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_lambda.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_modal.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_ovh_training.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_ovhcloud.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_price_compare.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_provider_base.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_runner.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_runpod.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_vastai.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu/test_workspace_sync.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_gpu_modal_creds.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_init.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_init_facade.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_install_commands.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_fastai.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_huggingface.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_keras.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_langchain.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_lightning.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_pytorch.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_setA.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_setB.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_setC.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_sklearn.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_integration_xgboost.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_launch.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_log.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_log_code.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_machine_migrate.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_mcp_decisions.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_mcp_monitor.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_mcp_predictions.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_mcp_server.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_media.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_media_extra.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_migrate.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_offline.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_offline_sync.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_patent_scan.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_pii.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_plot.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_plot_media_extra2.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_prompt_module.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_pure_modules.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_query_api.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_redact.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_reload_module.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_research_module.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_resume.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_retry_transport.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_run_module.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sdk_cluster_j1.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sdk_cluster_j2.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sdk_cluster_j3.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sdk_cluster_j4.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sdk_core_edges.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sdk_features.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_sender.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_session_module.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_session_sync.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_summary.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_system_metrics.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_topup_hi.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/tests/test_trace.py +0 -0
- {openrunner_sdk-2.41.6 → openrunner_sdk-2.41.7}/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.41.
|
|
3
|
+
Version: 2.41.7
|
|
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
|
|
@@ -176,3 +176,45 @@ When the user asks about papers, research, or sessions:
|
|
|
176
176
|
- Use `mcp__openrunner__openrunner_search_research` for research plans
|
|
177
177
|
- Use `mcp__openrunner__openrunner_search_sessions` for AI session history
|
|
178
178
|
- Use `mcp__openrunner__openrunner_update_paper` to modify paper sections
|
|
179
|
+
|
|
180
|
+
## Container registry & serverless deployment
|
|
181
|
+
|
|
182
|
+
Register a container registry (Docker Hub, GHCR, Google Artifact Registry, AWS
|
|
183
|
+
ECR, Azure ACR, OVH/Harbor) once; the upstream credential is stored encrypted
|
|
184
|
+
server-side and the OpenRunner **broker** proxies pull/push — the client never
|
|
185
|
+
holds the upstream key.
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
openrunner registry add --name "Harbor ML" --url REG_URL --username U --token T --namespace NS
|
|
189
|
+
openrunner registry set-default <id> # broker fallback when the repo path is ambiguous
|
|
190
|
+
openrunner registry login # docker login the broker (short-lived token)
|
|
191
|
+
docker push <registry_host>/<namespace>/<project-slug>:<user>-<name>-<tag>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Repo convention (`canonical_image_name`): `{namespace}/{project_slug}`, tag leads
|
|
195
|
+
with the user — e.g. `model-team/ner-email:jl-int8-v1`.
|
|
196
|
+
|
|
197
|
+
**Images link to a project = the deploy gate.** An image pushed **through the
|
|
198
|
+
broker** is **auto-linked** to its project on the manifest PUT (project resolved
|
|
199
|
+
from the repo's project-slug segment), so it appears under the project's
|
|
200
|
+
**Registry** tab (artifact page) and the project-overview **Registry** panel with
|
|
201
|
+
no manual step. Direct-to-upstream pushes (or registries that hide their catalog,
|
|
202
|
+
e.g. OVH Harbor robots can't list `_catalog`) must be linked explicitly:
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
openrunner deploy link IMAGE -p ORG/NAME [--registry-id UUID]
|
|
206
|
+
openrunner deploy images -p ORG/NAME # list linked images
|
|
207
|
+
openrunner deploy gpus -p ORG/NAME # deployable GPU offers
|
|
208
|
+
openrunner deploy create ... ; openrunner deploy scale <id> N ; openrunner deploy call <id> ...
|
|
209
|
+
```
|
|
210
|
+
API: `GET/POST /projects/{id}/images`, `.../deployments`. SDK:
|
|
211
|
+
`client.list_project_images(pid)`, `client.link_project_image(pid, image, registry_id=)`.
|
|
212
|
+
Slash: `/openrunner:registry`, `/openrunner:deploy`, `/openrunner:build-api`.
|
|
213
|
+
|
|
214
|
+
## Full LLM map: llms.txt
|
|
215
|
+
|
|
216
|
+
The complete end-to-end, LLM-oriented map of OpenRunner (dataset → run
|
|
217
|
+
instrumentation → GPU training → sweep → registry → deploy → handover) lives at
|
|
218
|
+
**https://openrun.gladia.io/llms-full.txt** (source: `src/web/public/llms-full.txt`),
|
|
219
|
+
with a short index at **/llms.txt**. Read the full doc to ground yourself in the
|
|
220
|
+
real commands + conventions before driving OpenRunner end-to-end for a new project.
|
|
@@ -112,11 +112,20 @@ from openrunner.datasets import (
|
|
|
112
112
|
word_lookup,
|
|
113
113
|
set_dataset_card,
|
|
114
114
|
set_storage_policy,
|
|
115
|
+
update_dataset,
|
|
115
116
|
upload_file,
|
|
116
117
|
upload_sharded,
|
|
117
118
|
upload_folder,
|
|
118
119
|
)
|
|
119
120
|
from openrunner.config import Config
|
|
121
|
+
from openrunner.llms import (
|
|
122
|
+
llms_txt,
|
|
123
|
+
llms_txt_path,
|
|
124
|
+
LLMS_TXT_URL,
|
|
125
|
+
LLMS_FULL_TXT_URL,
|
|
126
|
+
LLMS_TXT_PATH,
|
|
127
|
+
LLMS_FULL_TXT_PATH,
|
|
128
|
+
)
|
|
120
129
|
from openrunner.model import Model
|
|
121
130
|
from openrunner.prompt import MessagesPrompt, Prompt, StringPrompt
|
|
122
131
|
from openrunner.launch import LaunchJob, launch, from_run as _launch_from_run
|
|
@@ -863,8 +863,11 @@ def artifact_list(project: str | None, project_opt: str | None) -> None:
|
|
|
863
863
|
|
|
864
864
|
@artifact.command("get")
|
|
865
865
|
@click.argument("name")
|
|
866
|
-
@click.option("--root", "-r",
|
|
867
|
-
|
|
866
|
+
@click.option("--root", "-r", "--output", "-o", "root", default=".",
|
|
867
|
+
help="Download directory (default: .). --output/-o is an alias.")
|
|
868
|
+
@click.option("--project", "-p", default=None,
|
|
869
|
+
help="Scope the lookup to ORG/PROJECT (else searches all accessible projects)")
|
|
870
|
+
def artifact_get(name: str, root: str, project: str | None = None) -> None:
|
|
868
871
|
"""Download an artifact to a local directory.
|
|
869
872
|
|
|
870
873
|
NAME can use colon syntax: my-dataset:latest or my-model:v3.
|
|
@@ -886,8 +889,16 @@ def artifact_get(name: str, root: str) -> None:
|
|
|
886
889
|
else:
|
|
887
890
|
alias = ref
|
|
888
891
|
|
|
889
|
-
# Find artifact by listing
|
|
892
|
+
# Find artifact by listing accessible projects. When --project is given we
|
|
893
|
+
# only search that one (faster, and disambiguates a name shared across
|
|
894
|
+
# projects); otherwise fall back to scanning every accessible project.
|
|
890
895
|
projects = client.list_projects()
|
|
896
|
+
if project:
|
|
897
|
+
projects = [
|
|
898
|
+
p for p in projects
|
|
899
|
+
if project in (p.get("id"), p.get("name"), p.get("slug"),
|
|
900
|
+
f"{p.get('org_slug')}/{p.get('slug')}")
|
|
901
|
+
] or projects
|
|
891
902
|
artifact_detail = None
|
|
892
903
|
target_version_id = None
|
|
893
904
|
|
|
@@ -1135,9 +1146,12 @@ def cache_cleanup(max_size: float | None) -> None:
|
|
|
1135
1146
|
|
|
1136
1147
|
@main.command("download-artifact")
|
|
1137
1148
|
@click.argument("name")
|
|
1138
|
-
@click.option("--root", "-r",
|
|
1149
|
+
@click.option("--root", "-r", "--output", "-o", "root", default=".",
|
|
1150
|
+
help="Download directory (default: .). --output/-o is an alias.")
|
|
1151
|
+
@click.option("--project", "-p", default=None,
|
|
1152
|
+
help="Scope the lookup to ORG/PROJECT (else searches all accessible projects)")
|
|
1139
1153
|
@click.pass_context
|
|
1140
|
-
def download_artifact_cmd(ctx: click.Context, name: str, root: str) -> None:
|
|
1154
|
+
def download_artifact_cmd(ctx: click.Context, name: str, root: str, project: str | None) -> None:
|
|
1141
1155
|
"""Download an artifact to a local directory.
|
|
1142
1156
|
|
|
1143
1157
|
NAME can use colon syntax: my-dataset:latest or my-model:v3.
|
|
@@ -1145,7 +1159,7 @@ def download_artifact_cmd(ctx: click.Context, name: str, root: str) -> None:
|
|
|
1145
1159
|
|
|
1146
1160
|
This is a top-level alias for `openrunner artifact get`.
|
|
1147
1161
|
"""
|
|
1148
|
-
ctx.invoke(artifact_get, name=name, root=root)
|
|
1162
|
+
ctx.invoke(artifact_get, name=name, root=root, project=project)
|
|
1149
1163
|
|
|
1150
1164
|
|
|
1151
1165
|
@main.command("upload-artifact")
|
|
@@ -3221,6 +3235,24 @@ def version_cmd(check: bool) -> None:
|
|
|
3221
3235
|
click.echo("Up to date.")
|
|
3222
3236
|
|
|
3223
3237
|
|
|
3238
|
+
@main.command("llms")
|
|
3239
|
+
@click.option("--full", is_flag=True, help="Print the complete guide (llms-full.txt) instead of the index")
|
|
3240
|
+
@click.option("--path", "show_path", is_flag=True, help="Print the bundled file path instead of its content")
|
|
3241
|
+
def llms_cmd(full: bool, show_path: bool) -> None:
|
|
3242
|
+
"""Print the bundled LLM-oriented OpenRunner doc.
|
|
3243
|
+
|
|
3244
|
+
The short index by default, or the complete end-to-end guide with --full.
|
|
3245
|
+
Bundled in the package (works offline); also served at /llms.txt and
|
|
3246
|
+
/llms-full.txt on the instance.
|
|
3247
|
+
"""
|
|
3248
|
+
from openrunner import llms as _llms
|
|
3249
|
+
|
|
3250
|
+
if show_path:
|
|
3251
|
+
click.echo(_llms.llms_txt_path(full=full))
|
|
3252
|
+
else:
|
|
3253
|
+
click.echo(_llms.llms_txt(full=full))
|
|
3254
|
+
|
|
3255
|
+
|
|
3224
3256
|
@main.command("_update_nudge", hidden=True)
|
|
3225
3257
|
def update_nudge_cmd() -> None:
|
|
3226
3258
|
"""Print ONE update-hint line if a newer SDK exists, else nothing. Cheap:
|
|
@@ -453,11 +453,24 @@ class DatasetsClient:
|
|
|
453
453
|
complete — so the dataset's file count grows live and an interrupted run
|
|
454
454
|
is genuinely resumable (re-run with ``skip_existing`` to continue). The
|
|
455
455
|
API stays out of the byte path, so throughput is bandwidth-bound.
|
|
456
|
+
|
|
457
|
+
``skip_existing`` skips a file only when the remote copy has the SAME
|
|
458
|
+
path AND the SAME content (sha256). A file whose bytes changed since the
|
|
459
|
+
last upload is re-uploaded — a pure path match would silently drop
|
|
460
|
+
edits, making a dataset update look successful while sending nothing.
|
|
456
461
|
"""
|
|
462
|
+
import hashlib
|
|
457
463
|
import os
|
|
458
464
|
import sys
|
|
459
465
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
460
466
|
|
|
467
|
+
def _sha256(fp: str) -> str:
|
|
468
|
+
h = hashlib.sha256()
|
|
469
|
+
with open(fp, "rb") as fh:
|
|
470
|
+
for chunk in iter(lambda: fh.read(1024 * 1024), b""):
|
|
471
|
+
h.update(chunk)
|
|
472
|
+
return h.hexdigest()
|
|
473
|
+
|
|
461
474
|
ds = self._resolve(repo_id)
|
|
462
475
|
items: list[tuple[str, str]] = []
|
|
463
476
|
for root, _dirs, names in os.walk(folder):
|
|
@@ -469,8 +482,16 @@ class DatasetsClient:
|
|
|
469
482
|
items.append((full, rel))
|
|
470
483
|
if skip_existing:
|
|
471
484
|
try:
|
|
472
|
-
|
|
473
|
-
|
|
485
|
+
# Map remote path -> sha256. Skip a local file only when both the
|
|
486
|
+
# path and the content hash match; changed files are re-uploaded.
|
|
487
|
+
remote = {f["path"]: (f.get("sha256") or "") for f in self.list_files(repo_id)}
|
|
488
|
+
kept: list[tuple[str, str]] = []
|
|
489
|
+
for full, rel in items:
|
|
490
|
+
rsha = remote.get(rel)
|
|
491
|
+
if rsha and rsha == _sha256(full):
|
|
492
|
+
continue
|
|
493
|
+
kept.append((full, rel))
|
|
494
|
+
items = kept
|
|
474
495
|
except Exception:
|
|
475
496
|
pass
|
|
476
497
|
if not items:
|
|
@@ -1008,6 +1029,24 @@ class DatasetsClient:
|
|
|
1008
1029
|
_check(r)
|
|
1009
1030
|
return r.json().get("columns", [])
|
|
1010
1031
|
|
|
1032
|
+
def delete_column(self, repo_id: str, name: str) -> list[str]:
|
|
1033
|
+
"""Delete an editable column from an indexed dataset.
|
|
1034
|
+
|
|
1035
|
+
Miroir exact de :meth:`add_column` — retire la colonne overlay (ou de la
|
|
1036
|
+
members table d'un dérivé) ``name`` ; les colonnes source indexées
|
|
1037
|
+
("parent") restent **en lecture seule** et ne peuvent pas être supprimées.
|
|
1038
|
+
|
|
1039
|
+
Exact mirror of :meth:`add_column`: removes the overlay (or derived-member)
|
|
1040
|
+
column ``name`` — the indexed source ("parent") columns stay **read-only**
|
|
1041
|
+
and cannot be deleted. A read-only source column (or the primary key) is
|
|
1042
|
+
rejected (400); an unknown column returns 404. Returns the remaining
|
|
1043
|
+
editable column names.
|
|
1044
|
+
"""
|
|
1045
|
+
ds = self._resolve(repo_id)
|
|
1046
|
+
r = self._http.delete(f"/datasets/{ds.id}/columns/{name}")
|
|
1047
|
+
_check(r)
|
|
1048
|
+
return r.json().get("columns", [])
|
|
1049
|
+
|
|
1011
1050
|
def set_cell(self, repo_id: str, debug_id: str, column: str,
|
|
1012
1051
|
value: str | None = None) -> dict:
|
|
1013
1052
|
"""Set ONE editable cell (creates the column on first write).
|
|
@@ -1261,6 +1300,12 @@ def add_column(repo_id: str, name: str, *, default: str | None = None) -> list[s
|
|
|
1261
1300
|
return _c().add_column(repo_id, name, default=default)
|
|
1262
1301
|
|
|
1263
1302
|
|
|
1303
|
+
def delete_column(repo_id: str, name: str) -> list[str]:
|
|
1304
|
+
"""Delete an editable column from an indexed dataset (source columns stay
|
|
1305
|
+
read-only). Module-level mirror of DatasetsClient.delete_column."""
|
|
1306
|
+
return _c().delete_column(repo_id, name)
|
|
1307
|
+
|
|
1308
|
+
|
|
1264
1309
|
def set_cell(repo_id: str, debug_id: str, column: str, value: str | None = None) -> dict:
|
|
1265
1310
|
"""Set one editable cell of a dataset row (creates the column if new)."""
|
|
1266
1311
|
return _c().set_cell(repo_id, debug_id, column, value)
|
|
@@ -534,25 +534,65 @@ async def terminate(
|
|
|
534
534
|
provider: str | None = None,
|
|
535
535
|
api_key: str | None = None,
|
|
536
536
|
) -> bool:
|
|
537
|
-
"""Terminate a GPU instance
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
537
|
+
"""Terminate a GPU instance.
|
|
538
|
+
|
|
539
|
+
Preferred path (governed): when no explicit ``api_key`` is passed, the
|
|
540
|
+
platform terminates the pod SERVER-SIDE — it decrypts the org's stored
|
|
541
|
+
provider key (which never leaves the API), kills the pod, VERIFIES it is
|
|
542
|
+
gone, and only then marks the instance ``terminated``. This is the only
|
|
543
|
+
path that works when the provider key lives on the platform (the common
|
|
544
|
+
case): a client-side terminate cannot see that key and would fail with
|
|
545
|
+
"No API key found for provider …".
|
|
546
|
+
|
|
547
|
+
Fallback (BYO key): when an explicit ``api_key`` is given, terminate the
|
|
548
|
+
pod directly via the provider API. The backend status is marked
|
|
549
|
+
``terminated`` ONLY if the provider kill actually succeeded — never
|
|
550
|
+
unconditionally, since a falsely-"terminated" record strands a BILLING pod
|
|
551
|
+
that our records claim is dead.
|
|
544
552
|
|
|
545
553
|
Args:
|
|
546
554
|
instance_id: Platform instance ID.
|
|
547
555
|
provider: Provider name (auto-detected from backend if None).
|
|
548
|
-
api_key: Explicit provider API key.
|
|
556
|
+
api_key: Explicit provider API key (opts into the client-side path).
|
|
549
557
|
|
|
550
558
|
Returns:
|
|
551
|
-
True if termination
|
|
559
|
+
True if termination is confirmed.
|
|
552
560
|
"""
|
|
553
561
|
api_client = _get_api_client()
|
|
554
562
|
|
|
555
|
-
|
|
563
|
+
def _stop_guard() -> None:
|
|
564
|
+
guard_entry = _active_guards.pop(instance_id, None)
|
|
565
|
+
if guard_entry:
|
|
566
|
+
guard_entry["stop"].set()
|
|
567
|
+
logger.info("Cost guard stopped for instance %s", instance_id)
|
|
568
|
+
|
|
569
|
+
# Governed server-side terminate: kills + verifies with the org's stored
|
|
570
|
+
# key. Used whenever we aren't handed an explicit BYO key.
|
|
571
|
+
if api_key is None and api_client is not None:
|
|
572
|
+
ok = api_client.terminate_instance(instance_id)
|
|
573
|
+
if ok:
|
|
574
|
+
# The API only reports success once the pod is confirmed gone.
|
|
575
|
+
inst = api_client.get_instance(instance_id) or {}
|
|
576
|
+
confirmed = inst.get("status") == "terminated"
|
|
577
|
+
if not confirmed:
|
|
578
|
+
# Non-terminal ("terminating") — the reconciler keeps retrying;
|
|
579
|
+
# surface that the pod is not yet confirmed dead.
|
|
580
|
+
logger.warning(
|
|
581
|
+
"terminate %s: server accepted but pod not yet confirmed "
|
|
582
|
+
"gone (status=%s) — the reconciler will keep retrying",
|
|
583
|
+
instance_id, inst.get("status"),
|
|
584
|
+
)
|
|
585
|
+
else:
|
|
586
|
+
_stop_guard()
|
|
587
|
+
return confirmed
|
|
588
|
+
logger.error(
|
|
589
|
+
"terminate %s: governed server-side termination failed — the pod "
|
|
590
|
+
"may still be BILLING; check `openrunner gpu ls` / provider console",
|
|
591
|
+
instance_id,
|
|
592
|
+
)
|
|
593
|
+
return False
|
|
594
|
+
|
|
595
|
+
# BYO-key path: resolve provider + provider_instance_id, then kill directly.
|
|
556
596
|
provider_instance_id = instance_id
|
|
557
597
|
if provider is None and api_client is not None:
|
|
558
598
|
instances = api_client.list_instances()
|
|
@@ -569,7 +609,6 @@ async def terminate(
|
|
|
569
609
|
logger.error("terminate: cannot determine provider for instance %s", instance_id)
|
|
570
610
|
return False
|
|
571
611
|
|
|
572
|
-
# Get provider instance and terminate
|
|
573
612
|
try:
|
|
574
613
|
prov = _get_provider_instance(provider, api_key=api_key, api_client=api_client)
|
|
575
614
|
result = await prov.terminate_instance(provider_instance_id)
|
|
@@ -577,18 +616,16 @@ async def terminate(
|
|
|
577
616
|
logger.warning("terminate: provider termination failed: %s", exc)
|
|
578
617
|
result = False
|
|
579
618
|
|
|
580
|
-
#
|
|
581
|
-
|
|
619
|
+
# Only mark terminated when the provider kill actually succeeded — a
|
|
620
|
+
# falsely-"terminated" record strands a billing pod.
|
|
621
|
+
if result and api_client is not None:
|
|
582
622
|
try:
|
|
583
623
|
api_client.update_instance_status(instance_id, "terminated")
|
|
584
624
|
except Exception as exc:
|
|
585
625
|
logger.warning("terminate: backend update failed: %s", exc)
|
|
586
626
|
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
if guard_entry:
|
|
590
|
-
guard_entry["stop"].set()
|
|
591
|
-
logger.info("Cost guard stopped for instance %s", instance_id)
|
|
627
|
+
if result:
|
|
628
|
+
_stop_guard()
|
|
592
629
|
|
|
593
630
|
return result
|
|
594
631
|
|
|
@@ -3254,6 +3254,93 @@ directly SSH-reachable** (`publicIp:22`): SSH is only via the **proxy**
|
|
|
3254
3254
|
"""
|
|
3255
3255
|
|
|
3256
3256
|
|
|
3257
|
+
REPORT_BUG_CMD = """---
|
|
3258
|
+
name: {prefix}report-bug
|
|
3259
|
+
description: Open a GitHub issue on the OpenRunner open-source repo for a bug you hit
|
|
3260
|
+
allowed-tools:
|
|
3261
|
+
- Bash
|
|
3262
|
+
- Read
|
|
3263
|
+
- Grep
|
|
3264
|
+
- AskUserQuestion
|
|
3265
|
+
---
|
|
3266
|
+
<objective>
|
|
3267
|
+
File a high-quality bug report as a GitHub issue on the OpenRunner open-source
|
|
3268
|
+
repository when the user hits a bug (or asks to report one). Gather REAL context
|
|
3269
|
+
from this session, avoid duplicates, confirm before creating (an issue is public),
|
|
3270
|
+
and return the issue URL.
|
|
3271
|
+
</objective>
|
|
3272
|
+
|
|
3273
|
+
<preconditions>
|
|
3274
|
+
- The `gh` CLI must be installed and authenticated. Check with `gh auth status`.
|
|
3275
|
+
If it is not authenticated, tell the user to run it themselves -- suggest they
|
|
3276
|
+
type `! gh auth login` in the prompt -- then stop.
|
|
3277
|
+
- Target repo = the OpenRunner open-source repository. Detect it (below); if it
|
|
3278
|
+
cannot be resolved, fall back to `jqueguiner/openrunner`.
|
|
3279
|
+
</preconditions>
|
|
3280
|
+
|
|
3281
|
+
<process>
|
|
3282
|
+
1. Verify gh is ready: `gh auth status`. If not, stop and ask the user to
|
|
3283
|
+
`! gh auth login`.
|
|
3284
|
+
2. Resolve the target repo. Prefer an explicit OpenRunner repo. If the current
|
|
3285
|
+
directory is the OpenRunner checkout, use its origin:
|
|
3286
|
+
`gh repo view --json nameWithOwner -q .nameWithOwner`. Otherwise default to
|
|
3287
|
+
`jqueguiner/openrunner`. Store it as REPO.
|
|
3288
|
+
3. Collect context (do NOT ask the user for what you can already observe):
|
|
3289
|
+
- SDK version: `openrunner version`.
|
|
3290
|
+
- OS + Python: `python3 -V` and `uname -sr`.
|
|
3291
|
+
- The failing command and its EXACT error output (quote verbatim), the repro
|
|
3292
|
+
steps, and expected vs actual behaviour -- reconstruct these from the current
|
|
3293
|
+
session. Use AskUserQuestion ONLY for the pieces you genuinely cannot infer.
|
|
3294
|
+
4. De-dupe: search existing issues before opening a new one:
|
|
3295
|
+
`gh issue list --repo REPO --state all --search "<key error phrase>"`.
|
|
3296
|
+
If a clear match exists, show it and ask whether to comment on it
|
|
3297
|
+
(`gh issue comment <n> --repo REPO --body ...`) instead of opening a new one.
|
|
3298
|
+
5. Draft the issue using the body template below. SHOW the full title + body to
|
|
3299
|
+
the user and get EXPLICIT confirmation before creating -- an issue is public
|
|
3300
|
+
and outward-facing. Do not create it on your own initiative.
|
|
3301
|
+
6. Create it:
|
|
3302
|
+
`gh issue create --repo REPO --title "<title>" --body "<body>" --label bug`.
|
|
3303
|
+
If the `bug` label does not exist the call fails -- retry without `--label`.
|
|
3304
|
+
7. Print the returned issue URL to the user.
|
|
3305
|
+
</process>
|
|
3306
|
+
|
|
3307
|
+
<body-template>
|
|
3308
|
+
Compose the issue body as markdown with these sections (fill from real data;
|
|
3309
|
+
write "unknown" where you truly cannot determine a value -- never invent):
|
|
3310
|
+
|
|
3311
|
+
### Summary
|
|
3312
|
+
One or two sentences: what broke.
|
|
3313
|
+
|
|
3314
|
+
### Environment
|
|
3315
|
+
- openrunner-sdk: <version>
|
|
3316
|
+
- OS / Python: <uname> / <python -V>
|
|
3317
|
+
- Instance base_url: <from ~/.openrunner/settings.json, host only -- no api_key>
|
|
3318
|
+
|
|
3319
|
+
### Steps to reproduce
|
|
3320
|
+
1. ...
|
|
3321
|
+
|
|
3322
|
+
### Expected
|
|
3323
|
+
...
|
|
3324
|
+
|
|
3325
|
+
### Actual
|
|
3326
|
+
... (paste the exact error, in a fenced code block)
|
|
3327
|
+
|
|
3328
|
+
### Notes
|
|
3329
|
+
Anything else relevant (workaround found, related area of the codebase).
|
|
3330
|
+
</body-template>
|
|
3331
|
+
|
|
3332
|
+
<safety>
|
|
3333
|
+
- NEVER create the issue (or a comment) without explicit user confirmation. It is
|
|
3334
|
+
public and cannot be un-published cleanly.
|
|
3335
|
+
- REDACT secrets before including anything: strip api keys, tokens, passwords,
|
|
3336
|
+
bearer headers, `Authorization:` values, and the api_key from settings.json.
|
|
3337
|
+
Include only the base_url host, never credentials.
|
|
3338
|
+
- Quote error text verbatim (do not paraphrase the failure) -- but with secrets
|
|
3339
|
+
stripped.
|
|
3340
|
+
</safety>
|
|
3341
|
+
"""
|
|
3342
|
+
|
|
3343
|
+
|
|
3257
3344
|
FORGE_CMD = """---
|
|
3258
3345
|
name: {prefix}forge
|
|
3259
3346
|
description: Run or write a Python function on the Forge (Shadow-PaaS) serverless GPU fleet. Use for "run/launch/train on forge", "forge GPU", or writing an @app.function. Forge is a serverless PROVIDER (like Modal) -- NOT an ssh host or runner, so don't hunt ~/.ssh/config or `hosts ls`.
|
|
@@ -3577,6 +3664,7 @@ def install_claude_code() -> list[str]:
|
|
|
3577
3664
|
"unregister-machine.md": UNREGISTER_MACHINE_CMD,
|
|
3578
3665
|
"train.md": TRAIN_CMD,
|
|
3579
3666
|
"deploy.md": DEPLOY_CMD,
|
|
3667
|
+
"report-bug.md": REPORT_BUG_CMD,
|
|
3580
3668
|
"forge.md": FORGE_CMD,
|
|
3581
3669
|
}
|
|
3582
3670
|
|
|
@@ -3812,6 +3900,7 @@ def _install_all_commands_to_dir(cmd_dir: Path, prefix: str = "openrunner:") ->
|
|
|
3812
3900
|
"unregister-machine.md": UNREGISTER_MACHINE_CMD,
|
|
3813
3901
|
"train.md": TRAIN_CMD,
|
|
3814
3902
|
"deploy.md": DEPLOY_CMD,
|
|
3903
|
+
"report-bug.md": REPORT_BUG_CMD,
|
|
3815
3904
|
"forge.md": FORGE_CMD,
|
|
3816
3905
|
}
|
|
3817
3906
|
|