openrunner-sdk 2.37.4__tar.gz → 2.37.6__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.4 → openrunner_sdk-2.37.6}/PKG-INFO +1 -1
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/__init__.py +1 -1
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/install_commands.py +257 -1
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/pyproject.toml +1 -1
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/.gitignore +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/=6.0 +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/=8.1 +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/README.md +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/CLAUDE.md +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/_safepath.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/_secret_rules.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/api_client.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/artifact.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/autoresearch.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/buffer.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/cache.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/cli.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/config.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/cost.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/dataset.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/datasets.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/environment.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/evaluation.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/feedback.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/git_info.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/api_integration.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/cost_guard.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/gpu_types.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/price_compare.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/provider_base.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/providers/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/providers/lambda_cloud.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/providers/modal_provider.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/providers/ovhcloud.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/providers/runpod.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/providers/vastai.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/runner.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/gpu/workspace_sync.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/guardrails.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/handover.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/hooks/patent-lab-post-commit +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/accelerate.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/anthropic_tracer.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/catboost.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/diffusers.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/fastai.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/forced_alignment.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/gladia.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/gymnasium.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/huggingface.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/hydra.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/ignite.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/jax.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/keras.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/langchain.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/lightgbm.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/lightning.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/llamaindex.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/openai_finetune.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/openai_tracer.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/optuna.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/pytorch.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/sb3.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/sklearn.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/skypilot.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/tensorflow.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/trl.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/tts.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/ultralytics.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/voice_agent.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/whisper.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/integration/xgboost.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/launch.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/machine.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/mcp_server.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/media.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/migrate.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/model.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/model_card.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/offline.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/patent_scan.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/pii.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/plot.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/projects.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/prompt.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/query_api.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/redact.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/reload.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/research.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/research_policy.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/run.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/scorers.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/sender.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/session.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/settings.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/summary.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/sweep.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/sync.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/system_metrics.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/tensorboard.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/tools/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/tools/patent_report.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/trace.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/transcript_formatter.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/wal.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/wandb_compat/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/wandb_compat/_shim.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/openrunner/wer.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/scripts/gen_betterleaks_rules.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/conftest.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-aaa/config.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-aaa/metadata.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-aaa/metrics.jsonl +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-aaa/summary.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/manifest.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/model-checkpoint/weights.bin +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/manifest.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/artifacts/sample-image/preview.png +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/config.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/metadata.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/metrics.jsonl +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/fixtures/wandb-export-mini/run-bbb/summary.json +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/integration/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/integration/conftest.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/integration/test_artifact_round_trip.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_alert.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_aliases.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_api_client.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_artifact.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_buffer.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_cache.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_class_scorers.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_cli.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_config.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_evaluation.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_finish.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_git_info.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/__init__.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/conftest.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_cost_guard.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_gpu_types.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_lambda.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_modal.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_ovhcloud.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_price_compare.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_provider_base.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_runner.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_runpod.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_sdk_gpu_api.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_vastai.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_gpu/test_workspace_sync.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_init.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_install_commands.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_fastai.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_huggingface.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_keras.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_langchain.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_lightning.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_pytorch.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_sklearn.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_integration_xgboost.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_launch.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_log.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_log_code.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_mcp_decisions.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_mcp_monitor.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_mcp_predictions.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_media.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_migrate.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_offline.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_offline_sync.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_pii.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_plot.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_query_api.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_resume.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_sdk_features.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_sender.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_session_sync.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_summary.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_sweep.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_system_metrics.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/tests/test_trace.py +0 -0
- {openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/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.6
|
|
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.6"
|
|
185
185
|
|
|
186
186
|
logger = logging.getLogger("openrunner")
|
|
187
187
|
|
|
@@ -442,7 +442,7 @@ allowed-tools:
|
|
|
442
442
|
Upgrade openrunner-sdk and reinstall slash commands:
|
|
443
443
|
|
|
444
444
|
```bash
|
|
445
|
-
pip install --upgrade openrunner-sdk 2>&1 | tail -3 && python3 -c "
|
|
445
|
+
pip install --upgrade --no-cache-dir openrunner-sdk 2>&1 | tail -3 && python3 -c "
|
|
446
446
|
import sys, os
|
|
447
447
|
from pathlib import Path
|
|
448
448
|
for p in ([os.path.join(d, 'site-packages') for d in __import__('glob').glob(os.path.expanduser('~/.local/lib/python3.*/')) + __import__('glob').glob(os.path.expanduser('~/Library/Python/3.*/lib/python/'))]):
|
|
@@ -2596,6 +2596,256 @@ pulls** -- `openrunner gpu run --image ...` resolves the org's stored registry.)
|
|
|
2596
2596
|
"""
|
|
2597
2597
|
|
|
2598
2598
|
|
|
2599
|
+
DRIFT_CMD = """---
|
|
2600
|
+
name: {prefix}drift
|
|
2601
|
+
description: Instrument an inference API/service to report per-prediction events to OpenRunner inference-drift monitoring (distribution shift / PSI), segment by metadata, then watch + alert -- no raw payloads stored, only the metrics you choose
|
|
2602
|
+
argument-hint: "[project org/name]"
|
|
2603
|
+
allowed-tools:
|
|
2604
|
+
- Bash
|
|
2605
|
+
- Read
|
|
2606
|
+
- Edit
|
|
2607
|
+
- AskUserQuestion
|
|
2608
|
+
---
|
|
2609
|
+
|
|
2610
|
+
Add **inference-drift monitoring** to an API/service: after each prediction,
|
|
2611
|
+
report a lightweight event (input features + output metrics) to OpenRunner, which
|
|
2612
|
+
tracks distribution shift (PSI), per-segment health and A/B. Only the numbers +
|
|
2613
|
+
tags you send are stored -- never the raw inputs/outputs.
|
|
2614
|
+
|
|
2615
|
+
## The event shape (one per inference)
|
|
2616
|
+
|
|
2617
|
+
- `inference_id` -- your request/prediction id (str).
|
|
2618
|
+
- `metadata` -- dict of scalars OR lists (the axes you'll slice by), e.g.
|
|
2619
|
+
`{{"model": "v3", "lang": ["fr", "en"], "route": "asr", "region": "eu"}}`.
|
|
2620
|
+
- `metrics` -- dict of floats to watch, e.g.
|
|
2621
|
+
`{{"confidence": 0.92, "latency_ms": 180, "tokens": 57, "input_len": 12.4}}`.
|
|
2622
|
+
- `monitor` (optional) -- the drift stream name; use one per model/endpoint.
|
|
2623
|
+
- `event_time` (optional) -- ISO timestamp; defaults to now.
|
|
2624
|
+
|
|
2625
|
+
Choose metrics that reveal drift: output confidence/score, input length / feature
|
|
2626
|
+
stats, latency, class distribution. Metadata = segments to localise a drift.
|
|
2627
|
+
|
|
2628
|
+
## Step 1 -- resolve the project id
|
|
2629
|
+
|
|
2630
|
+
```bash
|
|
2631
|
+
openrunner login
|
|
2632
|
+
python3 -c "
|
|
2633
|
+
from openrunner.api_client import APIClient
|
|
2634
|
+
import json, os
|
|
2635
|
+
c = APIClient(base_url=os.environ.get('OPENRUNNER_BASE_URL','https://openrun.gladia.io'),
|
|
2636
|
+
api_key=os.environ['OPENRUNNER_API_KEY'])
|
|
2637
|
+
print([(p['name'], p['id']) for p in c.list_projects()])
|
|
2638
|
+
"
|
|
2639
|
+
```
|
|
2640
|
+
|
|
2641
|
+
## Step 2 -- instrument (NON-BLOCKING) -- FastAPI example
|
|
2642
|
+
|
|
2643
|
+
Report AFTER responding, batched on a background thread, so you never add latency
|
|
2644
|
+
to the request. The ingest endpoint answers **429 + Retry-After** under load (the
|
|
2645
|
+
client backs off) -- so drop events rather than block the request path.
|
|
2646
|
+
|
|
2647
|
+
```python
|
|
2648
|
+
import os, threading, queue, atexit
|
|
2649
|
+
from openrunner.api_client import APIClient
|
|
2650
|
+
|
|
2651
|
+
PROJECT_ID = "..." # from step 1
|
|
2652
|
+
_client = APIClient(base_url=os.environ.get("OPENRUNNER_BASE_URL", "https://openrun.gladia.io"),
|
|
2653
|
+
api_key=os.environ["OPENRUNNER_API_KEY"])
|
|
2654
|
+
_q: queue.Queue = queue.Queue(maxsize=10000)
|
|
2655
|
+
|
|
2656
|
+
def _flush_loop():
|
|
2657
|
+
buf = []
|
|
2658
|
+
while True:
|
|
2659
|
+
ev = _q.get()
|
|
2660
|
+
if ev is not None:
|
|
2661
|
+
buf.append(ev)
|
|
2662
|
+
if buf and (ev is None or len(buf) >= 200):
|
|
2663
|
+
_client.post_inference_events(PROJECT_ID, buf, monitor="asr-prod")
|
|
2664
|
+
buf = []
|
|
2665
|
+
if ev is None:
|
|
2666
|
+
return
|
|
2667
|
+
|
|
2668
|
+
threading.Thread(target=_flush_loop, daemon=True).start()
|
|
2669
|
+
atexit.register(lambda: _q.put(None))
|
|
2670
|
+
|
|
2671
|
+
def record_inference(req_id, metadata, metrics):
|
|
2672
|
+
try:
|
|
2673
|
+
_q.put_nowait({{"inference_id": req_id, "metadata": metadata, "metrics": metrics}})
|
|
2674
|
+
except queue.Full:
|
|
2675
|
+
pass # never block or fail the request because of monitoring
|
|
2676
|
+
|
|
2677
|
+
# ... in your endpoint, AFTER producing the result:
|
|
2678
|
+
record_inference(
|
|
2679
|
+
req_id,
|
|
2680
|
+
{{"model": "v3", "lang": lang, "route": "asr"}},
|
|
2681
|
+
{{"confidence": conf, "latency_ms": dt_ms, "audio_s": duration}},
|
|
2682
|
+
)
|
|
2683
|
+
```
|
|
2684
|
+
|
|
2685
|
+
**Non-Python service?** POST the events directly:
|
|
2686
|
+
|
|
2687
|
+
```
|
|
2688
|
+
POST /api/v1/projects/PROJECT_ID/inference-drift/ingest
|
|
2689
|
+
Authorization: Bearer <API_KEY>
|
|
2690
|
+
{{ "monitor": "asr-prod",
|
|
2691
|
+
"events": [ {{"inference_id": "r1", "metadata": {{"lang": "fr"}}, "metrics": {{"confidence": 0.9}}}} ] }}
|
|
2692
|
+
-> {{"ingested": n}} (429 + Retry-After under load -> back off)
|
|
2693
|
+
```
|
|
2694
|
+
|
|
2695
|
+
**Batch offline** from a JSON file instead of instrumenting:
|
|
2696
|
+
|
|
2697
|
+
```bash
|
|
2698
|
+
openrunner drift report events.json --project ORG/NAME --monitor asr-prod
|
|
2699
|
+
```
|
|
2700
|
+
|
|
2701
|
+
## Step 3 -- watch + alert
|
|
2702
|
+
|
|
2703
|
+
- UI: the **Drift** menu -> overview / timeseries / per-segment PSI / A/B.
|
|
2704
|
+
- CLI:
|
|
2705
|
+
- `openrunner drift monitors --project ORG/NAME`
|
|
2706
|
+
- `openrunner drift check --project ORG/NAME --metric confidence` (drift verdict)
|
|
2707
|
+
- `openrunner drift ab --project ORG/NAME --metric confidence --variant-a v2 --variant-b v3`
|
|
2708
|
+
- `openrunner drift ask --project ORG/NAME "did latency drift this week?"`
|
|
2709
|
+
- MCP (if the OpenRunner server is registered): the drift tools answer the same in-session.
|
|
2710
|
+
|
|
2711
|
+
## Notes
|
|
2712
|
+
|
|
2713
|
+
- **Nothing raw is stored** -- only the metrics + metadata you send.
|
|
2714
|
+
- One `monitor` per model/endpoint; segment with metadata (lang / region / route /
|
|
2715
|
+
model version) so a drift can be traced to a slice.
|
|
2716
|
+
- **Sample** at high QPS (report 1 in N) -- PSI needs volume, not every event.
|
|
2717
|
+
- Old days age out to S3 parquet automatically (a hot window stays in Postgres).
|
|
2718
|
+
"""
|
|
2719
|
+
|
|
2720
|
+
|
|
2721
|
+
DRIFT_INSTALL_CMD = """---
|
|
2722
|
+
name: {prefix}drift-install
|
|
2723
|
+
description: Actually wire inference-drift monitoring INTO the API in THIS repo -- detect the framework + endpoints, add a non-blocking reporter, insert record_inference() after each prediction, add the dependency, and verify with a live event (vs /openrunner:drift which only explains it)
|
|
2724
|
+
argument-hint: "[project org/name] [--endpoint PATH] [--sample N]"
|
|
2725
|
+
allowed-tools:
|
|
2726
|
+
- Bash
|
|
2727
|
+
- Read
|
|
2728
|
+
- Edit
|
|
2729
|
+
- Write
|
|
2730
|
+
- Grep
|
|
2731
|
+
- Glob
|
|
2732
|
+
- AskUserQuestion
|
|
2733
|
+
---
|
|
2734
|
+
|
|
2735
|
+
Instrument the inference API in the **current repo** with OpenRunner drift
|
|
2736
|
+
monitoring -- edit the code, don't just describe it (see `/openrunner:drift` for
|
|
2737
|
+
the reference). Do each step; ask only when genuinely ambiguous.
|
|
2738
|
+
|
|
2739
|
+
## Step 1 -- detect the API + inference endpoint(s)
|
|
2740
|
+
- Identify the framework (grep `fastapi`, `flask`, `django`, `express`,
|
|
2741
|
+
`@app.post`, `APIRouter`, route decorators) and the file(s) with the
|
|
2742
|
+
**inference** endpoint(s) -- the handlers that return model predictions.
|
|
2743
|
+
- If several, ask which to instrument (default: the prediction routes). Honour
|
|
2744
|
+
`--endpoint PATH` when given.
|
|
2745
|
+
|
|
2746
|
+
## Step 2 -- resolve project + creds
|
|
2747
|
+
- `openrunner login` if needed. Resolve the project id (from the `org/name` arg,
|
|
2748
|
+
else `APIClient.list_projects()`; ask if ambiguous).
|
|
2749
|
+
- Creds are read from the service env at runtime: `OPENRUNNER_API_KEY`
|
|
2750
|
+
(+ `OPENRUNNER_BASE_URL`). Confirm they are set in the deployment env; **never
|
|
2751
|
+
hardcode the key**. Store `PROJECT_ID` as a module constant or env var.
|
|
2752
|
+
|
|
2753
|
+
## Step 3 -- add the non-blocking reporter module
|
|
2754
|
+
Create `openrunner_drift.py` (match the repo layout) with a background batcher
|
|
2755
|
+
(thread + `queue`, drop on full, 200/flush, 429 backoff via the SDK) exposing
|
|
2756
|
+
`record_inference(inference_id, metadata, metrics)` -- the pattern from
|
|
2757
|
+
`/openrunner:drift`. For an async framework, use an asyncio task + `asyncio.Queue`
|
|
2758
|
+
instead of a thread.
|
|
2759
|
+
|
|
2760
|
+
## Step 4 -- instrument each endpoint
|
|
2761
|
+
AFTER the response is produced, insert a wrapped `record_inference(...)`:
|
|
2762
|
+
- `inference_id` = the request id / a `uuid4().hex`.
|
|
2763
|
+
- `metadata` = input axes present in the handler: model version, language, route,
|
|
2764
|
+
region, tenant/customer.
|
|
2765
|
+
- `metrics` = outputs + **latency measured around the model call** (wrap the
|
|
2766
|
+
predict call with a monotonic timer), output confidence/score, input length,
|
|
2767
|
+
token count.
|
|
2768
|
+
- Wrap in try/except (or the queue put_nowait) so monitoring **never** breaks or
|
|
2769
|
+
slows the request. Apply `--sample N` (report 1 in N) if given.
|
|
2770
|
+
|
|
2771
|
+
## Step 5 -- dependency + verify
|
|
2772
|
+
- Add `openrunner-sdk` to `requirements.txt` / `pyproject.toml` if missing.
|
|
2773
|
+
- Import-check the new module; send ONE synthetic event
|
|
2774
|
+
(`post_inference_events(PROJECT_ID, [{{...}}])`) and confirm `ingested: 1`.
|
|
2775
|
+
- Point the user at the **Drift** UI and `openrunner drift check --project ORG/NAME
|
|
2776
|
+
--metric confidence`.
|
|
2777
|
+
|
|
2778
|
+
## Guardrails
|
|
2779
|
+
- NEVER block or fail the request path for monitoring (drop on queue-full).
|
|
2780
|
+
- NEVER store raw inputs/outputs -- only the chosen metrics + metadata.
|
|
2781
|
+
- NEVER hardcode the API key -- read from env.
|
|
2782
|
+
- Keep the diff minimal + match the repo's style/imports.
|
|
2783
|
+
"""
|
|
2784
|
+
|
|
2785
|
+
|
|
2786
|
+
BUILD_API_CMD = """---
|
|
2787
|
+
name: {prefix}build-api
|
|
2788
|
+
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
|
|
2789
|
+
argument-hint: "[--model PATH_OR_ARTIFACT] [--framework fastapi] [--drift] [--registry NAME/ns]"
|
|
2790
|
+
allowed-tools:
|
|
2791
|
+
- Bash
|
|
2792
|
+
- Read
|
|
2793
|
+
- Edit
|
|
2794
|
+
- Write
|
|
2795
|
+
- Grep
|
|
2796
|
+
- Glob
|
|
2797
|
+
- AskUserQuestion
|
|
2798
|
+
---
|
|
2799
|
+
|
|
2800
|
+
Scaffold a serving API for a model in the **current repo** -- a real, runnable
|
|
2801
|
+
skeleton, not a description. Ask only what you can't infer.
|
|
2802
|
+
|
|
2803
|
+
## Step 1 -- understand the model
|
|
2804
|
+
- Find the model: a local checkpoint, an `openrunner.use_model(...)` artifact, a
|
|
2805
|
+
HF id, or a `predict()` the user points at (`--model`). Ask if unclear.
|
|
2806
|
+
- Determine input -> output shape (text/audio/image in; label/score/text out) to
|
|
2807
|
+
type the request/response.
|
|
2808
|
+
|
|
2809
|
+
## Step 2 -- scaffold the API (default FastAPI)
|
|
2810
|
+
Write a minimal, production-shaped service:
|
|
2811
|
+
- `app/main.py` -- FastAPI app; load the model ONCE at startup (lifespan), a typed
|
|
2812
|
+
`POST /predict` (pydantic request/response), `GET /health` (model-loaded probe),
|
|
2813
|
+
`GET /` version. Batch-friendly handler; no blocking work in the event loop for
|
|
2814
|
+
heavy models (run in a threadpool / worker).
|
|
2815
|
+
- `app/model.py` -- load + `predict()` wrapper (pull weights via
|
|
2816
|
+
`openrunner.use_model` when the model is an OpenRunner artifact).
|
|
2817
|
+
- `requirements.txt` / `pyproject.toml`, `.env.example` (PORT, model ref,
|
|
2818
|
+
`OPENRUNNER_*`), `README.md` (run + curl example).
|
|
2819
|
+
- `Dockerfile` -- slim base, install deps, copy app, `CMD` uvicorn on `$PORT`;
|
|
2820
|
+
GPU base image if the model needs CUDA.
|
|
2821
|
+
|
|
2822
|
+
## Step 3 -- (optional) bake in drift monitoring
|
|
2823
|
+
If `--drift` (or the user wants it): run the `/openrunner:drift-install` flow on
|
|
2824
|
+
the freshly scaffolded `/predict` -- add the non-blocking reporter + a
|
|
2825
|
+
`record_inference(...)` after the prediction (latency, confidence, input length).
|
|
2826
|
+
|
|
2827
|
+
## Step 4 -- (optional) container + deploy path
|
|
2828
|
+
- If `--registry NAME/ns`: show the governed push --
|
|
2829
|
+
`docker build -t registry.openrun.gladia.io/<ns>/<name>:v1 . && openrunner
|
|
2830
|
+
registry login && docker push ...` (the OpenRunner broker proxies to the org's
|
|
2831
|
+
upstream; see `/openrunner:registry`).
|
|
2832
|
+
- Note the deploy path: `openrunner gpu run --image <that image> ...` today, and
|
|
2833
|
+
the governed **Deployments** UI (image + GPU + min/max nodes) when available.
|
|
2834
|
+
|
|
2835
|
+
## Step 5 -- verify it runs
|
|
2836
|
+
- `uvicorn app.main:app` locally (or `python -m app`), `curl /health` -> ok,
|
|
2837
|
+
`curl -X POST /predict` with a sample payload -> a real response.
|
|
2838
|
+
- Report the run command, the curl example, and the build/push/deploy one-liners.
|
|
2839
|
+
|
|
2840
|
+
## Guardrails
|
|
2841
|
+
- Load the model once (startup), not per request; run heavy inference off the
|
|
2842
|
+
event loop.
|
|
2843
|
+
- Type the API (pydantic) and add `/health` so it's deploy/LB-ready.
|
|
2844
|
+
- Read config (model ref, keys, port) from env -- never hardcode secrets.
|
|
2845
|
+
- Keep it minimal + runnable; match the repo's language/stack if one exists.
|
|
2846
|
+
"""
|
|
2847
|
+
|
|
2848
|
+
|
|
2599
2849
|
def install_claude_code() -> list[str]:
|
|
2600
2850
|
"""Install commands in ~/.claude/commands/openrunner/."""
|
|
2601
2851
|
cmd_dir = Path.home() / ".claude" / "commands" / "openrunner"
|
|
@@ -2630,6 +2880,9 @@ def install_claude_code() -> list[str]:
|
|
|
2630
2880
|
"derive-dataset.md": DERIVE_DATASET_CMD,
|
|
2631
2881
|
"launch-gpu.md": LAUNCH_GPU_CMD,
|
|
2632
2882
|
"registry.md": REGISTRY_CMD,
|
|
2883
|
+
"drift.md": DRIFT_CMD,
|
|
2884
|
+
"drift-install.md": DRIFT_INSTALL_CMD,
|
|
2885
|
+
"build-api.md": BUILD_API_CMD,
|
|
2633
2886
|
}
|
|
2634
2887
|
|
|
2635
2888
|
files = []
|
|
@@ -2832,6 +3085,9 @@ def _install_all_commands_to_dir(cmd_dir: Path, prefix: str = "openrunner:") ->
|
|
|
2832
3085
|
"derive-dataset.md": DERIVE_DATASET_CMD,
|
|
2833
3086
|
"launch-gpu.md": LAUNCH_GPU_CMD,
|
|
2834
3087
|
"registry.md": REGISTRY_CMD,
|
|
3088
|
+
"drift.md": DRIFT_CMD,
|
|
3089
|
+
"drift-install.md": DRIFT_INSTALL_CMD,
|
|
3090
|
+
"build-api.md": BUILD_API_CMD,
|
|
2835
3091
|
}
|
|
2836
3092
|
|
|
2837
3093
|
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
|
|
File without changes
|
|
File without changes
|
{openrunner_sdk-2.37.4 → openrunner_sdk-2.37.6}/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.4 → openrunner_sdk-2.37.6}/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.4 → openrunner_sdk-2.37.6}/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
|