cmpnd 0.57.0__tar.gz → 0.58.0__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.57.0 → cmpnd-0.58.0}/AGENTS.md +34 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/PKG-INFO +2 -2
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_authored_import.py +1 -1
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_gepa_patch.py +6 -9
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/callback.py +1 -1
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/optimizers/tracker.py +3 -5
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/cli.md +0 -3
- {cmpnd-0.57.0 → cmpnd-0.58.0}/pyproject.toml +31 -4
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/check-pip-install.sh +1 -1
- cmpnd-0.58.0/scripts/install-test-env.sh +67 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/test-in-linux.sh +8 -7
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/span_reference_fixture.py +13 -7
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_adapter_reentrancy.py +2 -8
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_lm_usage_shapes.py +2 -4
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_program_lineage_persist.py +4 -5
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_rlm_patch.py +19 -6
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_span_references.py +3 -3
- {cmpnd-0.57.0 → cmpnd-0.58.0}/uv.lock +421 -194
- {cmpnd-0.57.0 → cmpnd-0.58.0}/.gitignore +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/CLAUDE.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/README.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_assessments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_deployments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_exporter_pool.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_http.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_program_patch.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_rlm_patch.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_runtime_tools.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_timespec.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_traces.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/_valsets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/authored.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/api_client.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/admin.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/assessments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/auth.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/datasets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/deployments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/evals.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/login.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/optimizations.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/org.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/signatures.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/tool_servers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/top.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/traces.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/commands/valsets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/credentials.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/deprecation.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/pagination.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/shell.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/trace_render.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/tree_help.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/cli/verbs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/client.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/configuration.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/context.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/credentials.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/dataset_sync.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/datasets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/decorators.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/deployment.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/deployment_metadata.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/deployment_runs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/eval_handler.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/execution.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/exporter.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/exporter_http.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/helpers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/identity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/imaging.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/decode.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/encode.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/hash.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/program.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/reflection.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/types.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/ir/xxh64.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/lm_configuration.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/mcp_servers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/models.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/named_programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/optimization.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/optimizers/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/optimizers/gepa.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/optimizers/gepa_callback.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/optimizers/resume.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/packaging.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/references.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/retry.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/cmpnd/traces.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/2026-04-02-code-review.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/client.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/custom-proposer.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/reading-traces.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/docs/sdk-instrumentation.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/examples/generalizing_proposer.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/examples/local_ollama.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/LINEAGE.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/README.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/bodies.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/program_names.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/protocols.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/py.typed +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/request_log.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/retry.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/ingest/pyproject.toml +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/audit-sdist.sh +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/capture_review_run.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/check_release_artifacts.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/fixtures/review_run.json.gz +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/gepa_resume_bug.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/release-stress.sh +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/require_version_bump.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/seed_review_run.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/scripts/selfhost_compat.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/stubs/dspy/__init__.pyi +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/stubs/dspy/primitives/__init__.pyi +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/stubs/dspy/primitives/prediction.pyi +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/stubs/dspy/utils/__init__.pyi +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/stubs/dspy/utils/callback.pyi +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/stubs/dspy/utils/dummies.pyi +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_credential_route.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_deployment_signature_helpers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_exporter_helpers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_fake_clock.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_identity_helpers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_resolve_refs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/_traced_run.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/conftest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/committee_task.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/conftest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/fake_lm.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/helpers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/target_capabilities.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_assessments_cli.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_capture_prompts.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_composite_module.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_deploy_execute.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_deploy_pandas.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_deploy_programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_edge_cases.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_example_hash.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_gepa_optimization.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_interpreter_spans.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_lm_accuracy.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_module_tracing.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_optimization_lineage.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_optimize_failures.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_optimize_loop.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_optimize_review_committee.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_parallel_export.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_project_attribution.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_react_tool_spans.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_save_load.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_trace_structure.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_traces_read.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_user_attribution.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/e2e/test_valsets_cli.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/01_predict_qa.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/08_opaque_module.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/10_react.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/11_refine.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/12_retrieve.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/13_knn.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/14_parallel.json +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/identity_vectors/README.md +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/ingest_conformance.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/authored_optimize/judge.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/conftest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/hosted_optimize_probe.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/optimization_run_probe.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/test_logs_renders_traces.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/test_optimization_run.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/test_optimizing_progress.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/integration/test_unhappy_path.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/__main__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/drain.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/ingest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/latency_transport.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/rlm_shape.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/rlm_size_report.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/sweep.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/test_rlm_shape.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/load/test_rlm_size_report.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/conftest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/seed_parity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_auth.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_datasets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_deployments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_evals.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_health.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_modules.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_optimizations.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_signatures.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_trace_streaming.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/parity/test_traces.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/_provider.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/_readiness.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/_reliability.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/_result.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/mint_bedrock_token.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_deploy_programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_multi_client_stress.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_optimize_client_committee.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_optimize_loop.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_optimize_loop_wasm.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_optimize_stress.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_provider_roles.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_readiness.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_real_provider_twins.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_reliability.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_reliability_classify.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_rlm_wasm.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/stress/test_trace_search.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_assessments_api.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_authored.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_authored_bundle_collisions.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_authored_metric_contract.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_authored_named_models.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_authored_optimize.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_callback.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_candidate_lineage.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/conftest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_admin.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_api_client.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_assessments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_auth.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_credentials.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_datasets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_deployment_runs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_deployments.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_evals.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_login.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_main.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_optimizations.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_org.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_pagination.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_parity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_programs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_provider_credentials.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_schema_sample.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_shell.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_signatures.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_tool_servers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_top.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_traces.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_traces_search_wire.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_tree_help.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cli/test_valsets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_client.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_client_floor.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_client_program_names.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_clustering/__init__.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_clustering/conftest.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_clustering/test_edge_cases.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_clustering/test_hash_consistency.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_clustering/test_type_conversion.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_cmp551_grouping_identity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_configuration.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_context.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_context_propagation.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_credential_kwargs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_credential_selection.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_credential_values.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_dataset_polling.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_dataset_sync.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_datasets.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_decision_client_spans.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_decorators.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_deploy.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_deploy_mcp_tool_references.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_deploy_program_id.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_deployment_metadata.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_deployment_runs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_deployments_read.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_eval.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_eval_example_attribution.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_eval_start.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_eval_trace_grouping.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_exception_paths.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_execute.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_execute_run_identity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_exporter.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_exporter_program_names.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_exporter_queue.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_exporter_real.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_fake_lm.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_gepa_callback.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_gepa_integration.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_gepa_output_normalization.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_gepa_resume.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_identity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_imaging.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_import_weight.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_ingest_conformance.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_ingest_second_producer.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_integration.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_interpreter_callback.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_ir_encoder_properties.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_ir_golden_vectors.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_ir_roundtrip.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_lm15_native_calls.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_lm_configuration.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_mcp_tools.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_models.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_multi_client_stress_readiness.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimization_progress.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimization_start.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize_budget.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize_lift.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize_lms.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize_proposer.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize_reflection_lm.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_optimize_terminal_failure.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_packaging.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_packaging_callable_source.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_packaging_mcp_tools.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_packaging_program_source.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_poll_until.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_program_id_deprecation.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_program_identity.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_program_names_in_deploy.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_programs_create.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_project_payload.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_real_provider_twins_readiness.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_reflector_properties.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_reflector_smoke.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_release_stress_script.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_replaced_names.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_repro_reactv2_bugs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_require_version_bump.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_retry.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_reversible_failures.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_run_attribution_paths.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_runtime_tools.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_schemas.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_seal_lm_credential.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_seed_review_run.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_signature_inputs.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_span_sent_once.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_system_one.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_trace_context_concurrency.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_trace_fact_wire_contract.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_trace_facts.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_trace_render.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_traces_read.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_tracked_gepa.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_tracker_enrich.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_truncation.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_upload_auth_headers.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_valsets_api.py +0 -0
- {cmpnd-0.57.0 → cmpnd-0.58.0}/tests/test_xxh64.py +0 -0
|
@@ -123,6 +123,40 @@ parameter, and a spec-less mock accepts one anyway.
|
|
|
123
123
|
with real LLMs (`CMPND_E2E_*` keys). It never uses a mock or an in-process
|
|
124
124
|
fake, and it runs only locally.
|
|
125
125
|
|
|
126
|
+
## DSPy versions under test
|
|
127
|
+
|
|
128
|
+
The SDK supports DSPy 3.3.x and 3.4.x, and `dependencies` floors DSPy at
|
|
129
|
+
3.3.0. `pyproject.toml` declares one dependency group per DSPy version the
|
|
130
|
+
`sdk-test` matrix tests, such as `dspy-3-4-1 = ["dspy==3.4.1"]`.
|
|
131
|
+
`[tool.uv] conflicts` makes the groups mutually exclusive, so `uv.lock` holds a
|
|
132
|
+
whole tree for each DSPy. Dependency groups never reach the wheel, so users
|
|
133
|
+
still install against the `dspy>=…` floor in `dependencies`.
|
|
134
|
+
|
|
135
|
+
- A plain `uv sync` or `uv run` installs the default group, the newest tested
|
|
136
|
+
DSPy.
|
|
137
|
+
- `scripts/install-test-env.sh <python> <dspy>` builds `.venv` from one group's
|
|
138
|
+
locked tree, as each `sdk-test` leg in `ci-sdk.yml` does. From the repo root,
|
|
139
|
+
run `just sdk-test-env 3.13 3.3.0`, then, from `python-sdk/`,
|
|
140
|
+
`.venv/bin/python -m pytest tests/ -k "not e2e"`. `uv sync --extra dev` in
|
|
141
|
+
`python-sdk/` returns to the default group.
|
|
142
|
+
- `--latest` resolves every package fresh, as a user's install today would.
|
|
143
|
+
With the DSPy version `newest` it pins no DSPy either. The daily
|
|
144
|
+
`sdk-latest-dependencies.yml` run uses both: every sdk-test leg, plus one
|
|
145
|
+
leg on the newest DSPy, which is the first to see a DSPy release no group
|
|
146
|
+
tests yet. A failure there alerts Slack.
|
|
147
|
+
- A DSPy release can pin some packages exactly, such as gepa (`dspy==3.3.0`
|
|
148
|
+
pins gepa 0.1.1). Its group locks those packages at the pinned versions. The
|
|
149
|
+
`mcp` extra floors DSPy at 3.3.1, so it conflicts with the `dspy-3-3-0`
|
|
150
|
+
group.
|
|
151
|
+
|
|
152
|
+
To test another DSPy version, add its group to `[dependency-groups]` and to
|
|
153
|
+
the first `conflicts` list, add a conflict with the `mcp` extra if it is below
|
|
154
|
+
3.3.1, add the leg to `sdk-test`'s matrix and to
|
|
155
|
+
`sdk-latest-dependencies.yml`, and run `uv lock`.
|
|
156
|
+
`.github/scripts/test_workflows.py` fails while the groups and the matrix
|
|
157
|
+
disagree. To move the default, change `default-groups` and refresh the span
|
|
158
|
+
reference fixture with `uv run python -m tests.span_reference_fixture`.
|
|
159
|
+
|
|
126
160
|
## Two packages, one published distribution
|
|
127
161
|
|
|
128
162
|
`cmpnd` (`cmpnd/`) is the SDK. `cmpnd_ingest` (`ingest/cmpnd_ingest/`) is the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cmpnd
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.58.0
|
|
4
4
|
Summary: DSPy observability and deployment SDK for cmpnd
|
|
5
5
|
Project-URL: Homepage, https://cmpnd.ai
|
|
6
6
|
Author-email: cmpnd <hello@cmpnd.ai>
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.15
|
|
18
18
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
19
19
|
Requires-Python: >=3.11
|
|
20
|
-
Requires-Dist: dspy>=3.
|
|
20
|
+
Requires-Dist: dspy>=3.3.0
|
|
21
21
|
Requires-Dist: httpx>=0.27.0
|
|
22
22
|
Requires-Dist: ipython>=8.20
|
|
23
23
|
Requires-Dist: pydantic>=2.0
|
|
@@ -25,7 +25,7 @@ def _built_lms(root: Path):
|
|
|
25
25
|
|
|
26
26
|
The check reads objects the import built and parses no source. It wraps the
|
|
27
27
|
``__init__`` of ``dspy.BaseLM`` and of every LM class that defines its own, because
|
|
28
|
-
|
|
28
|
+
an LM subclass need not call ``BaseLM.__init__``. It names the innermost
|
|
29
29
|
module of the bundle on the stack, so an LM a helper module builds is named by that
|
|
30
30
|
module, and records each LM once, however many of the wrapped constructors it runs.
|
|
31
31
|
"""
|
|
@@ -172,9 +172,6 @@ def patch_gepa() -> None:
|
|
|
172
172
|
|
|
173
173
|
import dspy
|
|
174
174
|
|
|
175
|
-
if not hasattr(dspy, "GEPA"):
|
|
176
|
-
return
|
|
177
|
-
|
|
178
175
|
# Resolve callback support once, at patch time — not per compile — so the
|
|
179
176
|
# answer matches the installed gepa the patch bound to.
|
|
180
177
|
has_callbacks = _gepa_supports_callbacks()
|
|
@@ -223,10 +220,10 @@ def unpatch_gepa() -> None:
|
|
|
223
220
|
_gepa_patched = False
|
|
224
221
|
return
|
|
225
222
|
|
|
226
|
-
GEPA =
|
|
227
|
-
if
|
|
228
|
-
GEPA.__init__ = GEPA._cmpnd_original_init
|
|
229
|
-
GEPA.compile = GEPA._cmpnd_original_compile
|
|
230
|
-
del GEPA._cmpnd_original_init
|
|
231
|
-
del GEPA._cmpnd_original_compile
|
|
223
|
+
GEPA = dspy.GEPA
|
|
224
|
+
if hasattr(GEPA, "_cmpnd_original_init"):
|
|
225
|
+
GEPA.__init__ = GEPA._cmpnd_original_init # pyright: ignore[reportAttributeAccessIssue]
|
|
226
|
+
GEPA.compile = GEPA._cmpnd_original_compile # pyright: ignore[reportAttributeAccessIssue]
|
|
227
|
+
del GEPA._cmpnd_original_init # pyright: ignore[reportAttributeAccessIssue]
|
|
228
|
+
del GEPA._cmpnd_original_compile # pyright: ignore[reportAttributeAccessIssue]
|
|
232
229
|
_gepa_patched = False
|
|
@@ -1101,7 +1101,7 @@ class _ModuleMixin(_CallbackBase):
|
|
|
1101
1101
|
"""Map DSPy module instance to span type."""
|
|
1102
1102
|
if isinstance(instance, dspy.Retrieve):
|
|
1103
1103
|
return models.SpanType.RETRIEVE
|
|
1104
|
-
elif isinstance(instance,
|
|
1104
|
+
elif isinstance(instance, dspy.RLM):
|
|
1105
1105
|
return models.SpanType.RLM
|
|
1106
1106
|
elif isinstance(instance, dspy.ReAct):
|
|
1107
1107
|
return models.SpanType.REACT
|
|
@@ -1332,15 +1332,13 @@ def code_component_types(student: Any) -> dict[str, str]:
|
|
|
1332
1332
|
serve cannot tell source from prose on its own, and without this a Flex's module
|
|
1333
1333
|
source renders as a word-diffed paragraph.
|
|
1334
1334
|
|
|
1335
|
-
Empty for a program with no Flex,
|
|
1336
|
-
not a dspy module.
|
|
1335
|
+
Empty for a program with no Flex, and for anything that is not a dspy module.
|
|
1337
1336
|
"""
|
|
1338
1337
|
import dspy
|
|
1339
1338
|
|
|
1340
|
-
|
|
1341
|
-
if flex_cls is None or not isinstance(student, dspy.Module):
|
|
1339
|
+
if not isinstance(student, dspy.Module):
|
|
1342
1340
|
return {}
|
|
1343
|
-
return {name: COMPONENT_KIND_CODE for name, sub in student.named_parameters() if isinstance(sub,
|
|
1341
|
+
return {name: COMPONENT_KIND_CODE for name, sub in student.named_parameters() if isinstance(sub, dspy.Flex)}
|
|
1344
1342
|
|
|
1345
1343
|
|
|
1346
1344
|
def enrich_from_program(
|
|
@@ -59,9 +59,6 @@ and sends the id.
|
|
|
59
59
|
`cmpnd programs purge --all` empties the Trash. Nothing restores a purged
|
|
60
60
|
program. Both ask for confirmation at a terminal and need `--force` anywhere
|
|
61
61
|
else. A live program is never purged.
|
|
62
|
-
A program created by name cannot be purged yet. It stays in the Trash, where
|
|
63
|
-
it no longer counts toward a plan's program cap, and `purge --all` answers
|
|
64
|
-
how many such programs it kept.
|
|
65
62
|
|
|
66
63
|
A program in the Trash or purged gives up its name. The next
|
|
67
64
|
`cmpnd programs create`, `cmpnd deploy` or SDK run under that name gets a new
|
|
@@ -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.
|
|
8
|
+
version = "0.58.0"
|
|
9
9
|
description = "DSPy observability and deployment SDK for cmpnd"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.11"
|
|
@@ -28,7 +28,7 @@ classifiers = [
|
|
|
28
28
|
]
|
|
29
29
|
|
|
30
30
|
dependencies = [
|
|
31
|
-
"dspy>=3.
|
|
31
|
+
"dspy>=3.3.0",
|
|
32
32
|
# Reached directly by the SDK (cmpnd/optimization.py's poll, cmpnd/datasets.py)
|
|
33
33
|
# and by the ingest transport this wheel bundles (ingest/cmpnd_ingest), whose
|
|
34
34
|
# only non-stdlib import it is.
|
|
@@ -129,6 +129,33 @@ fake-provider = [
|
|
|
129
129
|
[tool.uv.sources]
|
|
130
130
|
cmpnd-fake-provider = { path = "../fake-provider", editable = true }
|
|
131
131
|
|
|
132
|
+
# One group per DSPy version the test matrix runs, so uv.lock locks a whole tree for
|
|
133
|
+
# each and a test leg installs from the lock with only DSPy varying
|
|
134
|
+
# (`scripts/install-test-env.sh`; AGENTS.md, "DSPy versions under test"). Dependency
|
|
135
|
+
# groups never reach the wheel's metadata, so a user's install still takes
|
|
136
|
+
# `dspy>=3.3.0` above. Each group name is `dspy-` and the version with dots turned to
|
|
137
|
+
# dashes.
|
|
138
|
+
[dependency-groups]
|
|
139
|
+
dspy-3-4-1 = ["dspy==3.4.1"]
|
|
140
|
+
dspy-3-4-0 = ["dspy==3.4.0"]
|
|
141
|
+
dspy-3-3-1 = ["dspy==3.3.1"]
|
|
142
|
+
dspy-3-3-0 = ["dspy==3.3.0"]
|
|
143
|
+
|
|
144
|
+
[tool.uv]
|
|
145
|
+
# A plain `uv sync` or `uv run` installs the newest tested DSPy.
|
|
146
|
+
default-groups = ["dspy-3-4-1"]
|
|
147
|
+
# The groups pin different DSPy versions, so uv resolves a separate fork for each.
|
|
148
|
+
# The mcp extra floors dspy at 3.3.1, so it conflicts with the dspy-3-3-0 group.
|
|
149
|
+
conflicts = [
|
|
150
|
+
[
|
|
151
|
+
{ group = "dspy-3-4-1" },
|
|
152
|
+
{ group = "dspy-3-4-0" },
|
|
153
|
+
{ group = "dspy-3-3-1" },
|
|
154
|
+
{ group = "dspy-3-3-0" },
|
|
155
|
+
],
|
|
156
|
+
[{ extra = "mcp" }, { group = "dspy-3-3-0" }],
|
|
157
|
+
]
|
|
158
|
+
|
|
132
159
|
[project.scripts]
|
|
133
160
|
cmpnd = "cmpnd.cli:main"
|
|
134
161
|
|
|
@@ -141,8 +168,8 @@ Homepage = "https://cmpnd.ai"
|
|
|
141
168
|
# the two move together or a release fails at upload. hatchling 1.32.0 stamps
|
|
142
169
|
# 2.5, and the twine inside the pinned pypa/gh-action-pypi-publish accepts it;
|
|
143
170
|
# that pairing is what `twine check --strict` in sdk-lint proves on every PR.
|
|
144
|
-
# `==` so a backend bump
|
|
145
|
-
# than
|
|
171
|
+
# `==` so a backend bump is a reviewed edit here that runs that check, rather
|
|
172
|
+
# than a silent resolution on release day.
|
|
146
173
|
requires = ["hatchling==1.32.0"]
|
|
147
174
|
build-backend = "hatchling.build"
|
|
148
175
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Install cmpnd with pip's own resolver and check that the installed package
|
|
3
3
|
# imports and instruments DSPy. Called by .github/workflows/ci-sdk.yml (the
|
|
4
|
-
# sdk-test leg for Python 3.15).
|
|
4
|
+
# sdk-test-py315 job, the sdk-test leg for Python 3.15).
|
|
5
5
|
#
|
|
6
6
|
# `pip install cmpnd` is the install PyPI advertises. pip honours the
|
|
7
7
|
# requires-python upper bounds that uv ignores, so this check fails when no
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Build python-sdk/.venv for one sdk-test leg: the SDK and its dev extra, on one
|
|
3
|
+
# Python, at one DSPy version.
|
|
4
|
+
#
|
|
5
|
+
# CALLED BY: .github/workflows/ci-sdk.yml (sdk-test and sdk-test-py315),
|
|
6
|
+
# .github/workflows/sdk-latest-dependencies.yml (with --latest), `just
|
|
7
|
+
# sdk-test-env` at the repo root, and scripts/test-in-linux.sh.
|
|
8
|
+
#
|
|
9
|
+
# The install reads uv.lock. pyproject.toml declares one dependency group per
|
|
10
|
+
# tested DSPy, named `dspy-` and the version with dots turned to dashes, and the lock
|
|
11
|
+
# holds a whole tree for each. A leg syncs its group's tree exactly, so only DSPy,
|
|
12
|
+
# and whatever that DSPy itself pins, differs between legs. A red leg means the
|
|
13
|
+
# change broke something rather than that an upstream release did. The lock moves only
|
|
14
|
+
# by a reviewed commit: a security upgrade when bin/vulncheck fails on an advisory a
|
|
15
|
+
# bump would fix, and any other upgrade as a deliberate lock bump.
|
|
16
|
+
#
|
|
17
|
+
# --latest resolves every package fresh, with only the Python and DSPy versions
|
|
18
|
+
# pinned, as a user's install today would. With the DSPy version `newest`, it pins no
|
|
19
|
+
# DSPy either, so the install takes the newest release `dspy>=…` admits, as `pip
|
|
20
|
+
# install cmpnd` does. It prints the DSPy it installed. The daily run in
|
|
21
|
+
# sdk-latest-dependencies.yml uses it.
|
|
22
|
+
#
|
|
23
|
+
# Usage: scripts/install-test-env.sh [--latest] <python-version> <dspy-version>
|
|
24
|
+
# e.g. scripts/install-test-env.sh 3.13 3.3.0
|
|
25
|
+
# scripts/install-test-env.sh --latest 3.13 3.4.1
|
|
26
|
+
# scripts/install-test-env.sh --latest 3.14 newest
|
|
27
|
+
set -euo pipefail
|
|
28
|
+
|
|
29
|
+
usage() {
|
|
30
|
+
echo "usage: $0 [--latest] <python-version> <dspy-version>" >&2
|
|
31
|
+
exit 2
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
latest=false
|
|
35
|
+
if [ "${1:-}" = "--latest" ]; then
|
|
36
|
+
latest=true
|
|
37
|
+
shift
|
|
38
|
+
fi
|
|
39
|
+
[ "$#" -eq 2 ] || usage
|
|
40
|
+
python_version=$1
|
|
41
|
+
dspy_version=$2
|
|
42
|
+
|
|
43
|
+
cd "$(dirname "${BASH_SOURCE[0]}")/.."
|
|
44
|
+
|
|
45
|
+
if [ "$latest" = true ]; then
|
|
46
|
+
uv venv --clear --python "$python_version" .venv
|
|
47
|
+
if [ "$dspy_version" = newest ]; then
|
|
48
|
+
uv pip install --python .venv/bin/python -e ".[dev]"
|
|
49
|
+
else
|
|
50
|
+
uv pip install --python .venv/bin/python -e ".[dev]" "dspy==$dspy_version"
|
|
51
|
+
fi
|
|
52
|
+
echo "install-test-env: installed $(uv pip freeze --python .venv/bin/python | grep -i '^dspy==')"
|
|
53
|
+
exit 0
|
|
54
|
+
fi
|
|
55
|
+
if [ "$dspy_version" = newest ]; then
|
|
56
|
+
echo "install-test-env: the DSPy version newest needs --latest. uv.lock locks one tree per tested DSPy, and a locked install names one." >&2
|
|
57
|
+
exit 2
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
group="dspy-${dspy_version//./-}"
|
|
61
|
+
if ! grep -qE "^$group = " pyproject.toml; then
|
|
62
|
+
echo "install-test-env: pyproject.toml declares no dependency group $group. To test dspy $dspy_version, add $group = [\"dspy==$dspy_version\"] to [dependency-groups] and to the conflicts list in [tool.uv], then run uv lock." >&2
|
|
63
|
+
exit 2
|
|
64
|
+
fi
|
|
65
|
+
# --frozen installs exactly what uv.lock holds and never re-locks. sdk-lint's
|
|
66
|
+
# `uv lock --check` fails when the lock is stale against pyproject.toml.
|
|
67
|
+
uv sync --frozen --extra dev --no-default-groups --group "$group" --python "$python_version"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# Run the SDK suite (or a subset) on Linux, in a container that
|
|
2
|
+
# Run the SDK suite (or a subset) on Linux, in a container that installs its own
|
|
3
3
|
# dependencies.
|
|
4
4
|
#
|
|
5
5
|
# The lane exists because some of what this SDK has to get right is only
|
|
@@ -16,14 +16,16 @@
|
|
|
16
16
|
#
|
|
17
17
|
# It deliberately does NOT mount the host `.venv`: those wheels are macOS
|
|
18
18
|
# wheels, and a container reusing them fails in ways that teach you nothing about
|
|
19
|
-
# the code. uv
|
|
20
|
-
# to "would CI see this too".
|
|
21
|
-
#
|
|
19
|
+
# the code. uv installs from uv.lock inside, which is also what makes this a real
|
|
20
|
+
# answer to "would CI see this too". SDK_TEST_DSPY_VERSION picks a DSPy group the
|
|
21
|
+
# way an sdk-test leg does (scripts/install-test-env.sh). The copy also drops
|
|
22
|
+
# `.pyc` files because their embedded source paths may name a worktree that moved
|
|
23
|
+
# or no longer exists.
|
|
22
24
|
#
|
|
23
25
|
# Usage — everything, or a pytest selector:
|
|
24
26
|
# python-sdk/scripts/test-in-linux.sh
|
|
25
27
|
# python-sdk/scripts/test-in-linux.sh tests/test_exporter_queue.py -v
|
|
26
|
-
# SDK_TEST_DSPY_VERSION=3.
|
|
28
|
+
# SDK_TEST_DSPY_VERSION=3.3.0 python-sdk/scripts/test-in-linux.sh tests/test_run_attribution_paths.py -v
|
|
27
29
|
#
|
|
28
30
|
# Called by: `just sdk-test-linux` (repo root). No CI workflow — CI already runs
|
|
29
31
|
# on Linux; this is the local mirror of what it does.
|
|
@@ -53,8 +55,7 @@ cp -r /repo/python-sdk /repo/fake-provider /repo/docs /work/
|
|
|
53
55
|
rm -rf /work/python-sdk/.venv
|
|
54
56
|
find /work/python-sdk -name "*.pyc" -delete
|
|
55
57
|
if [ -n "$SDK_TEST_DSPY_VERSION" ]; then
|
|
56
|
-
|
|
57
|
-
uv pip install --quiet -e ".[dev]" "dspy==$SDK_TEST_DSPY_VERSION"
|
|
58
|
+
scripts/install-test-env.sh 3.12 "$SDK_TEST_DSPY_VERSION"
|
|
58
59
|
else
|
|
59
60
|
uv sync --extra dev --quiet
|
|
60
61
|
fi
|
|
@@ -19,6 +19,7 @@ import gzip
|
|
|
19
19
|
import hashlib
|
|
20
20
|
import json
|
|
21
21
|
import re
|
|
22
|
+
import tomllib
|
|
22
23
|
import uuid
|
|
23
24
|
from datetime import datetime, timedelta, timezone
|
|
24
25
|
from pathlib import Path
|
|
@@ -109,13 +110,18 @@ def render(doc: dict[str, Any]) -> str:
|
|
|
109
110
|
return json.dumps(doc, sort_keys=True, ensure_ascii=False, separators=(",", ":")) + "\n"
|
|
110
111
|
|
|
111
112
|
|
|
112
|
-
def
|
|
113
|
-
"""The DSPy version ``
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
113
|
+
def default_dspy_version() -> str:
|
|
114
|
+
"""The DSPy version a plain ``uv sync`` installs, which rendered the fixture's prompts.
|
|
115
|
+
|
|
116
|
+
That is the version pyproject.toml's default dependency group pins.
|
|
117
|
+
"""
|
|
118
|
+
pyproject = tomllib.loads((Path(__file__).resolve().parents[1] / "pyproject.toml").read_text())
|
|
119
|
+
(group,) = pyproject["tool"]["uv"]["default-groups"]
|
|
120
|
+
(requirement,) = pyproject["dependency-groups"][group]
|
|
121
|
+
name, _, version = requirement.partition("==")
|
|
122
|
+
if name != "dspy" or not version:
|
|
123
|
+
raise RuntimeError(f"default group {group} pins no dspy version: {requirement!r}")
|
|
124
|
+
return version
|
|
119
125
|
|
|
120
126
|
|
|
121
127
|
def read_committed() -> str:
|
|
@@ -14,20 +14,14 @@ import pytest
|
|
|
14
14
|
pytest.importorskip("dspy")
|
|
15
15
|
|
|
16
16
|
import dspy
|
|
17
|
+
from dspy.adapters.baml_adapter import BAMLAdapter
|
|
17
18
|
from dspy.utils.dummies import DummyLM
|
|
18
19
|
|
|
19
20
|
from cmpnd.configuration import configure
|
|
20
21
|
from cmpnd.context import clear_context, get_current_span
|
|
21
22
|
from tests import _traced_run
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
from dspy.adapters.baml_adapter import BAMLAdapter
|
|
25
|
-
except ImportError: # pragma: no cover - older DSPy without BAML
|
|
26
|
-
BAMLAdapter = None
|
|
27
|
-
|
|
28
|
-
ADAPTERS = [dspy.ChatAdapter, dspy.JSONAdapter, dspy.XMLAdapter]
|
|
29
|
-
if BAMLAdapter is not None:
|
|
30
|
-
ADAPTERS.append(BAMLAdapter)
|
|
24
|
+
ADAPTERS = [dspy.ChatAdapter, dspy.JSONAdapter, dspy.XMLAdapter, BAMLAdapter]
|
|
31
25
|
|
|
32
26
|
|
|
33
27
|
@pytest.fixture(autouse=True)
|
|
@@ -37,10 +37,8 @@ pytest.importorskip("dspy")
|
|
|
37
37
|
def _typed_lm_types_available() -> bool:
|
|
38
38
|
"""Report whether the installed DSPy ships the typed LM contract.
|
|
39
39
|
|
|
40
|
-
``dspy.core.types`` (``LMUsage``, ``LMResponse``)
|
|
41
|
-
|
|
42
|
-
3.1.3, 3.2.0 and 3.2.1, present on 3.3.0 and 3.3.1, and removed in 3.4.0b1,
|
|
43
|
-
whose ``dspy.core.types`` raises ``ImportError``. Probed by import rather
|
|
40
|
+
``dspy.core.types`` (``LMUsage``, ``LMResponse``) is present on DSPy 3.3.0 and
|
|
41
|
+
3.3.1 and removed in 3.4.0b1, whose ``dspy.core.types`` raises ``ImportError``. Probed by import rather
|
|
44
42
|
than by version number, so the answer stays right whatever the matrix pins
|
|
45
43
|
next.
|
|
46
44
|
|
|
@@ -105,11 +105,10 @@ def test_loaded_tag_feeds_compiled_from(tmp_path):
|
|
|
105
105
|
|
|
106
106
|
|
|
107
107
|
def test_wrappers_forward_only_callers_args():
|
|
108
|
-
# The patch is installed process-wide,
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
#
|
|
112
|
-
# break where the wrapper forced allow_unsafe_lm_state.
|
|
108
|
+
# The patch is installed process-wide, so the wrappers must forward only what
|
|
109
|
+
# the caller passed, whatever dump_state/load_state signature the installed
|
|
110
|
+
# DSPy has: a bare positional round-trip must not raise from an injected
|
|
111
|
+
# keyword such as allow_unsafe_lm_state.
|
|
113
112
|
prog = _Tiny()
|
|
114
113
|
state = prog.dump_state() # no json_mode kwarg
|
|
115
114
|
_Tiny().load_state(state) # no allow_unsafe_lm_state kwarg
|
|
@@ -7,6 +7,7 @@ active cmpnd callback while preserving the func's signature (the interpreter
|
|
|
7
7
|
builds its sandbox stub from inspect.signature).
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
|
+
import contextlib
|
|
10
11
|
import inspect
|
|
11
12
|
import uuid
|
|
12
13
|
|
|
@@ -23,6 +24,18 @@ def _configured():
|
|
|
23
24
|
yield
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def use_callbacks():
|
|
29
|
+
"""Installs DSPy callbacks for the rest of one test through dspy.context.
|
|
30
|
+
|
|
31
|
+
monkeypatch cannot set them: dspy.settings serves callbacks from its config
|
|
32
|
+
through __getattr__, so pytest 9.2's monkeypatch records the attribute as
|
|
33
|
+
unset and its teardown delattr fails.
|
|
34
|
+
"""
|
|
35
|
+
with contextlib.ExitStack() as stack:
|
|
36
|
+
yield lambda *cbs: stack.enter_context(dspy.context(callbacks=list(cbs)))
|
|
37
|
+
|
|
38
|
+
|
|
26
39
|
def _make_rlm():
|
|
27
40
|
def add_pages(first: int, last: int) -> int:
|
|
28
41
|
"""Sum a page range."""
|
|
@@ -52,7 +65,7 @@ def test_wrapped_tool_preserves_signature():
|
|
|
52
65
|
assert inspect.signature(shim) == inspect.signature(add_pages)
|
|
53
66
|
|
|
54
67
|
|
|
55
|
-
def test_tool_span_created_and_nested_under_rlm(monkeypatch):
|
|
68
|
+
def test_tool_span_created_and_nested_under_rlm(monkeypatch, use_callbacks):
|
|
56
69
|
"""With a callback and an RLM.forward span on the stack, invoking a wrapped
|
|
57
70
|
tool creates a TOOL span parented to the RLM span."""
|
|
58
71
|
_rlm_patch._patched = False
|
|
@@ -61,7 +74,7 @@ def test_tool_span_created_and_nested_under_rlm(monkeypatch):
|
|
|
61
74
|
tracked = []
|
|
62
75
|
cb = callback.CmpndCallback()
|
|
63
76
|
monkeypatch.setattr(cb, "_track_span", lambda span: tracked.append(span))
|
|
64
|
-
|
|
77
|
+
use_callbacks(cb)
|
|
65
78
|
|
|
66
79
|
context.clear_context()
|
|
67
80
|
context.set_current_trace(models.TraceBuilder(trace_id=uuid.uuid4()))
|
|
@@ -86,7 +99,7 @@ def test_tool_span_created_and_nested_under_rlm(monkeypatch):
|
|
|
86
99
|
assert span.trace_id == rlm_span.trace_id
|
|
87
100
|
|
|
88
101
|
|
|
89
|
-
def test_multiple_callbacks_emit_one_tool_span(monkeypatch):
|
|
102
|
+
def test_multiple_callbacks_emit_one_tool_span(monkeypatch, use_callbacks):
|
|
90
103
|
"""Two registered CmpndCallbacks share one span-stack contextvar, so the
|
|
91
104
|
shim dispatches to only the first — one tool span, stack balanced, no
|
|
92
105
|
tool-span-nested-under-tool-span corruption."""
|
|
@@ -98,7 +111,7 @@ def test_multiple_callbacks_emit_one_tool_span(monkeypatch):
|
|
|
98
111
|
cb_b = callback.CmpndCallback()
|
|
99
112
|
monkeypatch.setattr(cb_a, "_track_span", lambda span: tracked_a.append(span))
|
|
100
113
|
monkeypatch.setattr(cb_b, "_track_span", lambda span: tracked_b.append(span))
|
|
101
|
-
|
|
114
|
+
use_callbacks(cb_a, cb_b)
|
|
102
115
|
|
|
103
116
|
context.clear_context()
|
|
104
117
|
context.set_current_trace(models.TraceBuilder(trace_id=uuid.uuid4()))
|
|
@@ -136,14 +149,14 @@ def test_tracing_off_calls_func_without_span():
|
|
|
136
149
|
dspy.settings.callbacks = original
|
|
137
150
|
|
|
138
151
|
|
|
139
|
-
def test_raising_tool_closes_span_and_reraises(monkeypatch):
|
|
152
|
+
def test_raising_tool_closes_span_and_reraises(monkeypatch, use_callbacks):
|
|
140
153
|
_rlm_patch._patched = False
|
|
141
154
|
_rlm_patch.patch_rlm_tools()
|
|
142
155
|
|
|
143
156
|
tracked = []
|
|
144
157
|
cb = callback.CmpndCallback()
|
|
145
158
|
monkeypatch.setattr(cb, "_track_span", lambda span: tracked.append(span))
|
|
146
|
-
|
|
159
|
+
use_callbacks(cb)
|
|
147
160
|
|
|
148
161
|
def boom(x: int) -> int:
|
|
149
162
|
raise ValueError("nope")
|
|
@@ -350,12 +350,12 @@ def test_the_committed_thirty_turn_fixture_is_what_the_sdk_emits():
|
|
|
350
350
|
"""serve's Postgres test ingests this file, so it must be the SDK's current output.
|
|
351
351
|
|
|
352
352
|
The rendered prompts are DSPy's text, so the comparison holds only on the
|
|
353
|
-
DSPy the
|
|
353
|
+
DSPy the default dependency group pins; the CI matrix's other versions skip it.
|
|
354
354
|
"""
|
|
355
355
|
from tests import span_reference_fixture
|
|
356
356
|
|
|
357
|
-
if dspy.__version__ != span_reference_fixture.
|
|
358
|
-
pytest.skip(f"the fixture was rendered by the
|
|
357
|
+
if dspy.__version__ != span_reference_fixture.default_dspy_version():
|
|
358
|
+
pytest.skip(f"the fixture was rendered by the default group's DSPy, not {dspy.__version__}")
|
|
359
359
|
fresh = span_reference_fixture.render(span_reference_fixture.build())
|
|
360
360
|
assert span_reference_fixture.read_committed() == fresh, (
|
|
361
361
|
"docs/schemas/span-references/rlm-30-turns.json.gz is stale; "
|