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.
Files changed (406) hide show
  1. {cmpnd-0.82.0 → cmpnd-0.83.0}/PKG-INFO +79 -26
  2. {cmpnd-0.82.0 → cmpnd-0.83.0}/README.md +78 -25
  3. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/__init__.py +6 -1
  4. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/top.py +3 -3
  5. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/cli.md +24 -14
  6. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/client.md +25 -13
  7. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/custom-proposer.md +3 -1
  8. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/sdk-instrumentation.md +7 -3
  9. {cmpnd-0.82.0 → cmpnd-0.83.0}/examples/generalizing_proposer.py +3 -1
  10. cmpnd-0.83.0/examples/local_ollama.py +57 -0
  11. {cmpnd-0.82.0 → cmpnd-0.83.0}/pyproject.toml +1 -1
  12. {cmpnd-0.82.0 → cmpnd-0.83.0}/uv.lock +1 -1
  13. cmpnd-0.82.0/examples/local_ollama.py +0 -48
  14. {cmpnd-0.82.0 → cmpnd-0.83.0}/.gitignore +0 -0
  15. {cmpnd-0.82.0 → cmpnd-0.83.0}/AGENTS.md +0 -0
  16. {cmpnd-0.82.0 → cmpnd-0.83.0}/CLAUDE.md +0 -0
  17. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/__init__.py +0 -0
  18. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_assessments.py +0 -0
  19. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_authored_import.py +0 -0
  20. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_deployments.py +0 -0
  21. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_exporter_pool.py +0 -0
  22. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_gepa_patch.py +0 -0
  23. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_http.py +0 -0
  24. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_program_patch.py +0 -0
  25. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_rlm_patch.py +0 -0
  26. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_runtime_tools.py +0 -0
  27. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_timespec.py +0 -0
  28. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_traces.py +0 -0
  29. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/_valsets.py +0 -0
  30. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/authored.py +0 -0
  31. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/callback.py +0 -0
  32. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/api_client.py +0 -0
  33. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/__init__.py +0 -0
  34. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/admin.py +0 -0
  35. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/assessments.py +0 -0
  36. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/auth.py +0 -0
  37. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/datasets.py +0 -0
  38. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/deployments.py +0 -0
  39. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/evals.py +0 -0
  40. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/login.py +0 -0
  41. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/optimizations.py +0 -0
  42. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/org.py +0 -0
  43. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/programs.py +0 -0
  44. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  45. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  46. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/traces.py +0 -0
  47. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/commands/valsets.py +0 -0
  48. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/credentials.py +0 -0
  49. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/deprecation.py +0 -0
  50. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/pagination.py +0 -0
  51. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/shell.py +0 -0
  52. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/trace_render.py +0 -0
  53. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/tree_help.py +0 -0
  54. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/verbs.py +0 -0
  55. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/cli/views.py +0 -0
  56. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/client.py +0 -0
  57. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/configuration.py +0 -0
  58. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/context.py +0 -0
  59. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/credentials.py +0 -0
  60. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/dataset_sync.py +0 -0
  61. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/datasets.py +0 -0
  62. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/decorators.py +0 -0
  63. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/deployment.py +0 -0
  64. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/deployment_metadata.py +0 -0
  65. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/deployment_runs.py +0 -0
  66. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/eval_handler.py +0 -0
  67. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/execution.py +0 -0
  68. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/exporter.py +0 -0
  69. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/exporter_http.py +0 -0
  70. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/helpers.py +0 -0
  71. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/identity.py +0 -0
  72. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/imaging.py +0 -0
  73. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/__init__.py +0 -0
  74. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/decode.py +0 -0
  75. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/encode.py +0 -0
  76. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/hash.py +0 -0
  77. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/program.py +0 -0
  78. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/reflection.py +0 -0
  79. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/types.py +0 -0
  80. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/ir/xxh64.py +0 -0
  81. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/lm_configuration.py +0 -0
  82. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/mcp_servers.py +0 -0
  83. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/models.py +0 -0
  84. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/named_programs.py +0 -0
  85. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimization.py +0 -0
  86. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/__init__.py +0 -0
  87. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/gepa.py +0 -0
  88. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  89. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/resume.py +0 -0
  90. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/optimizers/tracker.py +0 -0
  91. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/packaging.py +0 -0
  92. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/program_naming.py +0 -0
  93. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/programs.py +0 -0
  94. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/references.py +0 -0
  95. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/retry.py +0 -0
  96. {cmpnd-0.82.0 → cmpnd-0.83.0}/cmpnd/traces.py +0 -0
  97. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/2026-04-02-code-review.md +0 -0
  98. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  99. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  100. {cmpnd-0.82.0 → cmpnd-0.83.0}/docs/reading-traces.md +0 -0
  101. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/LINEAGE.md +0 -0
  102. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/README.md +0 -0
  103. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  104. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  105. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  106. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  107. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  108. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  109. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/py.typed +0 -0
  110. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  111. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/retry.py +0 -0
  112. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  113. {cmpnd-0.82.0 → cmpnd-0.83.0}/ingest/pyproject.toml +0 -0
  114. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/audit-sdist.sh +0 -0
  115. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/capture_review_run.py +0 -0
  116. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/check-pip-install.sh +0 -0
  117. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/check_release_artifacts.py +0 -0
  118. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/fixtures/review_run.json.gz +0 -0
  119. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/gepa_resume_bug.py +0 -0
  120. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/install-test-env.sh +0 -0
  121. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/release-gate.sh +0 -0
  122. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/release-real-models.sh +0 -0
  123. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/require_version_bump.py +0 -0
  124. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/seed_review_run.py +0 -0
  125. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/selfhost_compat.py +0 -0
  126. {cmpnd-0.82.0 → cmpnd-0.83.0}/scripts/test-in-linux.sh +0 -0
  127. {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/__init__.pyi +0 -0
  128. {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  129. {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  130. {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/utils/__init__.pyi +0 -0
  131. {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/utils/callback.pyi +0 -0
  132. {cmpnd-0.82.0 → cmpnd-0.83.0}/stubs/dspy/utils/dummies.pyi +0 -0
  133. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/__init__.py +0 -0
  134. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_credential_route.py +0 -0
  135. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_deployment_signature_helpers.py +0 -0
  136. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_exporter_helpers.py +0 -0
  137. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_fake_clock.py +0 -0
  138. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_identity_helpers.py +0 -0
  139. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_resolve_refs.py +0 -0
  140. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/_traced_run.py +0 -0
  141. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/conftest.py +0 -0
  142. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/__init__.py +0 -0
  143. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/committee_task.py +0 -0
  144. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/conftest.py +0 -0
  145. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/continuation_task.py +0 -0
  146. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  147. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  148. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/fake_lm.py +0 -0
  149. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/helpers.py +0 -0
  150. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/target_capabilities.py +0 -0
  151. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_assessments_cli.py +0 -0
  152. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_capture_prompts.py +0 -0
  153. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_composite_module.py +0 -0
  154. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  155. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_deploy_execute.py +0 -0
  156. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_deploy_pandas.py +0 -0
  157. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_deploy_programs.py +0 -0
  158. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_edge_cases.py +0 -0
  159. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_example_hash.py +0 -0
  160. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_gepa_optimization.py +0 -0
  161. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_interpreter_spans.py +0 -0
  162. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_lm_accuracy.py +0 -0
  163. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_module_tracing.py +0 -0
  164. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimization_lineage.py +0 -0
  165. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  166. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
  167. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_continuation.py +0 -0
  168. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
  169. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_failures.py +0 -0
  170. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_loop.py +0 -0
  171. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  172. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
  173. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_parallel_export.py +0 -0
  174. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_project_attribution.py +0 -0
  175. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_react_tool_spans.py +0 -0
  176. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_save_load.py +0 -0
  177. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_trace_structure.py +0 -0
  178. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_traces_read.py +0 -0
  179. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_user_attribution.py +0 -0
  180. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/e2e/test_valsets_cli.py +0 -0
  181. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  182. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  183. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  184. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  185. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  186. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  187. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  188. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  189. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  190. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/10_react.json +0 -0
  191. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/11_refine.json +0 -0
  192. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/12_retrieve.json +0 -0
  193. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/13_knn.json +0 -0
  194. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/14_parallel.json +0 -0
  195. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/identity_vectors/README.md +0 -0
  196. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/ingest_conformance.py +0 -0
  197. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/__init__.py +0 -0
  198. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/authored_optimize/judge.py +0 -0
  199. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  200. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/conftest.py +0 -0
  201. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
  202. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/hosted_optimize_probe.py +0 -0
  203. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/optimization_run_probe.py +0 -0
  204. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  205. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_logs_renders_traces.py +0 -0
  206. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_optimization_run.py +0 -0
  207. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_optimizing_progress.py +0 -0
  208. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/integration/test_unhappy_path.py +0 -0
  209. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/__init__.py +0 -0
  210. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/__main__.py +0 -0
  211. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/drain.py +0 -0
  212. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/ingest.py +0 -0
  213. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/latency_transport.py +0 -0
  214. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/rlm_shape.py +0 -0
  215. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/rlm_size_report.py +0 -0
  216. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/sweep.py +0 -0
  217. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/test_rlm_shape.py +0 -0
  218. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/load/test_rlm_size_report.py +0 -0
  219. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/__init__.py +0 -0
  220. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/conftest.py +0 -0
  221. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/seed_parity.py +0 -0
  222. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_auth.py +0 -0
  223. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_datasets.py +0 -0
  224. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_deployments.py +0 -0
  225. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_evals.py +0 -0
  226. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_health.py +0 -0
  227. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_modules.py +0 -0
  228. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_optimizations.py +0 -0
  229. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_programs.py +0 -0
  230. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_signatures.py +0 -0
  231. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_trace_streaming.py +0 -0
  232. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/parity/test_traces.py +0 -0
  233. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/__init__.py +0 -0
  234. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_provider.py +0 -0
  235. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_readiness.py +0 -0
  236. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_reliability.py +0 -0
  237. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/_result.py +0 -0
  238. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/mint_bedrock_token.py +0 -0
  239. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_bedrock_converse.py +0 -0
  240. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_deploy_programs.py +0 -0
  241. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_multi_client_stress.py +0 -0
  242. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_client_committee.py +0 -0
  243. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_continuation.py +0 -0
  244. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_loop.py +0 -0
  245. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
  246. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_optimize_stress.py +0 -0
  247. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_provider_roles.py +0 -0
  248. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_readiness.py +0 -0
  249. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_real_provider_twins.py +0 -0
  250. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_reliability.py +0 -0
  251. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_reliability_classify.py +0 -0
  252. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_rlm_wasm.py +0 -0
  253. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/real_models/test_trace_search.py +0 -0
  254. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/span_reference_fixture.py +0 -0
  255. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_adapter_reentrancy.py +0 -0
  256. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_assessments_api.py +0 -0
  257. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored.py +0 -0
  258. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_binding_credentials.py +0 -0
  259. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_bundle_collisions.py +0 -0
  260. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_metric_contract.py +0 -0
  261. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_named_models.py +0 -0
  262. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_authored_optimize.py +0 -0
  263. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_callback.py +0 -0
  264. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_candidate_lineage.py +0 -0
  265. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/__init__.py +0 -0
  266. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/conftest.py +0 -0
  267. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_admin.py +0 -0
  268. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_api_client.py +0 -0
  269. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_assessments.py +0 -0
  270. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_auth.py +0 -0
  271. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_credentials.py +0 -0
  272. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_datasets.py +0 -0
  273. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_deployment_runs.py +0 -0
  274. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_deployments.py +0 -0
  275. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_evals.py +0 -0
  276. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_login.py +0 -0
  277. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_main.py +0 -0
  278. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_optimizations.py +0 -0
  279. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_org.py +0 -0
  280. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_pagination.py +0 -0
  281. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_parity.py +0 -0
  282. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_programs.py +0 -0
  283. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_provider_credentials.py +0 -0
  284. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_schema_sample.py +0 -0
  285. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_shell.py +0 -0
  286. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_tool_servers.py +0 -0
  287. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_top.py +0 -0
  288. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_traces.py +0 -0
  289. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
  290. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  291. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_tree_help.py +0 -0
  292. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cli/test_valsets.py +0 -0
  293. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_client.py +0 -0
  294. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_client_floor.py +0 -0
  295. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_client_program_names.py +0 -0
  296. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/__init__.py +0 -0
  297. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/conftest.py +0 -0
  298. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/test_edge_cases.py +0 -0
  299. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  300. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_clustering/test_type_conversion.py +0 -0
  301. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_cmp551_grouping_identity.py +0 -0
  302. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_configuration.py +0 -0
  303. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_context.py +0 -0
  304. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_context_propagation.py +0 -0
  305. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_credential_kwargs.py +0 -0
  306. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_credential_selection.py +0 -0
  307. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_credential_values.py +0 -0
  308. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_dataset_polling.py +0 -0
  309. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_dataset_sync.py +0 -0
  310. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_datasets.py +0 -0
  311. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_decision_client_spans.py +0 -0
  312. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_decorators.py +0 -0
  313. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deploy.py +0 -0
  314. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deploy_mcp_tool_references.py +0 -0
  315. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deploy_program_id.py +0 -0
  316. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deployment_metadata.py +0 -0
  317. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deployment_runs.py +0 -0
  318. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_deployments_read.py +0 -0
  319. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval.py +0 -0
  320. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_example_attribution.py +0 -0
  321. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_program_id.py +0 -0
  322. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_start.py +0 -0
  323. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_eval_trace_grouping.py +0 -0
  324. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exception_paths.py +0 -0
  325. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_execute.py +0 -0
  326. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_execute_run_identity.py +0 -0
  327. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter.py +0 -0
  328. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter_program_names.py +0 -0
  329. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter_queue.py +0 -0
  330. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_exporter_real.py +0 -0
  331. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_fake_lm.py +0 -0
  332. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_callback.py +0 -0
  333. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_integration.py +0 -0
  334. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_output_normalization.py +0 -0
  335. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_gepa_resume.py +0 -0
  336. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_identity.py +0 -0
  337. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_imaging.py +0 -0
  338. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_import_weight.py +0 -0
  339. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ingest_conformance.py +0 -0
  340. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ingest_second_producer.py +0 -0
  341. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_integration.py +0 -0
  342. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_interpreter_callback.py +0 -0
  343. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ir_encoder_properties.py +0 -0
  344. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ir_golden_vectors.py +0 -0
  345. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_ir_roundtrip.py +0 -0
  346. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_lm15_native_calls.py +0 -0
  347. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_lm_configuration.py +0 -0
  348. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_lm_usage_shapes.py +0 -0
  349. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_mcp_tools.py +0 -0
  350. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_models.py +0 -0
  351. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_multi_client_stress_readiness.py +0 -0
  352. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_no_signature_hash_on_the_wire.py +0 -0
  353. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_phase_callback.py +0 -0
  354. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_program_names.py +0 -0
  355. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_progress.py +0 -0
  356. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimization_start.py +0 -0
  357. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize.py +0 -0
  358. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_budget.py +0 -0
  359. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_lift.py +0 -0
  360. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_lms.py +0 -0
  361. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_proposer.py +0 -0
  362. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_reflection_lm.py +0 -0
  363. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_optimize_terminal_failure.py +0 -0
  364. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging.py +0 -0
  365. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging_callable_source.py +0 -0
  366. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging_mcp_tools.py +0 -0
  367. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_packaging_program_source.py +0 -0
  368. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_poll_until.py +0 -0
  369. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_id_deprecation.py +0 -0
  370. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_identity.py +0 -0
  371. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_lineage_persist.py +0 -0
  372. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_names_in_deploy.py +0 -0
  373. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_program_naming.py +0 -0
  374. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_programs_create.py +0 -0
  375. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_project_payload.py +0 -0
  376. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_real_provider_twins_readiness.py +0 -0
  377. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_reflector_properties.py +0 -0
  378. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_reflector_smoke.py +0 -0
  379. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_release_gate_script.py +0 -0
  380. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_release_real_models_script.py +0 -0
  381. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_replaced_names.py +0 -0
  382. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_repro_reactv2_bugs.py +0 -0
  383. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_require_version_bump.py +0 -0
  384. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_retry.py +0 -0
  385. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_reversible_failures.py +0 -0
  386. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_rlm_patch.py +0 -0
  387. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_run_attribution_paths.py +0 -0
  388. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_runtime_tools.py +0 -0
  389. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_schemas.py +0 -0
  390. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_seal_lm_credential.py +0 -0
  391. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_seed_review_run.py +0 -0
  392. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_signature_inputs.py +0 -0
  393. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_span_references.py +0 -0
  394. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_span_sent_once.py +0 -0
  395. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_system_one.py +0 -0
  396. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_context_concurrency.py +0 -0
  397. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_fact_wire_contract.py +0 -0
  398. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_facts.py +0 -0
  399. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_trace_render.py +0 -0
  400. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_traces_read.py +0 -0
  401. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_tracked_gepa.py +0 -0
  402. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_tracker_enrich.py +0 -0
  403. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_truncation.py +0 -0
  404. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_upload_auth_headers.py +0 -0
  405. {cmpnd-0.82.0 → cmpnd-0.83.0}/tests/test_valsets_api.py +0 -0
  406. {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.82.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 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
 
@@ -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
 
@@ -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 deploy program.py qa --run '{"question": "..."}' # deploy program name qa + smoke test
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 (default: the organization's default "
1482
- "credential). `cmpnd credentials list` shows the names",
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 (default: the organization's default credential). "
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 that it should have one. An
26
- optimize with `--deployment-id` needs no program name, because that deployment
27
- already has its program, and a program name with it is refused when the file
28
- binds no program. In the shell, `deploy()` and `optimize()` take the
29
- program name as `program=`.
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. The CLI looks
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. `refresh` lists the
693
- tools again after a vendor changes them. `list` and `show` print the API's
694
- JSON. With `--text`, `show` prints each tool with its allow-list state and a
695
- one-line description, and `--schemas` adds the reduced argument schema the
696
- platform enforces. `create`, `allow`, `deny` and `refresh` render the server
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
- A run spends the organization's default credential unless the command names
777
- another. `--credential NAME` names the run's credential. The program's model
778
- spends it, and so does every model that names no credential of its own.
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=..., timeout=..., metadata=...)` deploys a
144
- `cmpnd.Program` and returns a `cmpnd.DeployedProgram`.
145
- - `sdk.run_deployment(deployment, *, entrypoint=None, **inputs)` runs one
146
- deployment and returns a `dspy.Prediction`. `deployment` is a
147
- `DeployedProgram` or a deployment id. `entrypoint` picks the module to run
148
- inside a deployment that holds more than one. A `program_name` among the
149
- inputs raises `TypeError` and names `entrypoint=`.
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", ...)` runs the
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.execute()`, `cmpnd.optimize()`, the top-level run
167
- functions and `sdk.run_optimization()` raise a `TypeError` that names the
168
- client method that replaces them.
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
- deployment = client.deploy_program(cmpnd.Program("my-program", module=program, lm=lm))
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"),