cmpnd 0.82.0__tar.gz → 0.84.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.
Files changed (409) hide show
  1. {cmpnd-0.82.0 → cmpnd-0.84.0}/AGENTS.md +7 -1
  2. {cmpnd-0.82.0 → cmpnd-0.84.0}/PKG-INFO +80 -27
  3. {cmpnd-0.82.0 → cmpnd-0.84.0}/README.md +79 -26
  4. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/callback.py +116 -21
  5. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/__init__.py +6 -1
  6. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/top.py +3 -3
  7. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/configuration.py +3 -3
  8. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/context.py +41 -2
  9. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/models.py +130 -6
  10. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/cli.md +24 -14
  11. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/client.md +25 -13
  12. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/custom-proposer.md +3 -1
  13. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/sdk-instrumentation.md +33 -8
  14. {cmpnd-0.82.0 → cmpnd-0.84.0}/examples/generalizing_proposer.py +3 -1
  15. cmpnd-0.84.0/examples/local_ollama.py +57 -0
  16. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/README.md +20 -3
  17. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/bodies.py +14 -7
  18. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/exporter_http.py +84 -47
  19. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/program_names.py +4 -29
  20. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/protocols.py +19 -1
  21. cmpnd-0.84.0/ingest/cmpnd_ingest/span_context.py +63 -0
  22. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/trace_facts.py +4 -0
  23. {cmpnd-0.82.0 → cmpnd-0.84.0}/pyproject.toml +1 -1
  24. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/test-in-linux.sh +18 -4
  25. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/rlm_shape.py +4 -0
  26. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/test_rlm_shape.py +3 -1
  27. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/span_reference_fixture.py +9 -1
  28. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_callback.py +6 -2
  29. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_context.py +20 -0
  30. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_credential_kwargs.py +1 -1
  31. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_credential_selection.py +1 -1
  32. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_exporter_program_names.py +7 -4
  33. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_program_identity.py +2 -2
  34. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_span_references.py +18 -0
  35. cmpnd-0.84.0/tests/test_span_submission.py +492 -0
  36. cmpnd-0.84.0/tests/test_span_submission_wire_contract.py +190 -0
  37. {cmpnd-0.82.0 → cmpnd-0.84.0}/uv.lock +1 -1
  38. cmpnd-0.82.0/examples/local_ollama.py +0 -48
  39. {cmpnd-0.82.0 → cmpnd-0.84.0}/.gitignore +0 -0
  40. {cmpnd-0.82.0 → cmpnd-0.84.0}/CLAUDE.md +0 -0
  41. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/__init__.py +0 -0
  42. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_assessments.py +0 -0
  43. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_authored_import.py +0 -0
  44. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_deployments.py +0 -0
  45. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_exporter_pool.py +0 -0
  46. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_gepa_patch.py +0 -0
  47. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_http.py +0 -0
  48. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_program_patch.py +0 -0
  49. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_rlm_patch.py +0 -0
  50. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_runtime_tools.py +0 -0
  51. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_timespec.py +0 -0
  52. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_traces.py +0 -0
  53. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/_valsets.py +0 -0
  54. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/authored.py +0 -0
  55. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/api_client.py +0 -0
  56. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/__init__.py +0 -0
  57. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/admin.py +0 -0
  58. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/assessments.py +0 -0
  59. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/auth.py +0 -0
  60. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/datasets.py +0 -0
  61. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/deployments.py +0 -0
  62. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/evals.py +0 -0
  63. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/login.py +0 -0
  64. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/optimizations.py +0 -0
  65. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/org.py +0 -0
  66. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/programs.py +0 -0
  67. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  68. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  69. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/traces.py +0 -0
  70. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/commands/valsets.py +0 -0
  71. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/credentials.py +0 -0
  72. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/deprecation.py +0 -0
  73. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/pagination.py +0 -0
  74. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/shell.py +0 -0
  75. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/trace_render.py +0 -0
  76. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/tree_help.py +0 -0
  77. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/verbs.py +0 -0
  78. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/cli/views.py +0 -0
  79. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/client.py +0 -0
  80. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/credentials.py +0 -0
  81. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/dataset_sync.py +0 -0
  82. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/datasets.py +0 -0
  83. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/decorators.py +0 -0
  84. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/deployment.py +0 -0
  85. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/deployment_metadata.py +0 -0
  86. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/deployment_runs.py +0 -0
  87. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/eval_handler.py +0 -0
  88. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/execution.py +0 -0
  89. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/exporter.py +0 -0
  90. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/exporter_http.py +0 -0
  91. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/helpers.py +0 -0
  92. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/identity.py +0 -0
  93. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/imaging.py +0 -0
  94. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/__init__.py +0 -0
  95. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/decode.py +0 -0
  96. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/encode.py +0 -0
  97. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/hash.py +0 -0
  98. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/program.py +0 -0
  99. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/reflection.py +0 -0
  100. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/types.py +0 -0
  101. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/ir/xxh64.py +0 -0
  102. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/lm_configuration.py +0 -0
  103. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/mcp_servers.py +0 -0
  104. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/named_programs.py +0 -0
  105. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/optimization.py +0 -0
  106. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/optimizers/__init__.py +0 -0
  107. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/optimizers/gepa.py +0 -0
  108. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  109. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/optimizers/resume.py +0 -0
  110. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/optimizers/tracker.py +0 -0
  111. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/packaging.py +0 -0
  112. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/program_naming.py +0 -0
  113. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/programs.py +0 -0
  114. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/references.py +0 -0
  115. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/retry.py +0 -0
  116. {cmpnd-0.82.0 → cmpnd-0.84.0}/cmpnd/traces.py +0 -0
  117. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/2026-04-02-code-review.md +0 -0
  118. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  119. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  120. {cmpnd-0.82.0 → cmpnd-0.84.0}/docs/reading-traces.md +0 -0
  121. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/LINEAGE.md +0 -0
  122. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  123. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  124. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/py.typed +0 -0
  125. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  126. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/cmpnd_ingest/retry.py +0 -0
  127. {cmpnd-0.82.0 → cmpnd-0.84.0}/ingest/pyproject.toml +0 -0
  128. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/audit-sdist.sh +0 -0
  129. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/capture_review_run.py +0 -0
  130. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/check-pip-install.sh +0 -0
  131. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/check_release_artifacts.py +0 -0
  132. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/fixtures/review_run.json.gz +0 -0
  133. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/gepa_resume_bug.py +0 -0
  134. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/install-test-env.sh +0 -0
  135. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/release-gate.sh +0 -0
  136. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/release-real-models.sh +0 -0
  137. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/require_version_bump.py +0 -0
  138. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/seed_review_run.py +0 -0
  139. {cmpnd-0.82.0 → cmpnd-0.84.0}/scripts/selfhost_compat.py +0 -0
  140. {cmpnd-0.82.0 → cmpnd-0.84.0}/stubs/dspy/__init__.pyi +0 -0
  141. {cmpnd-0.82.0 → cmpnd-0.84.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  142. {cmpnd-0.82.0 → cmpnd-0.84.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  143. {cmpnd-0.82.0 → cmpnd-0.84.0}/stubs/dspy/utils/__init__.pyi +0 -0
  144. {cmpnd-0.82.0 → cmpnd-0.84.0}/stubs/dspy/utils/callback.pyi +0 -0
  145. {cmpnd-0.82.0 → cmpnd-0.84.0}/stubs/dspy/utils/dummies.pyi +0 -0
  146. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/__init__.py +0 -0
  147. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_credential_route.py +0 -0
  148. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_deployment_signature_helpers.py +0 -0
  149. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_exporter_helpers.py +0 -0
  150. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_fake_clock.py +0 -0
  151. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_identity_helpers.py +0 -0
  152. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_resolve_refs.py +0 -0
  153. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/_traced_run.py +0 -0
  154. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/conftest.py +0 -0
  155. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/__init__.py +0 -0
  156. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/committee_task.py +0 -0
  157. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/conftest.py +0 -0
  158. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/continuation_task.py +0 -0
  159. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  160. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  161. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/fake_lm.py +0 -0
  162. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/helpers.py +0 -0
  163. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/target_capabilities.py +0 -0
  164. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_assessments_cli.py +0 -0
  165. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_capture_prompts.py +0 -0
  166. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_composite_module.py +0 -0
  167. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  168. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_deploy_execute.py +0 -0
  169. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_deploy_pandas.py +0 -0
  170. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_deploy_programs.py +0 -0
  171. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_edge_cases.py +0 -0
  172. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_example_hash.py +0 -0
  173. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_gepa_optimization.py +0 -0
  174. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_interpreter_spans.py +0 -0
  175. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_lm_accuracy.py +0 -0
  176. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_module_tracing.py +0 -0
  177. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimization_lineage.py +0 -0
  178. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  179. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
  180. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_continuation.py +0 -0
  181. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
  182. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_failures.py +0 -0
  183. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_loop.py +0 -0
  184. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  185. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
  186. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_parallel_export.py +0 -0
  187. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_project_attribution.py +0 -0
  188. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_react_tool_spans.py +0 -0
  189. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_save_load.py +0 -0
  190. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_trace_structure.py +0 -0
  191. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_traces_read.py +0 -0
  192. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_user_attribution.py +0 -0
  193. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/e2e/test_valsets_cli.py +0 -0
  194. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  195. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  196. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  197. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  198. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  199. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  200. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  201. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  202. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  203. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/10_react.json +0 -0
  204. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/11_refine.json +0 -0
  205. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/12_retrieve.json +0 -0
  206. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/13_knn.json +0 -0
  207. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/14_parallel.json +0 -0
  208. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/identity_vectors/README.md +0 -0
  209. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/ingest_conformance.py +0 -0
  210. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/__init__.py +0 -0
  211. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/authored_optimize/judge.py +0 -0
  212. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  213. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/conftest.py +0 -0
  214. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
  215. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/hosted_optimize_probe.py +0 -0
  216. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/optimization_run_probe.py +0 -0
  217. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  218. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/test_logs_renders_traces.py +0 -0
  219. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/test_optimization_run.py +0 -0
  220. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/test_optimizing_progress.py +0 -0
  221. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/integration/test_unhappy_path.py +0 -0
  222. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/__init__.py +0 -0
  223. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/__main__.py +0 -0
  224. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/drain.py +0 -0
  225. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/ingest.py +0 -0
  226. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/latency_transport.py +0 -0
  227. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/rlm_size_report.py +0 -0
  228. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/sweep.py +0 -0
  229. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/load/test_rlm_size_report.py +0 -0
  230. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/__init__.py +0 -0
  231. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/conftest.py +0 -0
  232. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/seed_parity.py +0 -0
  233. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_auth.py +0 -0
  234. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_datasets.py +0 -0
  235. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_deployments.py +0 -0
  236. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_evals.py +0 -0
  237. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_health.py +0 -0
  238. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_modules.py +0 -0
  239. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_optimizations.py +0 -0
  240. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_programs.py +0 -0
  241. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_signatures.py +0 -0
  242. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_trace_streaming.py +0 -0
  243. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/parity/test_traces.py +0 -0
  244. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/__init__.py +0 -0
  245. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/_provider.py +0 -0
  246. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/_readiness.py +0 -0
  247. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/_reliability.py +0 -0
  248. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/_result.py +0 -0
  249. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/mint_bedrock_token.py +0 -0
  250. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_bedrock_converse.py +0 -0
  251. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_deploy_programs.py +0 -0
  252. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_multi_client_stress.py +0 -0
  253. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_optimize_client_committee.py +0 -0
  254. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_optimize_continuation.py +0 -0
  255. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_optimize_loop.py +0 -0
  256. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
  257. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_optimize_stress.py +0 -0
  258. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_provider_roles.py +0 -0
  259. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_readiness.py +0 -0
  260. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_real_provider_twins.py +0 -0
  261. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_reliability.py +0 -0
  262. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_reliability_classify.py +0 -0
  263. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_rlm_wasm.py +0 -0
  264. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/real_models/test_trace_search.py +0 -0
  265. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_adapter_reentrancy.py +0 -0
  266. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_assessments_api.py +0 -0
  267. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_authored.py +0 -0
  268. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_authored_binding_credentials.py +0 -0
  269. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_authored_bundle_collisions.py +0 -0
  270. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_authored_metric_contract.py +0 -0
  271. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_authored_named_models.py +0 -0
  272. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_authored_optimize.py +0 -0
  273. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_candidate_lineage.py +0 -0
  274. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/__init__.py +0 -0
  275. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/conftest.py +0 -0
  276. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_admin.py +0 -0
  277. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_api_client.py +0 -0
  278. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_assessments.py +0 -0
  279. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_auth.py +0 -0
  280. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_credentials.py +0 -0
  281. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_datasets.py +0 -0
  282. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_deployment_runs.py +0 -0
  283. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_deployments.py +0 -0
  284. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_evals.py +0 -0
  285. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_login.py +0 -0
  286. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_main.py +0 -0
  287. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_optimizations.py +0 -0
  288. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_org.py +0 -0
  289. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_pagination.py +0 -0
  290. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_parity.py +0 -0
  291. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_programs.py +0 -0
  292. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_provider_credentials.py +0 -0
  293. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_schema_sample.py +0 -0
  294. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_shell.py +0 -0
  295. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_tool_servers.py +0 -0
  296. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_top.py +0 -0
  297. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_traces.py +0 -0
  298. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
  299. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  300. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_tree_help.py +0 -0
  301. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cli/test_valsets.py +0 -0
  302. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_client.py +0 -0
  303. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_client_floor.py +0 -0
  304. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_client_program_names.py +0 -0
  305. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_clustering/__init__.py +0 -0
  306. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_clustering/conftest.py +0 -0
  307. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_clustering/test_edge_cases.py +0 -0
  308. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  309. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_clustering/test_type_conversion.py +0 -0
  310. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_cmp551_grouping_identity.py +0 -0
  311. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_configuration.py +0 -0
  312. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_context_propagation.py +0 -0
  313. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_credential_values.py +0 -0
  314. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_dataset_polling.py +0 -0
  315. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_dataset_sync.py +0 -0
  316. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_datasets.py +0 -0
  317. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_decision_client_spans.py +0 -0
  318. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_decorators.py +0 -0
  319. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_deploy.py +0 -0
  320. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_deploy_mcp_tool_references.py +0 -0
  321. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_deploy_program_id.py +0 -0
  322. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_deployment_metadata.py +0 -0
  323. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_deployment_runs.py +0 -0
  324. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_deployments_read.py +0 -0
  325. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_eval.py +0 -0
  326. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_eval_example_attribution.py +0 -0
  327. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_eval_program_id.py +0 -0
  328. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_eval_start.py +0 -0
  329. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_eval_trace_grouping.py +0 -0
  330. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_exception_paths.py +0 -0
  331. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_execute.py +0 -0
  332. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_execute_run_identity.py +0 -0
  333. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_exporter.py +0 -0
  334. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_exporter_queue.py +0 -0
  335. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_exporter_real.py +0 -0
  336. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_fake_lm.py +0 -0
  337. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_gepa_callback.py +0 -0
  338. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_gepa_integration.py +0 -0
  339. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_gepa_output_normalization.py +0 -0
  340. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_gepa_resume.py +0 -0
  341. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_identity.py +0 -0
  342. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_imaging.py +0 -0
  343. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_import_weight.py +0 -0
  344. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_ingest_conformance.py +0 -0
  345. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_ingest_second_producer.py +0 -0
  346. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_integration.py +0 -0
  347. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_interpreter_callback.py +0 -0
  348. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_ir_encoder_properties.py +0 -0
  349. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_ir_golden_vectors.py +0 -0
  350. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_ir_roundtrip.py +0 -0
  351. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_lm15_native_calls.py +0 -0
  352. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_lm_configuration.py +0 -0
  353. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_lm_usage_shapes.py +0 -0
  354. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_mcp_tools.py +0 -0
  355. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_models.py +0 -0
  356. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_multi_client_stress_readiness.py +0 -0
  357. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_no_signature_hash_on_the_wire.py +0 -0
  358. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimization_phase_callback.py +0 -0
  359. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimization_program_names.py +0 -0
  360. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimization_progress.py +0 -0
  361. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimization_start.py +0 -0
  362. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize.py +0 -0
  363. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize_budget.py +0 -0
  364. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize_lift.py +0 -0
  365. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize_lms.py +0 -0
  366. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize_proposer.py +0 -0
  367. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize_reflection_lm.py +0 -0
  368. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_optimize_terminal_failure.py +0 -0
  369. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_packaging.py +0 -0
  370. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_packaging_callable_source.py +0 -0
  371. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_packaging_mcp_tools.py +0 -0
  372. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_packaging_program_source.py +0 -0
  373. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_poll_until.py +0 -0
  374. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_program_id_deprecation.py +0 -0
  375. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_program_lineage_persist.py +0 -0
  376. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_program_names_in_deploy.py +0 -0
  377. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_program_naming.py +0 -0
  378. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_programs_create.py +0 -0
  379. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_project_payload.py +0 -0
  380. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_real_provider_twins_readiness.py +0 -0
  381. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_reflector_properties.py +0 -0
  382. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_reflector_smoke.py +0 -0
  383. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_release_gate_script.py +0 -0
  384. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_release_real_models_script.py +0 -0
  385. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_replaced_names.py +0 -0
  386. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_repro_reactv2_bugs.py +0 -0
  387. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_require_version_bump.py +0 -0
  388. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_retry.py +0 -0
  389. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_reversible_failures.py +0 -0
  390. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_rlm_patch.py +0 -0
  391. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_run_attribution_paths.py +0 -0
  392. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_runtime_tools.py +0 -0
  393. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_schemas.py +0 -0
  394. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_seal_lm_credential.py +0 -0
  395. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_seed_review_run.py +0 -0
  396. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_signature_inputs.py +0 -0
  397. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_span_sent_once.py +0 -0
  398. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_system_one.py +0 -0
  399. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_trace_context_concurrency.py +0 -0
  400. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_trace_fact_wire_contract.py +0 -0
  401. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_trace_facts.py +0 -0
  402. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_trace_render.py +0 -0
  403. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_traces_read.py +0 -0
  404. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_tracked_gepa.py +0 -0
  405. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_tracker_enrich.py +0 -0
  406. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_truncation.py +0 -0
  407. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_upload_auth_headers.py +0 -0
  408. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_valsets_api.py +0 -0
  409. {cmpnd-0.82.0 → cmpnd-0.84.0}/tests/test_xxh64.py +0 -0
@@ -137,7 +137,13 @@ still install against the `dspy>=…` floor in `dependencies`.
137
137
  - `scripts/install-test-env.sh <python> <dspy>` builds `.venv` from one group's
138
138
  locked tree, as each `sdk-test` leg in `ci-sdk.yml` does. From the repo root,
139
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
140
+ `.venv/bin/python -m pytest tests/ -k "not e2e"`. The root recipe
141
+ `SDK_TEST_PYTHON_VERSION=3.13 SDK_TEST_DSPY_VERSION=3.4.0 just sdk-test-linux`
142
+ runs the same locked environment in Linux. `SDK_TEST_LINUX_IMAGE` selects a
143
+ pinned CI builder when reproducing a job. The helper copies the worker pins
144
+ and truncation vectors and mounts Git metadata read-only for revision tests.
145
+ The revision tests require Git, which the CI builder provides.
146
+ `uv sync --extra dev` in
141
147
  `python-sdk/` returns to the default group.
142
148
  - `--latest` resolves every package fresh, as a user's install today would.
143
149
  With the DSPy version `newest` it pins no DSPy either. The daily
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.82.0
3
+ Version: 0.84.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 self-hosted cmpnd install, also
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(api_key="ck_xxx")
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
- - Without `credential=`, the deployment spends the organization's default,
225
- which an owner sets with `cmpnd credentials default NAME`.
226
- - The deployment records the credential's name. Each call spends the newest
227
- credential sealed under that name, so an owner who rotates a key needs no
228
- redeploy.
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 and make it the default:
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
- deployed = sdk.deploy_program(qa) # spends the default credential, openai
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 the same file from the
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, # optional: a cmpnd.Credential the program's model spends
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(api_key="ck_xxx")
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, or the organization's default. The
433
- platform refuses a credential whose endpoint does not serve a binding's
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, # optional: the cmpnd.Credential every other binding spends
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
 
@@ -632,7 +685,7 @@ cmpnd.configure(
632
685
  flush_interval_seconds=5.0, # optional: seconds between flushes
633
686
  capture_inputs=True, # optional: record span inputs
634
687
  capture_outputs=True, # optional: record span outputs
635
- default_tags={"env": "prod"}, # optional: tags on every trace
688
+ default_tags={"env": "prod"}, # optional: tags on every trace; a run's own tags override them
636
689
  )
637
690
  ```
638
691
 
@@ -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 self-hosted cmpnd install, also
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(api_key="ck_xxx")
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
- - Without `credential=`, the deployment spends the organization's default,
174
- which an owner sets with `cmpnd credentials default NAME`.
175
- - The deployment records the credential's name. Each call spends the newest
176
- credential sealed under that name, so an owner who rotates a key needs no
177
- redeploy.
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 and make it the default:
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
- deployed = sdk.deploy_program(qa) # spends the default credential, openai
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 the same file from the
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, # optional: a cmpnd.Credential the program's model spends
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(api_key="ck_xxx")
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, or the organization's default. The
382
- platform refuses a credential whose endpoint does not serve a binding's
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, # optional: the cmpnd.Credential every other binding spends
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
 
@@ -581,7 +634,7 @@ cmpnd.configure(
581
634
  flush_interval_seconds=5.0, # optional: seconds between flushes
582
635
  capture_inputs=True, # optional: record span inputs
583
636
  capture_outputs=True, # optional: record span outputs
584
- default_tags={"env": "prod"}, # optional: tags on every trace
637
+ default_tags={"env": "prod"}, # optional: tags on every trace; a run's own tags override them
585
638
  )
586
639
  ```
587
640