cmpnd 0.82.0__tar.gz → 0.83.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.82.0 → cmpnd-0.83.0}/PKG-INFO +79 -26
- {cmpnd-0.82.0 → cmpnd-0.83.0}/README.md +78 -25
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/__init__.py +6 -1
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/top.py +3 -3
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/cli.md +24 -14
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/client.md +25 -13
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/custom-proposer.md +3 -1
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/sdk-instrumentation.md +7 -3
- {cmpnd-0.82.0 → cmpnd-0.83.0}/examples/generalizing_proposer.py +3 -1
- cmpnd-0.83.0/examples/local_ollama.py +57 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/pyproject.toml +1 -1
- {cmpnd-0.82.0 → cmpnd-0.83.0}/uv.lock +1 -1
- cmpnd-0.82.0/examples/local_ollama.py +0 -48
- {cmpnd-0.82.0 → cmpnd-0.83.0}/.gitignore +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/AGENTS.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/CLAUDE.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_assessments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_authored_import.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_deployments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_exporter_pool.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_gepa_patch.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_http.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_program_patch.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_rlm_patch.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_runtime_tools.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_timespec.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_traces.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_valsets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/authored.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/callback.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/api_client.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/admin.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/assessments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/auth.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/datasets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/deployments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/evals.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/login.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/optimizations.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/org.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/tool_servers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/traces.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/valsets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/credentials.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/deprecation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/pagination.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/shell.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/trace_render.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/tree_help.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/verbs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/views.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/client.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/configuration.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/context.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/credentials.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/dataset_sync.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/datasets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/decorators.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/deployment.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/deployment_metadata.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/deployment_runs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/eval_handler.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/execution.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/exporter.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/exporter_http.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/helpers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/identity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/imaging.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/decode.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/encode.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/hash.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/program.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/reflection.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/types.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/xxh64.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/lm_configuration.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/mcp_servers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/models.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/named_programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimization.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/gepa.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/gepa_callback.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/resume.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/tracker.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/packaging.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/program_naming.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/references.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/retry.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/traces.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/2026-04-02-code-review.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/reading-traces.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/LINEAGE.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/README.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/bodies.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/program_names.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/protocols.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/py.typed +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/request_log.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/retry.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/pyproject.toml +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/audit-sdist.sh +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/capture_review_run.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/check-pip-install.sh +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/check_release_artifacts.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/fixtures/review_run.json.gz +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/gepa_resume_bug.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/install-test-env.sh +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/release-gate.sh +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/release-real-models.sh +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/require_version_bump.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/seed_review_run.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/selfhost_compat.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/test-in-linux.sh +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/__init__.pyi +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/primitives/__init__.pyi +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/primitives/prediction.pyi +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/utils/__init__.pyi +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/utils/callback.pyi +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/utils/dummies.pyi +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_credential_route.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_deployment_signature_helpers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_exporter_helpers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_fake_clock.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_identity_helpers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_resolve_refs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_traced_run.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/conftest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/committee_task.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/conftest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/continuation_task.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/fake_lm.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/helpers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/target_capabilities.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_assessments_cli.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_capture_prompts.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_composite_module.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_deploy_execute.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_deploy_pandas.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_deploy_programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_edge_cases.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_example_hash.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_gepa_optimization.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_interpreter_spans.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_lm_accuracy.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_module_tracing.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimization_lineage.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_continuation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_failures.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_loop.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_review_committee.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_parallel_export.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_project_attribution.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_react_tool_spans.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_save_load.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_trace_structure.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_traces_read.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_user_attribution.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_valsets_cli.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/01_predict_qa.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/08_opaque_module.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/10_react.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/11_refine.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/12_retrieve.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/13_knn.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/14_parallel.json +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/README.md +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/ingest_conformance.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/authored_optimize/judge.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/conftest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/hosted_optimize_probe.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/optimization_run_probe.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_logs_renders_traces.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_optimization_run.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_optimizing_progress.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_unhappy_path.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/__main__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/drain.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/ingest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/latency_transport.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/rlm_shape.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/rlm_size_report.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/sweep.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/test_rlm_shape.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/test_rlm_size_report.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/conftest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/seed_parity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_auth.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_datasets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_deployments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_evals.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_health.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_modules.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_optimizations.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_signatures.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_trace_streaming.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_traces.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_provider.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_readiness.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_reliability.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_result.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/mint_bedrock_token.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_bedrock_converse.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_deploy_programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_multi_client_stress.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_client_committee.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_continuation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_loop.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_stress.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_provider_roles.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_readiness.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_real_provider_twins.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_reliability.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_reliability_classify.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_rlm_wasm.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_trace_search.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/span_reference_fixture.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_adapter_reentrancy.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_assessments_api.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_binding_credentials.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_bundle_collisions.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_metric_contract.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_named_models.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_optimize.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_callback.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_candidate_lineage.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/conftest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_admin.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_api_client.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_assessments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_auth.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_credentials.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_datasets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_deployment_runs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_deployments.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_evals.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_login.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_main.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_optimizations.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_org.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_pagination.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_parity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_programs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_provider_credentials.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_schema_sample.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_shell.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_tool_servers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_top.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_traces.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_traces_search_wire.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_tree_help.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_valsets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_client.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_client_floor.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_client_program_names.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/__init__.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/conftest.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/test_edge_cases.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/test_hash_consistency.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/test_type_conversion.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cmp551_grouping_identity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_configuration.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_context.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_context_propagation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_credential_kwargs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_credential_selection.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_credential_values.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_dataset_polling.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_dataset_sync.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_datasets.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_decision_client_spans.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_decorators.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deploy.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deploy_mcp_tool_references.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deploy_program_id.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deployment_metadata.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deployment_runs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deployments_read.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_example_attribution.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_program_id.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_start.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_trace_grouping.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exception_paths.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_execute.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_execute_run_identity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter_program_names.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter_queue.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter_real.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_fake_lm.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_callback.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_integration.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_output_normalization.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_resume.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_identity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_imaging.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_import_weight.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ingest_conformance.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ingest_second_producer.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_integration.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_interpreter_callback.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ir_encoder_properties.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ir_golden_vectors.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ir_roundtrip.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_lm15_native_calls.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_lm_configuration.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_lm_usage_shapes.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_mcp_tools.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_models.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_multi_client_stress_readiness.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_no_signature_hash_on_the_wire.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_phase_callback.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_program_names.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_progress.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_start.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_budget.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_lift.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_lms.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_proposer.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_reflection_lm.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_terminal_failure.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging_callable_source.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging_mcp_tools.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging_program_source.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_poll_until.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_id_deprecation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_identity.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_lineage_persist.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_names_in_deploy.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_naming.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_programs_create.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_project_payload.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_real_provider_twins_readiness.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_reflector_properties.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_reflector_smoke.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_release_gate_script.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_release_real_models_script.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_replaced_names.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_repro_reactv2_bugs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_require_version_bump.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_retry.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_reversible_failures.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_rlm_patch.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_run_attribution_paths.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_runtime_tools.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_schemas.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_seal_lm_credential.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_seed_review_run.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_signature_inputs.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_span_references.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_span_sent_once.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_system_one.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_context_concurrency.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_fact_wire_contract.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_facts.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_render.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_traces_read.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_tracked_gepa.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_tracker_enrich.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_truncation.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_upload_auth_headers.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_valsets_api.py +0 -0
- {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_xxh64.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cmpnd
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.83.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>
|
|
@@ -66,8 +66,13 @@ uv add cmpnd # or: pip install cmpnd
|
|
|
66
66
|
The `cmpnd` library works with the cmpnd service at
|
|
67
67
|
[platform.cmpnd.ai](https://platform.cmpnd.ai). Create an API key on the
|
|
68
68
|
platform under Settings → API keys, and pass it as `api_key=` to
|
|
69
|
-
`cmpnd.Client()` or `cmpnd.configure()`. For a
|
|
70
|
-
pass the install's URL as `endpoint
|
|
69
|
+
`cmpnd.Client()` or `cmpnd.configure()`, or set `CMPND_API_KEY`. For a
|
|
70
|
+
self-hosted cmpnd install, also pass the install's URL as `endpoint=`, or set
|
|
71
|
+
`CMPND_ENDPOINT`.
|
|
72
|
+
|
|
73
|
+
The library reads its key and endpoint from those arguments and variables
|
|
74
|
+
alone. It never reads the key that `cmpnd login` stores for the command line,
|
|
75
|
+
so a script that runs after `cmpnd login` still sets `CMPND_API_KEY`.
|
|
71
76
|
|
|
72
77
|
## Quick start
|
|
73
78
|
|
|
@@ -176,12 +181,13 @@ client for server-side execution:
|
|
|
176
181
|
import cmpnd
|
|
177
182
|
import dspy
|
|
178
183
|
|
|
179
|
-
sdk = cmpnd.Client(
|
|
184
|
+
sdk = cmpnd.Client() # reads CMPND_API_KEY
|
|
185
|
+
openai = cmpnd.credentials.get("openai") # a credential your organization sealed
|
|
180
186
|
|
|
181
187
|
qa4 = cmpnd.Program(
|
|
182
188
|
"question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
|
|
183
189
|
)
|
|
184
|
-
deployed = sdk.deploy_program(qa4)
|
|
190
|
+
deployed = sdk.deploy_program(qa4, credential=openai)
|
|
185
191
|
|
|
186
192
|
result = sdk.run_deployment(deployed, question="What is DSPy?") # runs server-side
|
|
187
193
|
print(result.answer)
|
|
@@ -219,13 +225,18 @@ deployed = sdk.deploy_program(program, credential=luna)
|
|
|
219
225
|
the organization does not hold raises `cmpnd.CredentialNotFound`, which lists
|
|
220
226
|
the names it does hold and the nearest one. `cmpnd.credentials.list()`
|
|
221
227
|
returns them all.
|
|
228
|
+
- `cmpnd.credentials.get` reads the key and endpoint the way
|
|
229
|
+
`cmpnd.configure()` does, and also takes `api_key=` and `endpoint=`.
|
|
222
230
|
- `credential=` takes a `cmpnd.Credential`, never a string. A string raises
|
|
223
231
|
and shows the `cmpnd.credentials.get(...)` line to write.
|
|
224
|
-
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
232
|
+
- An organization may have no default credential. Then every deploy and every
|
|
233
|
+
optimization names its credential. The platform refuses one that names none,
|
|
234
|
+
and the refusal lists the names the organization holds. An owner sets a
|
|
235
|
+
default with `cmpnd credentials default NAME`, and a deploy without
|
|
236
|
+
`credential=` spends it.
|
|
237
|
+
- The deployment records the credential's name. Its runs spend the newest
|
|
238
|
+
credential sealed under that name, so `run_deployment()` takes no credential,
|
|
239
|
+
and an owner who rotates a key needs no redeploy.
|
|
229
240
|
- The deploy prints the protocol, model and credential of each binding, as
|
|
230
241
|
above. A server that prints none chose the credential from the model's
|
|
231
242
|
provider prefix, and the SDK warns.
|
|
@@ -237,6 +248,24 @@ the platform only through `cmpnd credentials create`. `cmpnd deploy FILE`
|
|
|
237
248
|
refuses source whose import builds an LM carrying a key, and names the module,
|
|
238
249
|
the model and the field.
|
|
239
250
|
|
|
251
|
+
### Gateways
|
|
252
|
+
|
|
253
|
+
An OpenAI-compatible gateway, such as LunaRoute, is a credential of its own.
|
|
254
|
+
Seal its key with the gateway's preset, or with `--preset openai_like` and the
|
|
255
|
+
gateway's address:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
cmpnd credentials create --name luna-exec --preset lunaroute < key.txt
|
|
259
|
+
cmpnd credentials create --name my-gateway --preset openai_like --api-base https://gateway.example.com/v1 < key.txt
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Spell the gateway's models `openai/<model>`, such as
|
|
263
|
+
`openai/deepseek-4.1-flash`, and deploy with
|
|
264
|
+
`credential=cmpnd.credentials.get("luna-exec")`. The `openai/` prefix selects
|
|
265
|
+
the Chat Completions wire protocol, and the gateway receives the model after
|
|
266
|
+
the first `/`. The credential decides the address and the key, so one gateway
|
|
267
|
+
serves every model it routes.
|
|
268
|
+
|
|
240
269
|
### The same source on your laptop and hosted
|
|
241
270
|
|
|
242
271
|
A program's logic runs unchanged on your laptop and hosted. On your laptop it
|
|
@@ -259,11 +288,10 @@ def metric(gold, pred, trace=None, pred_name=None, pred_trace=None, lms=None):
|
|
|
259
288
|
return dspy.Prediction(score=float(verdict.correct), feedback="correct" if verdict.correct else "wrong")
|
|
260
289
|
```
|
|
261
290
|
|
|
262
|
-
Seal the key once for the organization
|
|
291
|
+
Seal the key once for the organization:
|
|
263
292
|
|
|
264
293
|
```bash
|
|
265
294
|
printf '%s' "$OPENAI_API_KEY" | cmpnd credentials create --name openai --preset openai
|
|
266
|
-
cmpnd credentials default openai
|
|
267
295
|
```
|
|
268
296
|
|
|
269
297
|
The entry point is the only code that knows where the run happens:
|
|
@@ -287,13 +315,15 @@ lms = {"critic": dspy.LM("openai/gpt-5-mini")}
|
|
|
287
315
|
train, val = load_examples() # your dspy.Example lists
|
|
288
316
|
|
|
289
317
|
if HOSTED:
|
|
290
|
-
|
|
318
|
+
openai = cmpnd.credentials.get("openai")
|
|
319
|
+
deployed = sdk.deploy_program(qa, credential=openai)
|
|
291
320
|
print(sdk.run_deployment(deployed, question="What is DSPy?"))
|
|
292
321
|
best = sdk.optimize_deployment(
|
|
293
322
|
deployed,
|
|
294
323
|
trainset=train,
|
|
295
324
|
valset=val,
|
|
296
325
|
metric=metric, # the platform hands it lms
|
|
326
|
+
credential=openai, # every model below spends it
|
|
297
327
|
reflection_lm=cmpnd.HostedLM(reflection),
|
|
298
328
|
lms={name: cmpnd.HostedLM(model) for name, model in lms.items()},
|
|
299
329
|
auto="light",
|
|
@@ -305,12 +335,12 @@ else:
|
|
|
305
335
|
```
|
|
306
336
|
|
|
307
337
|
`python main.py` runs everything on your laptop, and `python main.py --hosted`
|
|
308
|
-
runs it on the platform. `cmpnd deploy qa.py qa` deploys
|
|
309
|
-
terminal.
|
|
338
|
+
runs it on the platform. `cmpnd deploy qa.py qa --credential openai` deploys
|
|
339
|
+
the same file from the terminal.
|
|
310
340
|
|
|
311
341
|
| | On your laptop | Hosted |
|
|
312
342
|
|---|---|---|
|
|
313
|
-
| Key | the provider's variable in your environment, such as `OPENAI_API_KEY` | the credential the call names, else the organization's default |
|
|
343
|
+
| Key | the provider's variable in your environment, such as `OPENAI_API_KEY` | the credential the call names, else the organization's default, if one is set |
|
|
314
344
|
| Address | the LM's `api_base`, else the provider's endpoint | the credential's `api_base` |
|
|
315
345
|
| Model | `gpt-5-mini`, the model after its first `/` | `gpt-5-mini` |
|
|
316
346
|
| The metric's `lms` | the dict the entry point binds | the run's `lms=`, which the platform hands it |
|
|
@@ -348,7 +378,7 @@ sdk.deploy_program(
|
|
|
348
378
|
metric=None, # optional: a metric callable, packaged for optimization
|
|
349
379
|
timeout=300, # optional: seconds to wait for the deployment to be ready
|
|
350
380
|
metadata=None, # optional: a JSON-serializable dict, at most 64 KiB, stored with the deployment
|
|
351
|
-
credential=None, #
|
|
381
|
+
credential=None, # a cmpnd.Credential the program's model spends, else the org's default, if one is set
|
|
352
382
|
)
|
|
353
383
|
```
|
|
354
384
|
|
|
@@ -371,12 +401,13 @@ found. Deploy the program first:
|
|
|
371
401
|
import cmpnd
|
|
372
402
|
import dspy
|
|
373
403
|
|
|
374
|
-
sdk = cmpnd.Client(
|
|
404
|
+
sdk = cmpnd.Client() # reads CMPND_API_KEY
|
|
405
|
+
openai = cmpnd.credentials.get("openai")
|
|
375
406
|
|
|
376
407
|
program = cmpnd.Program(
|
|
377
408
|
"haiku", module=dspy.ChainOfThought("topic -> haiku"), lm=dspy.LM("openai/gpt-6-luna")
|
|
378
409
|
)
|
|
379
|
-
deployed = sdk.deploy_program(program)
|
|
410
|
+
deployed = sdk.deploy_program(program, credential=openai)
|
|
380
411
|
|
|
381
412
|
# GEPA needs a five-argument feedback metric that returns dspy.Prediction(score=, feedback=)
|
|
382
413
|
def metric(example, pred, trace=None, pred_name=None, pred_trace=None):
|
|
@@ -391,6 +422,7 @@ best = sdk.optimize_deployment(
|
|
|
391
422
|
trainset=train,
|
|
392
423
|
valset=val,
|
|
393
424
|
metric=metric,
|
|
425
|
+
credential=openai,
|
|
394
426
|
reflection_lm=dspy.LM("openai/gpt-6-luna"),
|
|
395
427
|
auto="light",
|
|
396
428
|
)
|
|
@@ -429,9 +461,9 @@ best = sdk.optimize_deployment(
|
|
|
429
461
|
|
|
430
462
|
`cmpnd.HostedLM(lm, credential=c)` wraps a chat LM, and
|
|
431
463
|
`cmpnd.SystemOne(model, credential=c)` declares a System One model. A binding
|
|
432
|
-
without a credential spends the run's,
|
|
433
|
-
platform refuses a credential whose endpoint does not serve a
|
|
434
|
-
protocol, and names the `credential=` to add.
|
|
464
|
+
without a credential spends the run's, else the organization's default, if one
|
|
465
|
+
is set. The platform refuses a credential whose endpoint does not serve a
|
|
466
|
+
binding's protocol, and names the `credential=` to add.
|
|
435
467
|
|
|
436
468
|
The SDK checks the metric before any network call. GEPA writes each new
|
|
437
469
|
instruction from the textual feedback the metric returns, so it needs a
|
|
@@ -466,6 +498,7 @@ def faithfulness(gold, pred, trace, pred_name, pred_trace, lms=None):
|
|
|
466
498
|
|
|
467
499
|
best = sdk.optimize_deployment(
|
|
468
500
|
deployed, optimizer="gepa", trainset=train, valset=val, metric=faithfulness,
|
|
501
|
+
credential=openai,
|
|
469
502
|
reflection_lm=dspy.LM("openai/gpt-6-luna"),
|
|
470
503
|
lms={"critic": dspy.LM("openai/gpt-6-luna")},
|
|
471
504
|
max_metric_calls=300,
|
|
@@ -499,7 +532,7 @@ sdk.optimize_deployment(
|
|
|
499
532
|
config=None, # optional: optimizer config, allow-listed by the platform
|
|
500
533
|
reflection_lm=None, # required: a dspy.LM, a bare model name or a cmpnd.HostedLM
|
|
501
534
|
lms=None, # optional: name -> dspy.LM, cmpnd.HostedLM or cmpnd.SystemOne
|
|
502
|
-
credential=None, #
|
|
535
|
+
credential=None, # the cmpnd.Credential every other binding spends, else the org's default, if one is set
|
|
503
536
|
max_metric_calls=None, # budget: the metric-call ceiling for the run
|
|
504
537
|
auto=None, # budget: "light", "medium" or "heavy"
|
|
505
538
|
may_author_code=None, # optional: False keeps each dspy.Flex at its deployed source
|
|
@@ -565,13 +598,33 @@ Deploy a source file under a program name, or optimize the program a file
|
|
|
565
598
|
declares:
|
|
566
599
|
|
|
567
600
|
```bash
|
|
568
|
-
cmpnd deploy program.py question-answerer
|
|
569
|
-
cmpnd optimize gepa task.py haiku --reflection-model openai/gpt-6-luna --auto light
|
|
601
|
+
cmpnd deploy program.py question-answerer --credential openai
|
|
602
|
+
cmpnd optimize gepa task.py haiku --credential openai --reflection-model openai/gpt-6-luna --auto light
|
|
570
603
|
```
|
|
571
604
|
|
|
572
605
|
`cmpnd deploy` uploads the file as written. `cmpnd optimize` reads `program`,
|
|
573
606
|
`trainset`, `valset` and `metric` from the file, deploys the program under the
|
|
574
|
-
program name and prints the best deployment ID.
|
|
607
|
+
program name and prints the best deployment ID. `--credential` names the
|
|
608
|
+
credential the program's models spend, and `cmpnd credentials list` shows the
|
|
609
|
+
names your organization holds.
|
|
610
|
+
|
|
611
|
+
`cmpnd programs rename PROGRAM NAME` gives a program a new name, or names one
|
|
612
|
+
that has none. PROGRAM is a program name or a `p_` id, and the program keeps
|
|
613
|
+
its id and its history. The old name is free at once, so update the code that
|
|
614
|
+
declares it.
|
|
615
|
+
|
|
616
|
+
A program calls tools on an MCP server once your organization seals the
|
|
617
|
+
server's key, registers the server and allows its tools:
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
cmpnd credentials create --kind mcp --server https://mcp.exa.ai/mcp --name exa-prod \
|
|
621
|
+
--placement query_param --query-param-name exaApiKey < exa-key.txt
|
|
622
|
+
cmpnd tool-servers create --url https://mcp.exa.ai/mcp --credential exa-prod
|
|
623
|
+
cmpnd tool-servers allow <server_id> web_search_exa
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
[`docs/cli.md`](docs/cli.md) describes every command, including "Tool
|
|
627
|
+
servers".
|
|
575
628
|
|
|
576
629
|
## Custom spans
|
|
577
630
|
|
|
@@ -15,8 +15,13 @@ uv add cmpnd # or: pip install cmpnd
|
|
|
15
15
|
The `cmpnd` library works with the cmpnd service at
|
|
16
16
|
[platform.cmpnd.ai](https://platform.cmpnd.ai). Create an API key on the
|
|
17
17
|
platform under Settings → API keys, and pass it as `api_key=` to
|
|
18
|
-
`cmpnd.Client()` or `cmpnd.configure()`. For a
|
|
19
|
-
pass the install's URL as `endpoint
|
|
18
|
+
`cmpnd.Client()` or `cmpnd.configure()`, or set `CMPND_API_KEY`. For a
|
|
19
|
+
self-hosted cmpnd install, also pass the install's URL as `endpoint=`, or set
|
|
20
|
+
`CMPND_ENDPOINT`.
|
|
21
|
+
|
|
22
|
+
The library reads its key and endpoint from those arguments and variables
|
|
23
|
+
alone. It never reads the key that `cmpnd login` stores for the command line,
|
|
24
|
+
so a script that runs after `cmpnd login` still sets `CMPND_API_KEY`.
|
|
20
25
|
|
|
21
26
|
## Quick start
|
|
22
27
|
|
|
@@ -125,12 +130,13 @@ client for server-side execution:
|
|
|
125
130
|
import cmpnd
|
|
126
131
|
import dspy
|
|
127
132
|
|
|
128
|
-
sdk = cmpnd.Client(
|
|
133
|
+
sdk = cmpnd.Client() # reads CMPND_API_KEY
|
|
134
|
+
openai = cmpnd.credentials.get("openai") # a credential your organization sealed
|
|
129
135
|
|
|
130
136
|
qa4 = cmpnd.Program(
|
|
131
137
|
"question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
|
|
132
138
|
)
|
|
133
|
-
deployed = sdk.deploy_program(qa4)
|
|
139
|
+
deployed = sdk.deploy_program(qa4, credential=openai)
|
|
134
140
|
|
|
135
141
|
result = sdk.run_deployment(deployed, question="What is DSPy?") # runs server-side
|
|
136
142
|
print(result.answer)
|
|
@@ -168,13 +174,18 @@ deployed = sdk.deploy_program(program, credential=luna)
|
|
|
168
174
|
the organization does not hold raises `cmpnd.CredentialNotFound`, which lists
|
|
169
175
|
the names it does hold and the nearest one. `cmpnd.credentials.list()`
|
|
170
176
|
returns them all.
|
|
177
|
+
- `cmpnd.credentials.get` reads the key and endpoint the way
|
|
178
|
+
`cmpnd.configure()` does, and also takes `api_key=` and `endpoint=`.
|
|
171
179
|
- `credential=` takes a `cmpnd.Credential`, never a string. A string raises
|
|
172
180
|
and shows the `cmpnd.credentials.get(...)` line to write.
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
181
|
+
- An organization may have no default credential. Then every deploy and every
|
|
182
|
+
optimization names its credential. The platform refuses one that names none,
|
|
183
|
+
and the refusal lists the names the organization holds. An owner sets a
|
|
184
|
+
default with `cmpnd credentials default NAME`, and a deploy without
|
|
185
|
+
`credential=` spends it.
|
|
186
|
+
- The deployment records the credential's name. Its runs spend the newest
|
|
187
|
+
credential sealed under that name, so `run_deployment()` takes no credential,
|
|
188
|
+
and an owner who rotates a key needs no redeploy.
|
|
178
189
|
- The deploy prints the protocol, model and credential of each binding, as
|
|
179
190
|
above. A server that prints none chose the credential from the model's
|
|
180
191
|
provider prefix, and the SDK warns.
|
|
@@ -186,6 +197,24 @@ the platform only through `cmpnd credentials create`. `cmpnd deploy FILE`
|
|
|
186
197
|
refuses source whose import builds an LM carrying a key, and names the module,
|
|
187
198
|
the model and the field.
|
|
188
199
|
|
|
200
|
+
### Gateways
|
|
201
|
+
|
|
202
|
+
An OpenAI-compatible gateway, such as LunaRoute, is a credential of its own.
|
|
203
|
+
Seal its key with the gateway's preset, or with `--preset openai_like` and the
|
|
204
|
+
gateway's address:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
cmpnd credentials create --name luna-exec --preset lunaroute < key.txt
|
|
208
|
+
cmpnd credentials create --name my-gateway --preset openai_like --api-base https://gateway.example.com/v1 < key.txt
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Spell the gateway's models `openai/<model>`, such as
|
|
212
|
+
`openai/deepseek-4.1-flash`, and deploy with
|
|
213
|
+
`credential=cmpnd.credentials.get("luna-exec")`. The `openai/` prefix selects
|
|
214
|
+
the Chat Completions wire protocol, and the gateway receives the model after
|
|
215
|
+
the first `/`. The credential decides the address and the key, so one gateway
|
|
216
|
+
serves every model it routes.
|
|
217
|
+
|
|
189
218
|
### The same source on your laptop and hosted
|
|
190
219
|
|
|
191
220
|
A program's logic runs unchanged on your laptop and hosted. On your laptop it
|
|
@@ -208,11 +237,10 @@ def metric(gold, pred, trace=None, pred_name=None, pred_trace=None, lms=None):
|
|
|
208
237
|
return dspy.Prediction(score=float(verdict.correct), feedback="correct" if verdict.correct else "wrong")
|
|
209
238
|
```
|
|
210
239
|
|
|
211
|
-
Seal the key once for the organization
|
|
240
|
+
Seal the key once for the organization:
|
|
212
241
|
|
|
213
242
|
```bash
|
|
214
243
|
printf '%s' "$OPENAI_API_KEY" | cmpnd credentials create --name openai --preset openai
|
|
215
|
-
cmpnd credentials default openai
|
|
216
244
|
```
|
|
217
245
|
|
|
218
246
|
The entry point is the only code that knows where the run happens:
|
|
@@ -236,13 +264,15 @@ lms = {"critic": dspy.LM("openai/gpt-5-mini")}
|
|
|
236
264
|
train, val = load_examples() # your dspy.Example lists
|
|
237
265
|
|
|
238
266
|
if HOSTED:
|
|
239
|
-
|
|
267
|
+
openai = cmpnd.credentials.get("openai")
|
|
268
|
+
deployed = sdk.deploy_program(qa, credential=openai)
|
|
240
269
|
print(sdk.run_deployment(deployed, question="What is DSPy?"))
|
|
241
270
|
best = sdk.optimize_deployment(
|
|
242
271
|
deployed,
|
|
243
272
|
trainset=train,
|
|
244
273
|
valset=val,
|
|
245
274
|
metric=metric, # the platform hands it lms
|
|
275
|
+
credential=openai, # every model below spends it
|
|
246
276
|
reflection_lm=cmpnd.HostedLM(reflection),
|
|
247
277
|
lms={name: cmpnd.HostedLM(model) for name, model in lms.items()},
|
|
248
278
|
auto="light",
|
|
@@ -254,12 +284,12 @@ else:
|
|
|
254
284
|
```
|
|
255
285
|
|
|
256
286
|
`python main.py` runs everything on your laptop, and `python main.py --hosted`
|
|
257
|
-
runs it on the platform. `cmpnd deploy qa.py qa` deploys
|
|
258
|
-
terminal.
|
|
287
|
+
runs it on the platform. `cmpnd deploy qa.py qa --credential openai` deploys
|
|
288
|
+
the same file from the terminal.
|
|
259
289
|
|
|
260
290
|
| | On your laptop | Hosted |
|
|
261
291
|
|---|---|---|
|
|
262
|
-
| Key | the provider's variable in your environment, such as `OPENAI_API_KEY` | the credential the call names, else the organization's default |
|
|
292
|
+
| Key | the provider's variable in your environment, such as `OPENAI_API_KEY` | the credential the call names, else the organization's default, if one is set |
|
|
263
293
|
| Address | the LM's `api_base`, else the provider's endpoint | the credential's `api_base` |
|
|
264
294
|
| Model | `gpt-5-mini`, the model after its first `/` | `gpt-5-mini` |
|
|
265
295
|
| The metric's `lms` | the dict the entry point binds | the run's `lms=`, which the platform hands it |
|
|
@@ -297,7 +327,7 @@ sdk.deploy_program(
|
|
|
297
327
|
metric=None, # optional: a metric callable, packaged for optimization
|
|
298
328
|
timeout=300, # optional: seconds to wait for the deployment to be ready
|
|
299
329
|
metadata=None, # optional: a JSON-serializable dict, at most 64 KiB, stored with the deployment
|
|
300
|
-
credential=None, #
|
|
330
|
+
credential=None, # a cmpnd.Credential the program's model spends, else the org's default, if one is set
|
|
301
331
|
)
|
|
302
332
|
```
|
|
303
333
|
|
|
@@ -320,12 +350,13 @@ found. Deploy the program first:
|
|
|
320
350
|
import cmpnd
|
|
321
351
|
import dspy
|
|
322
352
|
|
|
323
|
-
sdk = cmpnd.Client(
|
|
353
|
+
sdk = cmpnd.Client() # reads CMPND_API_KEY
|
|
354
|
+
openai = cmpnd.credentials.get("openai")
|
|
324
355
|
|
|
325
356
|
program = cmpnd.Program(
|
|
326
357
|
"haiku", module=dspy.ChainOfThought("topic -> haiku"), lm=dspy.LM("openai/gpt-6-luna")
|
|
327
358
|
)
|
|
328
|
-
deployed = sdk.deploy_program(program)
|
|
359
|
+
deployed = sdk.deploy_program(program, credential=openai)
|
|
329
360
|
|
|
330
361
|
# GEPA needs a five-argument feedback metric that returns dspy.Prediction(score=, feedback=)
|
|
331
362
|
def metric(example, pred, trace=None, pred_name=None, pred_trace=None):
|
|
@@ -340,6 +371,7 @@ best = sdk.optimize_deployment(
|
|
|
340
371
|
trainset=train,
|
|
341
372
|
valset=val,
|
|
342
373
|
metric=metric,
|
|
374
|
+
credential=openai,
|
|
343
375
|
reflection_lm=dspy.LM("openai/gpt-6-luna"),
|
|
344
376
|
auto="light",
|
|
345
377
|
)
|
|
@@ -378,9 +410,9 @@ best = sdk.optimize_deployment(
|
|
|
378
410
|
|
|
379
411
|
`cmpnd.HostedLM(lm, credential=c)` wraps a chat LM, and
|
|
380
412
|
`cmpnd.SystemOne(model, credential=c)` declares a System One model. A binding
|
|
381
|
-
without a credential spends the run's,
|
|
382
|
-
platform refuses a credential whose endpoint does not serve a
|
|
383
|
-
protocol, and names the `credential=` to add.
|
|
413
|
+
without a credential spends the run's, else the organization's default, if one
|
|
414
|
+
is set. The platform refuses a credential whose endpoint does not serve a
|
|
415
|
+
binding's protocol, and names the `credential=` to add.
|
|
384
416
|
|
|
385
417
|
The SDK checks the metric before any network call. GEPA writes each new
|
|
386
418
|
instruction from the textual feedback the metric returns, so it needs a
|
|
@@ -415,6 +447,7 @@ def faithfulness(gold, pred, trace, pred_name, pred_trace, lms=None):
|
|
|
415
447
|
|
|
416
448
|
best = sdk.optimize_deployment(
|
|
417
449
|
deployed, optimizer="gepa", trainset=train, valset=val, metric=faithfulness,
|
|
450
|
+
credential=openai,
|
|
418
451
|
reflection_lm=dspy.LM("openai/gpt-6-luna"),
|
|
419
452
|
lms={"critic": dspy.LM("openai/gpt-6-luna")},
|
|
420
453
|
max_metric_calls=300,
|
|
@@ -448,7 +481,7 @@ sdk.optimize_deployment(
|
|
|
448
481
|
config=None, # optional: optimizer config, allow-listed by the platform
|
|
449
482
|
reflection_lm=None, # required: a dspy.LM, a bare model name or a cmpnd.HostedLM
|
|
450
483
|
lms=None, # optional: name -> dspy.LM, cmpnd.HostedLM or cmpnd.SystemOne
|
|
451
|
-
credential=None, #
|
|
484
|
+
credential=None, # the cmpnd.Credential every other binding spends, else the org's default, if one is set
|
|
452
485
|
max_metric_calls=None, # budget: the metric-call ceiling for the run
|
|
453
486
|
auto=None, # budget: "light", "medium" or "heavy"
|
|
454
487
|
may_author_code=None, # optional: False keeps each dspy.Flex at its deployed source
|
|
@@ -514,13 +547,33 @@ Deploy a source file under a program name, or optimize the program a file
|
|
|
514
547
|
declares:
|
|
515
548
|
|
|
516
549
|
```bash
|
|
517
|
-
cmpnd deploy program.py question-answerer
|
|
518
|
-
cmpnd optimize gepa task.py haiku --reflection-model openai/gpt-6-luna --auto light
|
|
550
|
+
cmpnd deploy program.py question-answerer --credential openai
|
|
551
|
+
cmpnd optimize gepa task.py haiku --credential openai --reflection-model openai/gpt-6-luna --auto light
|
|
519
552
|
```
|
|
520
553
|
|
|
521
554
|
`cmpnd deploy` uploads the file as written. `cmpnd optimize` reads `program`,
|
|
522
555
|
`trainset`, `valset` and `metric` from the file, deploys the program under the
|
|
523
|
-
program name and prints the best deployment ID.
|
|
556
|
+
program name and prints the best deployment ID. `--credential` names the
|
|
557
|
+
credential the program's models spend, and `cmpnd credentials list` shows the
|
|
558
|
+
names your organization holds.
|
|
559
|
+
|
|
560
|
+
`cmpnd programs rename PROGRAM NAME` gives a program a new name, or names one
|
|
561
|
+
that has none. PROGRAM is a program name or a `p_` id, and the program keeps
|
|
562
|
+
its id and its history. The old name is free at once, so update the code that
|
|
563
|
+
declares it.
|
|
564
|
+
|
|
565
|
+
A program calls tools on an MCP server once your organization seals the
|
|
566
|
+
server's key, registers the server and allows its tools:
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
cmpnd credentials create --kind mcp --server https://mcp.exa.ai/mcp --name exa-prod \
|
|
570
|
+
--placement query_param --query-param-name exaApiKey < exa-key.txt
|
|
571
|
+
cmpnd tool-servers create --url https://mcp.exa.ai/mcp --credential exa-prod
|
|
572
|
+
cmpnd tool-servers allow <server_id> web_search_exa
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
[`docs/cli.md`](docs/cli.md) describes every command, including "Tool
|
|
576
|
+
servers".
|
|
524
577
|
|
|
525
578
|
## Custom spans
|
|
526
579
|
|
|
@@ -60,13 +60,18 @@ class _LazyVersionAction(argparse.Action):
|
|
|
60
60
|
_EPILOG = """\
|
|
61
61
|
deploy-flow workflow (Docker-style; the path an agent should reach for first):
|
|
62
62
|
|
|
63
|
-
cmpnd
|
|
63
|
+
cmpnd credentials list # the credential names a deploy may spend
|
|
64
|
+
cmpnd deploy program.py qa --credential NAME --run '{"question": "..."}'
|
|
65
|
+
# deploy program name qa + smoke test
|
|
64
66
|
cmpnd ps # list deployments
|
|
65
67
|
cmpnd status <id> -f # wait for terminal state
|
|
66
68
|
cmpnd run <id> '{"...": "..."}' # invoke a ready deployment
|
|
67
69
|
cmpnd logs <id> # narrative timeline + traces
|
|
68
70
|
cmpnd inspect <id> # full JSON record
|
|
69
71
|
|
|
72
|
+
A deploy without --credential spends the organization's default credential, if
|
|
73
|
+
one is set.
|
|
74
|
+
|
|
70
75
|
answering a question (question-shaped flows, resolved in one or two calls):
|
|
71
76
|
|
|
72
77
|
"get the last 3 traces and tell me where it's slow"
|
|
@@ -1478,8 +1478,8 @@ def register(subparsers: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
1478
1478
|
"--credential",
|
|
1479
1479
|
metavar="NAME",
|
|
1480
1480
|
default=None,
|
|
1481
|
-
help="The provider credential the program's model spends
|
|
1482
|
-
"credential
|
|
1481
|
+
help="The provider credential the program's model spends, else the organization's default "
|
|
1482
|
+
"credential, if one is set. `cmpnd credentials list` shows the names",
|
|
1483
1483
|
)
|
|
1484
1484
|
dp.add_argument("--json", action="store_true", help="Emit --run output as JSON")
|
|
1485
1485
|
dp.set_defaults(func=_handler("deploy"))
|
|
@@ -1559,7 +1559,7 @@ def register(subparsers: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
1559
1559
|
metavar="NAME",
|
|
1560
1560
|
default=None,
|
|
1561
1561
|
help="The provider credential the run spends: the program's model, and every model that names no "
|
|
1562
|
-
"credential of its own
|
|
1562
|
+
"credential of its own. Else the organization's default credential, if one is set. "
|
|
1563
1563
|
"`cmpnd credentials list` shows the names",
|
|
1564
1564
|
)
|
|
1565
1565
|
opt.add_argument(
|
|
@@ -22,11 +22,12 @@ first time the organization uses the program name. The deployment carries that
|
|
|
22
22
|
id. A Python process that declares the same program name with
|
|
23
23
|
`cmpnd.Program(name, ...)` traces to the same program.
|
|
24
24
|
|
|
25
|
-
A deploy or an optimize with no program name warns
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
program name
|
|
25
|
+
A deploy or an optimize with no program name warns in the CLI. Serve then
|
|
26
|
+
refuses the deploy with a `400`, and the CLI reports an error that shows the
|
|
27
|
+
`cmpnd deploy SOURCE PROGRAM_NAME` form. An optimize with `--deployment-id`
|
|
28
|
+
needs no program name, because that deployment already has its program, and a
|
|
29
|
+
program name with it is refused when the file binds no program. In the shell,
|
|
30
|
+
`deploy()` and `optimize()` take the program name as `program=`.
|
|
30
31
|
|
|
31
32
|
The platform deploys and optimizes only a program a user named. A program name
|
|
32
33
|
given here, to `cmpnd.Program(name, ...)` or to `cmpnd programs rename` is one.
|
|
@@ -312,7 +313,8 @@ model and the field, never the value. Seal the key with
|
|
|
312
313
|
`cmpnd credentials create` instead.
|
|
313
314
|
|
|
314
315
|
`--credential NAME` names the provider credential the program's model spends.
|
|
315
|
-
Without it, the deployment spends the organization's default
|
|
316
|
+
Without it, the deployment spends the organization's default, if one is set,
|
|
317
|
+
and serve refuses the deploy when the organization has none. The CLI looks
|
|
316
318
|
the name up before it stages the source. A name the organization does not hold
|
|
317
319
|
fails with the names it does hold and the nearest one, and nothing is sent.
|
|
318
320
|
The platform checks the name again at the deploy, which catches a credential
|
|
@@ -684,16 +686,23 @@ server, the credential it uses and the allow-list of tools a deploy may name.
|
|
|
684
686
|
cmpnd tool-servers create --url https://mcp.exa.ai/mcp --credential exa-prod [--name exa]
|
|
685
687
|
cmpnd tool-servers list [--text]
|
|
686
688
|
cmpnd tool-servers show <server_id> [--text [--schemas]]
|
|
689
|
+
cmpnd tool-servers allow <server_id> [TOOL ...] [--all]
|
|
690
|
+
cmpnd tool-servers deny <server_id> [TOOL ...] [--all]
|
|
687
691
|
cmpnd tool-servers refresh <server_id>
|
|
688
692
|
cmpnd tool-servers delete <server_id> --force
|
|
689
693
|
```
|
|
690
694
|
|
|
691
695
|
`create` registers the server and has the platform list its tools. The
|
|
692
|
-
platform contacts the server, and the CLI never does.
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
696
|
+
platform contacts the server, and the CLI never does. Registering grants
|
|
697
|
+
nothing. `allow` names the tools a deploy may call, such as
|
|
698
|
+
`cmpnd tool-servers allow ts_ZdYFc5Zg2fGR web_search_exa`, and until an owner
|
|
699
|
+
runs it, the platform refuses a deploy that names a tool on the server.
|
|
700
|
+
`allow --all` grants every tool on the server, including tools it lists later.
|
|
701
|
+
`deny` withdraws named tools, and `deny --all` clears the standing grant and
|
|
702
|
+
every named one. `refresh` lists the tools again after a vendor changes
|
|
703
|
+
them. `list` and `show` print the API's JSON. With `--text`, `show` prints
|
|
704
|
+
each tool with its allow-list state and a one-line description, and
|
|
705
|
+
`--schemas` adds the reduced argument schema the platform enforces. `create`, `allow`, `deny` and `refresh` render the server
|
|
697
706
|
as it now stands, and `--json` prints the raw payload instead.
|
|
698
707
|
|
|
699
708
|
When the platform cannot list a server's tools because of the server itself,
|
|
@@ -773,9 +782,10 @@ organization must hold provider credentials for every model the run uses.
|
|
|
773
782
|
Named model declarations hold model names and sampling settings, and the CLI
|
|
774
783
|
refuses a provider key on them.
|
|
775
784
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
785
|
+
`--credential NAME` names the run's credential. The program's model spends
|
|
786
|
+
it, and so does every model that names no credential of its own. Without it,
|
|
787
|
+
those models spend the organization's default, if one is set, and serve
|
|
788
|
+
refuses the run when the organization has none.
|
|
779
789
|
`--reflection-credential NAME` names the credential the reflection model
|
|
780
790
|
spends. `--lm-credential BINDING=NAME` names the credential one model in the
|
|
781
791
|
file's `lms` spends, and repeats once per binding:
|
|
@@ -140,32 +140,44 @@ plain DSPy on its LM and traces nothing.
|
|
|
140
140
|
A client deploys, runs and optimizes on the platform with its own key and
|
|
141
141
|
endpoint. None of these reads the global config:
|
|
142
142
|
|
|
143
|
-
- `sdk.deploy_program(program, metric
|
|
144
|
-
`cmpnd.Program` and returns a
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
143
|
+
- `sdk.deploy_program(program, *, metric=None, timeout=300, metadata=None,
|
|
144
|
+
credential=None)` deploys a `cmpnd.Program` and returns a
|
|
145
|
+
`cmpnd.DeployedProgram`. `credential` is the `cmpnd.Credential` the
|
|
146
|
+
program's model spends, from `cmpnd.credentials.get(NAME)`. Without one, the
|
|
147
|
+
deployment spends the organization's default, if one is set, and the platform
|
|
148
|
+
refuses the deploy when the organization has none. `metadata` is a
|
|
149
|
+
JSON-serializable dict stored with the deployment record.
|
|
150
|
+
- `sdk.run_deployment(deployment, *, entrypoint=None, timeout=30,
|
|
151
|
+
metadata=None, tags=None, lm=None, **inputs)` runs one deployment and returns
|
|
152
|
+
a `dspy.Prediction`. `deployment` is a `DeployedProgram` or a deployment id.
|
|
153
|
+
`entrypoint` picks the module to run inside a deployment that holds more than
|
|
154
|
+
one. `metadata` and `tags` are `dict[str, str]` values the platform applies
|
|
155
|
+
to the run's root trace. The run spends the credential its deployment
|
|
156
|
+
recorded. A `program_name` among the inputs raises `TypeError` and names
|
|
157
|
+
`entrypoint=`.
|
|
150
158
|
- `sdk.submit_deployment_run`, `list_deployment_runs`, `get_deployment_run`,
|
|
151
159
|
`get_deployment_run_result` and `wait_deployment_run` submit, find and resume
|
|
152
160
|
runs without waiting in one call. `sdk.deployment_run_id(result)` reads the run
|
|
153
161
|
id of a prediction or an exception. `sdk.get_trace_id(result)` reads the
|
|
154
162
|
id of the run's root trace the same way, or returns `None` when serve named no
|
|
155
163
|
trace.
|
|
156
|
-
- `sdk.optimize_deployment(deployment, optimizer="gepa",
|
|
157
|
-
platform's optimization on a deployment and returns the best
|
|
164
|
+
- `sdk.optimize_deployment(deployment, optimizer="gepa", ..., credential=None)`
|
|
165
|
+
runs the platform's optimization on a deployment and returns the best
|
|
158
166
|
`DeployedProgram`, with `.score`. It never deploys. The program's model comes
|
|
159
|
-
from the deployment.
|
|
167
|
+
from the deployment. `credential` names the `cmpnd.Credential` every model
|
|
168
|
+
that names none spends, else the organization's default, if one is set.
|
|
160
169
|
|
|
161
170
|
A `DeployedProgram` is not callable: a run needs a client's account, so calling
|
|
162
171
|
one raises `TypeError` and names `run_deployment`. The platform finds a
|
|
163
172
|
deployment by its id within the caller's organization, so another account's
|
|
164
173
|
client gets a 404 for it.
|
|
165
174
|
|
|
166
|
-
`cmpnd.deploy()`, `cmpnd.
|
|
167
|
-
functions and `sdk.run_optimization()`
|
|
168
|
-
|
|
175
|
+
`cmpnd.deploy()`, `cmpnd.deploy_bundle()`, `cmpnd.execute()`,
|
|
176
|
+
`cmpnd.optimize()`, the top-level run functions and `sdk.run_optimization()`
|
|
177
|
+
raise a `TypeError` that names the call that replaces them.
|
|
178
|
+
`cmpnd.deploy_bundle()` names two: `cmpnd deploy SOURCE PROGRAM_NAME` for a
|
|
179
|
+
source file, and `cmpnd.Client().deploy_program(program)` for a
|
|
180
|
+
`cmpnd.Program`.
|
|
169
181
|
|
|
170
182
|
## Membership
|
|
171
183
|
|
|
@@ -9,13 +9,15 @@ The proposer does the rewriting. The platform supplies one by default, and
|
|
|
9
9
|
import generalizing_proposer
|
|
10
10
|
|
|
11
11
|
client = cmpnd.Client()
|
|
12
|
-
|
|
12
|
+
openai = cmpnd.credentials.get("openai") # a credential your organization sealed
|
|
13
|
+
deployment = client.deploy_program(cmpnd.Program("my-program", module=program, lm=lm), credential=openai)
|
|
13
14
|
client.optimize_deployment(
|
|
14
15
|
deployment,
|
|
15
16
|
optimizer="gepa",
|
|
16
17
|
trainset=train,
|
|
17
18
|
valset=val,
|
|
18
19
|
metric=my_metric,
|
|
20
|
+
credential=openai, # every model below spends it
|
|
19
21
|
proposer=generalizing_proposer.propose, # yours
|
|
20
22
|
lms={"proposer-lm": dspy.LM("openai/gpt-6-luna")}, # what it may spend
|
|
21
23
|
reflection_lm=dspy.LM("openai/gpt-6-luna"),
|