cmpnd 0.85.1__tar.gz → 0.85.2__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.
- {cmpnd-0.85.1 → cmpnd-0.85.2}/PKG-INFO +1 -1
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_http.py +12 -6
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/sdk-instrumentation.md +2 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/exporter_http.py +5 -3
- cmpnd-0.85.2/ingest/cmpnd_ingest/user_agent.py +52 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/pyproject.toml +1 -1
- cmpnd-0.85.2/tests/test_user_agent.py +109 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/uv.lock +1 -1
- {cmpnd-0.85.1 → cmpnd-0.85.2}/.gitignore +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/AGENTS.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/CLAUDE.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/README.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_assessments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_authored_import.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_deployments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_exporter_pool.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_gepa_patch.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_program_patch.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_rlm_patch.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_runtime_tools.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_timespec.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_traces.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/_valsets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/authored.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/callback.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/api_client.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/admin.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/assessments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/auth.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/datasets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/deployments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/evals.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/login.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/optimizations.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/org.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/provider_credentials.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/tool_servers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/top.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/traces.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/commands/valsets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/credentials.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/deprecation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/pagination.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/shell.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/trace_render.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/tree_help.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/verbs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/cli/views.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/client.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/configuration.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/context.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/credentials.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/dataset_sync.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/datasets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/decorators.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/deployment.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/deployment_metadata.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/deployment_runs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/eval_handler.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/execution.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/exporter.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/exporter_http.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/helpers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/identity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/imaging.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/decode.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/encode.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/hash.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/program.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/reflection.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/types.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/ir/xxh64.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/lm_configuration.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/mcp_servers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/models.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/named_programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/optimization.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/optimizers/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/optimizers/gepa.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/optimizers/gepa_callback.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/optimizers/resume.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/optimizers/tracker.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/packaging.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/program_naming.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/references.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/retry.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/cmpnd/traces.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/2026-04-02-code-review.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/cli.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/client.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/custom-proposer.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/docs/reading-traces.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/examples/generalizing_proposer.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/examples/local_ollama.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/LINEAGE.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/README.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/bodies.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/client_floor.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/program_names.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/protocols.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/py.typed +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/request_log.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/retry.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/span_context.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/cmpnd_ingest/trace_facts.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/ingest/pyproject.toml +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/audit-sdist.sh +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/capture_review_run.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/check-pip-install.sh +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/check_release_artifacts.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/fixtures/review_run.json.gz +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/gepa_resume_bug.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/install-test-env.sh +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/release-gate.sh +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/release-real-models.sh +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/require_version_bump.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/seed_review_run.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/selfhost_compat.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/scripts/test-in-linux.sh +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/stubs/dspy/__init__.pyi +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/stubs/dspy/primitives/__init__.pyi +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/stubs/dspy/primitives/prediction.pyi +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/stubs/dspy/utils/__init__.pyi +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/stubs/dspy/utils/callback.pyi +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/stubs/dspy/utils/dummies.pyi +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_credential_route.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_deployment_signature_helpers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_exporter_helpers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_fake_clock.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_identity_helpers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_resolve_refs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/_traced_run.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/conftest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/committee_task.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/conftest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/continuation_task.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/data/committee_train.ndjson.gz +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/data/committee_val.ndjson.gz +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/fake_lm.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/helpers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/target_capabilities.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_assessments_cli.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_capture_prompts.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_composite_module.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_dataset_auto_creation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_deploy_execute.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_deploy_pandas.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_deploy_programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_edge_cases.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_example_hash.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_gepa_optimization.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_interpreter_spans.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_lm_accuracy.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_module_tracing.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimization_lineage.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimization_metric_identity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_authored_metric.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_continuation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_custom_proposer.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_failures.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_loop.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_review_committee.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_parallel_export.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_project_attribution.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_react_tool_spans.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_save_load.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_trace_structure.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_traces_read.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_user_attribution.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/e2e/test_valsets_cli.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/01_predict_qa.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/04_predict_richer_types.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/06_multichaincomparison.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/07_program_of_thought.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/08_opaque_module.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/10_react.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/11_refine.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/12_retrieve.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/13_knn.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/14_parallel.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/identity_vectors/README.md +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/ingest_conformance.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/authored_optimize/judge.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/conftest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/hosted_optimize_probe.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/optimization_run_probe.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/test_cli_deploy_smoketest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/test_logs_renders_traces.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/test_optimization_run.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/test_optimizing_progress.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/integration/test_unhappy_path.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/lm15_prompt_fixture.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/lm15_prompts/four_turn_predict.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/lm15_prompts/rlm_six_turns.json +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/__main__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/drain.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/ingest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/latency_transport.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/rlm_shape.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/rlm_size_report.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/sweep.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/test_rlm_shape.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/load/test_rlm_size_report.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/conftest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/seed_parity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_auth.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_datasets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_deployments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_evals.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_health.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_modules.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_optimizations.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_signatures.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_trace_streaming.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/parity/test_traces.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/_provider.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/_readiness.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/_reliability.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/_result.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/mint_bedrock_token.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_bedrock_converse.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_deploy_programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_multi_client_stress.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_optimize_client_committee.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_optimize_continuation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_optimize_loop.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_optimize_loop_wasm.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_optimize_stress.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_provider_roles.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_readiness.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_real_provider_twins.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_reliability.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_reliability_classify.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_rlm_wasm.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/real_models/test_trace_search.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/span_reference_fixture.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_adapter_reentrancy.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_assessments_api.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_authored.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_authored_binding_credentials.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_authored_bundle_collisions.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_authored_metric_contract.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_authored_named_models.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_authored_optimize.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_callback.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_candidate_lineage.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/conftest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_admin.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_api_client.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_assessments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_auth.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_credentials.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_datasets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_deployment_runs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_deployments.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_evals.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_login.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_main.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_optimizations.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_org.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_pagination.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_parity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_programs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_provider_credentials.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_schema_sample.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_shell.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_tool_servers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_top.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_traces.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_traces_program_and_module.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_traces_search_wire.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_tree_help.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cli/test_valsets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_client.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_client_floor.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_client_program_names.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_clustering/__init__.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_clustering/conftest.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_clustering/test_edge_cases.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_clustering/test_hash_consistency.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_clustering/test_type_conversion.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_cmp551_grouping_identity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_configuration.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_context.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_context_propagation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_credential_kwargs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_credential_selection.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_credential_values.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_dataset_polling.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_dataset_sync.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_datasets.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_decision_client_spans.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_decorators.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_deploy.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_deploy_mcp_tool_references.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_deploy_program_id.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_deployment_metadata.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_deployment_runs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_deployments_read.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_eval.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_eval_example_attribution.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_eval_program_id.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_eval_start.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_eval_trace_grouping.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_exception_paths.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_execute.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_execute_run_identity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_exporter.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_exporter_program_names.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_exporter_queue.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_exporter_real.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_fake_lm.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_gepa_callback.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_gepa_integration.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_gepa_output_normalization.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_gepa_resume.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_identity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_imaging.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_import_weight.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_ingest_conformance.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_ingest_second_producer.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_integration.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_interpreter_callback.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_ir_encoder_properties.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_ir_golden_vectors.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_ir_roundtrip.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_lm15_native_calls.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_lm15_prompt_fixtures.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_lm15_prompt_references.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_lm_configuration.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_lm_usage_shapes.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_mcp_tools.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_models.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_multi_client_stress_readiness.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_no_signature_hash_on_the_wire.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimization_phase_callback.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimization_program_names.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimization_progress.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimization_start.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize_budget.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize_lift.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize_lms.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize_proposer.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize_reflection_lm.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_optimize_terminal_failure.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_packaging.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_packaging_callable_source.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_packaging_mcp_tools.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_packaging_program_source.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_poll_until.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_program_id_deprecation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_program_identity.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_program_lineage_persist.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_program_names_in_deploy.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_program_naming.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_programs_create.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_project_payload.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_real_provider_twins_readiness.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_reflector_properties.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_reflector_smoke.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_release_gate_script.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_release_real_models_script.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_replaced_names.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_repro_reactv2_bugs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_require_version_bump.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_retry.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_reversible_failures.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_rlm_patch.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_run_attribution_paths.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_runtime_tools.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_schemas.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_seal_lm_credential.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_seed_review_run.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_signature_inputs.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_span_references.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_span_sent_once.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_span_submission.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_span_submission_wire_contract.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_system_one.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_trace_context_concurrency.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_trace_fact_wire_contract.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_trace_facts.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_trace_render.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_traces_read.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_tracked_gepa.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_tracker_enrich.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_truncation.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_upload_auth_headers.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_valsets_api.py +0 -0
- {cmpnd-0.85.1 → cmpnd-0.85.2}/tests/test_xxh64.py +0 -0
|
@@ -16,7 +16,7 @@ from typing import Any
|
|
|
16
16
|
from urllib.parse import urlsplit
|
|
17
17
|
|
|
18
18
|
import httpx
|
|
19
|
-
from cmpnd_ingest import client_floor
|
|
19
|
+
from cmpnd_ingest import client_floor, user_agent
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class ApiError(Exception):
|
|
@@ -79,16 +79,22 @@ def server_detail(response: httpx.Response) -> str:
|
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
def new_client(**kwargs: Any) -> httpx.Client:
|
|
82
|
-
"""An ``httpx.Client`` that
|
|
83
|
-
|
|
82
|
+
"""An ``httpx.Client`` that names this release to the server and warns when
|
|
83
|
+
the server no longer supports it (:mod:`cmpnd_ingest.client_floor`).
|
|
84
84
|
|
|
85
|
-
Every client the SDK builds comes from here, so every
|
|
86
|
-
|
|
85
|
+
Every client the SDK builds comes from here, so every request carries the
|
|
86
|
+
release's ``User-Agent`` (:mod:`cmpnd_ingest.user_agent`) and every answer
|
|
87
|
+
the platform sends gets the check. A caller's own ``headers`` override the
|
|
88
|
+
``User-Agent``, and its own ``event_hooks`` run after the check.
|
|
87
89
|
"""
|
|
88
90
|
hooks = client_floor.event_hooks()
|
|
89
91
|
for event, callers in (kwargs.pop("event_hooks", None) or {}).items():
|
|
90
92
|
hooks.setdefault(event, []).extend(callers)
|
|
91
|
-
|
|
93
|
+
# httpx.Headers matches names without regard to case, so a caller's `user-agent`
|
|
94
|
+
# replaces the default rather than travelling beside it.
|
|
95
|
+
headers = httpx.Headers(user_agent.headers())
|
|
96
|
+
headers.update(kwargs.pop("headers", None) or {})
|
|
97
|
+
return httpx.Client(event_hooks=hooks, headers=headers, **kwargs)
|
|
92
98
|
|
|
93
99
|
|
|
94
100
|
_DEFAULT_PORTS = {"http": 80, "https": 443}
|
|
@@ -373,6 +373,8 @@ Two callers implement the waiting:
|
|
|
373
373
|
|
|
374
374
|
Every API answer names the oldest cmpnd release the server supports, in the `X-Cmpnd-Minimum-Client-Version` header. `cmpnd_ingest/client_floor.py` reads it in an httpx response hook. When the installed `cmpnd` is older, it raises an `UpgradeRequiredWarning` once per process that names both versions and the command `pip install -U cmpnd`. The server refuses nothing for a client's version, so a call below the floor still goes through, and the warning appears beside whatever it does. Every client the SDK builds comes from `cmpnd._http.new_client`, which installs the hook, and the exporter installs it in `_client_kwargs`. `tests/test_client_floor.py` fails on an `httpx.Client` built any other way in `cmpnd/`. An install of `cmpnd_ingest` without `cmpnd` has no version to compare and says nothing. `CMPND_NO_UPGRADE_WARNING=1` silences the warning for a user who stays on an older release on purpose, and the warning names that switch. `cmpnd.UpgradeRequiredWarning` is public, so a `warnings` filter silences it in code.
|
|
375
375
|
|
|
376
|
+
Every request names its release in the other direction, so the server can count which releases are in use. `cmpnd_ingest/user_agent.py` builds the `User-Agent` value, such as `cmpnd/0.85.2 python/3.12.13 httpx/0.28.1 dspy/3.4.1`. The first product is `cmpnd` for the SDK and `cmpnd-ingest` for a producer that installs only the transport, such as the optimizer's search process. A library that is not installed is left out. `cmpnd._http.new_client` and the exporter's `_client_kwargs` both send it. A caller that passes its own `User-Agent` to `new_client` keeps it. `tests/test_user_agent.py` checks the value that reaches the wire.
|
|
377
|
+
|
|
376
378
|
### The optimize loop and transient tolerance
|
|
377
379
|
|
|
378
380
|
`optimization._poll_until_terminal` is what a caller blocks on for the length of a run, so one transient answer or one reset connection must not destroy a healthy run. It rides through transient answers on the shared budget, resetting after each successful poll, and never extends past the caller's `timeout` (default 600s per step) — a backoff wait is clipped by the deadline rather than overshooting it.
|
|
@@ -34,7 +34,7 @@ from typing import Any, cast
|
|
|
34
34
|
|
|
35
35
|
import httpx
|
|
36
36
|
|
|
37
|
-
from . import client_floor, program_names, request_log, retry
|
|
37
|
+
from . import client_floor, program_names, request_log, retry, user_agent
|
|
38
38
|
from .bodies import EncodedTraceBody, SpanBody, TraceBody
|
|
39
39
|
from .protocols import (
|
|
40
40
|
EvalRunRecord,
|
|
@@ -1106,11 +1106,13 @@ class BatchExporter:
|
|
|
1106
1106
|
|
|
1107
1107
|
def _client_kwargs(self) -> dict[str, Any]:
|
|
1108
1108
|
"""Shared httpx.Client construction args for the background and sync
|
|
1109
|
-
clients, so both carry the same base URL, auth header,
|
|
1110
|
-
|
|
1109
|
+
clients, so both carry the same base URL, auth header, release
|
|
1110
|
+
``User-Agent`` (``user_agent``), client-floor check (``client_floor``)
|
|
1111
|
+
and, in tests, injected transport."""
|
|
1111
1112
|
kwargs: dict[str, Any] = {
|
|
1112
1113
|
"base_url": self._config.endpoint,
|
|
1113
1114
|
"headers": {
|
|
1115
|
+
**user_agent.headers(),
|
|
1114
1116
|
"X-API-Key": self._config.api_key,
|
|
1115
1117
|
"Content-Type": "application/json",
|
|
1116
1118
|
},
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""The ``User-Agent`` every client the SDK builds sends, so the server can count releases.
|
|
2
|
+
|
|
3
|
+
The value names the installed distribution first, then the runtime it runs on:
|
|
4
|
+
|
|
5
|
+
cmpnd/0.85.2 python/3.12.13 httpx/0.28.1 dspy/3.4.1
|
|
6
|
+
|
|
7
|
+
The first product is ``cmpnd`` for the SDK and ``cmpnd-ingest`` for a producer that
|
|
8
|
+
installs only the transport, so the two never count as one. A distribution that is not
|
|
9
|
+
installed, such as ``dspy`` for a transport-only producer, is left out. A value that
|
|
10
|
+
cannot be read becomes ``unknown`` rather than failing a request.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import functools
|
|
16
|
+
import importlib.metadata
|
|
17
|
+
import platform
|
|
18
|
+
|
|
19
|
+
# The distributions that provide this package, in the order the first one found names
|
|
20
|
+
# the client. Only one is installed at a time (ingest/README.md).
|
|
21
|
+
_CLIENTS = ("cmpnd", "cmpnd-ingest")
|
|
22
|
+
# Runtime libraries whose version shapes what a client sends.
|
|
23
|
+
_LIBRARIES = ("httpx", "dspy")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _version(distribution: str) -> str | None:
|
|
27
|
+
"""The installed version, or None when it is not installed or cannot be read.
|
|
28
|
+
|
|
29
|
+
Any failure to read metadata counts as absent, because a broken install's
|
|
30
|
+
metadata must not stop a client from being built.
|
|
31
|
+
"""
|
|
32
|
+
try:
|
|
33
|
+
return importlib.metadata.version(distribution)
|
|
34
|
+
except Exception:
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@functools.cache
|
|
39
|
+
def user_agent() -> str:
|
|
40
|
+
"""The ``User-Agent`` header value for this process."""
|
|
41
|
+
client = next(
|
|
42
|
+
(f"{name}/{version}" for name in _CLIENTS if (version := _version(name)) is not None),
|
|
43
|
+
"cmpnd/unknown",
|
|
44
|
+
)
|
|
45
|
+
products = [client, f"python/{platform.python_version()}"]
|
|
46
|
+
products += [f"{name}/{version}" for name in _LIBRARIES if (version := _version(name)) is not None]
|
|
47
|
+
return " ".join(products)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def headers() -> dict[str, str]:
|
|
51
|
+
"""The headers that identify this client, to merge into a client's own."""
|
|
52
|
+
return {"User-Agent": user_agent()}
|
|
@@ -5,7 +5,7 @@ name = "cmpnd"
|
|
|
5
5
|
# it's new) — no git tags. Bump with `uv version --bump {minor,patch}` or by
|
|
6
6
|
# hand. Runtime `cmpnd.__version__` reads installed metadata, so it tracks
|
|
7
7
|
# this automatically. See docs/plans/2026-07-02-sdk-pypi-tag-free-publish.md.
|
|
8
|
-
version = "0.85.
|
|
8
|
+
version = "0.85.2"
|
|
9
9
|
description = "DSPy observability and deployment SDK for cmpnd"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.11"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Every client the SDK builds names its release in ``User-Agent``, so the server can
|
|
2
|
+
count which releases are in use.
|
|
3
|
+
|
|
4
|
+
Driven over real ``httpx.Client`` instances with ``MockTransport``: the property is
|
|
5
|
+
what reaches the wire.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import platform
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
|
|
13
|
+
import httpx
|
|
14
|
+
import pytest
|
|
15
|
+
from cmpnd_ingest import user_agent
|
|
16
|
+
|
|
17
|
+
import cmpnd
|
|
18
|
+
from cmpnd import _http
|
|
19
|
+
from cmpnd.configuration import Config
|
|
20
|
+
from cmpnd.exporter import BatchExporter
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.fixture(autouse=True)
|
|
24
|
+
def _fresh_user_agent() -> Iterator[None]:
|
|
25
|
+
user_agent.user_agent.cache_clear()
|
|
26
|
+
yield
|
|
27
|
+
user_agent.user_agent.cache_clear()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _sent_user_agent(client: httpx.Client, requests: list[httpx.Request]) -> str:
|
|
31
|
+
with client:
|
|
32
|
+
client.get("https://app.cmpnd.ai/api/v1/deployments")
|
|
33
|
+
assert len(requests) == 1
|
|
34
|
+
return requests[0].headers["User-Agent"]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _capturing(requests: list[httpx.Request]) -> httpx.MockTransport:
|
|
38
|
+
def handle(request: httpx.Request) -> httpx.Response:
|
|
39
|
+
requests.append(request)
|
|
40
|
+
return httpx.Response(200, json={})
|
|
41
|
+
|
|
42
|
+
return httpx.MockTransport(handle)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_the_user_agent_names_the_release_python_and_libraries() -> None:
|
|
46
|
+
products = user_agent.user_agent().split(" ")
|
|
47
|
+
assert products[0] == f"cmpnd/{cmpnd.__version__}"
|
|
48
|
+
assert products[1] == f"python/{platform.python_version()}"
|
|
49
|
+
assert f"httpx/{httpx.__version__}" in products
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_an_api_client_sends_the_release_user_agent() -> None:
|
|
53
|
+
requests: list[httpx.Request] = []
|
|
54
|
+
sent = _sent_user_agent(_http.new_client(transport=_capturing(requests)), requests)
|
|
55
|
+
assert sent == user_agent.user_agent()
|
|
56
|
+
assert sent.startswith(f"cmpnd/{cmpnd.__version__} ")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_a_callers_own_user_agent_wins() -> None:
|
|
60
|
+
requests: list[httpx.Request] = []
|
|
61
|
+
client = _http.new_client(transport=_capturing(requests), headers={"User-Agent": "mine/1"})
|
|
62
|
+
assert _sent_user_agent(client, requests) == "mine/1"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@pytest.mark.parametrize("name", ["user-agent", "USER-AGENT"])
|
|
66
|
+
def test_a_callers_user_agent_wins_in_any_case(name: str) -> None:
|
|
67
|
+
requests: list[httpx.Request] = []
|
|
68
|
+
client = _http.new_client(transport=_capturing(requests), headers={name: "mine/1"})
|
|
69
|
+
_sent_user_agent(client, requests)
|
|
70
|
+
assert requests[0].headers.get_list("User-Agent") == ["mine/1"]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_a_callers_httpx_headers_win() -> None:
|
|
74
|
+
requests: list[httpx.Request] = []
|
|
75
|
+
client = _http.new_client(transport=_capturing(requests), headers=httpx.Headers({"User-Agent": "mine/1"}))
|
|
76
|
+
_sent_user_agent(client, requests)
|
|
77
|
+
assert requests[0].headers.get_list("User-Agent") == ["mine/1"]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_the_exporter_sends_the_release_user_agent() -> None:
|
|
81
|
+
requests: list[httpx.Request] = []
|
|
82
|
+
exporter = BatchExporter(Config(api_key="k", endpoint="http://localhost:9999"), transport=_capturing(requests))
|
|
83
|
+
sent = _sent_user_agent(httpx.Client(**exporter._client_kwargs()), requests)
|
|
84
|
+
assert sent == user_agent.user_agent()
|
|
85
|
+
assert requests[0].headers["X-API-Key"] == "k"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_a_transport_only_producer_names_itself(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
89
|
+
versions = {"cmpnd-ingest": "0.1.0", "httpx": "0.28.1"}
|
|
90
|
+
monkeypatch.setattr(user_agent, "_version", versions.get)
|
|
91
|
+
assert user_agent.user_agent() == f"cmpnd-ingest/0.1.0 python/{platform.python_version()} httpx/0.28.1"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_an_unreadable_release_still_sends_a_user_agent(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
95
|
+
monkeypatch.setattr(user_agent, "_version", lambda _name: None)
|
|
96
|
+
assert user_agent.user_agent() == f"cmpnd/unknown python/{platform.python_version()}"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_unreadable_metadata_still_builds_both_clients(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
100
|
+
def broken(_name: str) -> str:
|
|
101
|
+
raise OSError("metadata unreadable")
|
|
102
|
+
|
|
103
|
+
monkeypatch.setattr(user_agent.importlib.metadata, "version", broken)
|
|
104
|
+
requests: list[httpx.Request] = []
|
|
105
|
+
expected = f"cmpnd/unknown python/{platform.python_version()}"
|
|
106
|
+
assert _sent_user_agent(_http.new_client(transport=_capturing(requests)), requests) == expected
|
|
107
|
+
requests.clear()
|
|
108
|
+
exporter = BatchExporter(Config(api_key="k", endpoint="http://localhost:9999"), transport=_capturing(requests))
|
|
109
|
+
assert _sent_user_agent(httpx.Client(**exporter._client_kwargs()), requests) == expected
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|