cmpnd 0.52.0__tar.gz → 0.53.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 (383) hide show
  1. {cmpnd-0.52.0 → cmpnd-0.53.0}/PKG-INFO +187 -72
  2. {cmpnd-0.52.0 → cmpnd-0.53.0}/README.md +186 -71
  3. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/__init__.py +1 -1
  4. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/callback.py +5 -6
  5. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/programs.py +14 -25
  6. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/top.py +31 -58
  7. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/shell.py +7 -9
  8. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/client.py +7 -11
  9. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/configuration.py +20 -22
  10. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/deployment.py +23 -21
  11. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/identity.py +23 -12
  12. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/optimization.py +13 -16
  13. cmpnd-0.53.0/cmpnd/programs.py +57 -0
  14. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/cli.md +3 -2
  15. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/client.md +4 -4
  16. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/sdk-instrumentation.md +10 -9
  17. {cmpnd-0.52.0 → cmpnd-0.53.0}/pyproject.toml +1 -1
  18. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/committee_task.py +3 -3
  19. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/helpers.py +41 -8
  20. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_deploy_execute.py +21 -13
  21. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_deploy_pandas.py +2 -2
  22. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_deploy_programs.py +7 -5
  23. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_failures.py +2 -4
  24. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_loop.py +16 -13
  25. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_server_owned_completion.py +6 -5
  26. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_user_attribution.py +4 -1
  27. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_valsets_cli.py +2 -1
  28. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +6 -6
  29. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/hosted_optimize_probe.py +4 -3
  30. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_deploy_programs.py +2 -1
  31. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_optimize_loop.py +2 -3
  32. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_optimize_loop_wasm.py +4 -6
  33. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_optimize_stress.py +10 -7
  34. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_real_provider_twins.py +2 -3
  35. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_rlm_wasm.py +3 -2
  36. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_authored_optimize.py +1 -1
  37. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_shell.py +4 -4
  38. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_top.py +37 -32
  39. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_client.py +6 -10
  40. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_client_program_names.py +4 -5
  41. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_deploy.py +2 -5
  42. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_deploy_mcp_tool_references.py +1 -4
  43. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_deploy_program_id.py +16 -22
  44. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_execute_run_identity.py +3 -5
  45. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize.py +1 -4
  46. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_program_id_deprecation.py +66 -64
  47. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_program_identity.py +24 -25
  48. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_program_names_in_deploy.py +35 -60
  49. cmpnd-0.53.0/tests/test_programs_create.py +95 -0
  50. {cmpnd-0.52.0 → cmpnd-0.53.0}/uv.lock +161 -120
  51. cmpnd-0.52.0/cmpnd/programs.py +0 -146
  52. cmpnd-0.52.0/tests/test_programs_create.py +0 -131
  53. {cmpnd-0.52.0 → cmpnd-0.53.0}/.gitignore +0 -0
  54. {cmpnd-0.52.0 → cmpnd-0.53.0}/AGENTS.md +0 -0
  55. {cmpnd-0.52.0 → cmpnd-0.53.0}/CLAUDE.md +0 -0
  56. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_assessments.py +0 -0
  57. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_authored_import.py +0 -0
  58. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_deployments.py +0 -0
  59. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_exporter_pool.py +0 -0
  60. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_gepa_patch.py +0 -0
  61. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_http.py +0 -0
  62. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_program_patch.py +0 -0
  63. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_rlm_patch.py +0 -0
  64. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_runtime_tools.py +0 -0
  65. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_timespec.py +0 -0
  66. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_traces.py +0 -0
  67. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/_valsets.py +0 -0
  68. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/authored.py +0 -0
  69. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/__init__.py +0 -0
  70. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/api_client.py +0 -0
  71. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/__init__.py +0 -0
  72. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/admin.py +0 -0
  73. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/assessments.py +0 -0
  74. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/auth.py +0 -0
  75. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/datasets.py +0 -0
  76. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/deployments.py +0 -0
  77. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/evals.py +0 -0
  78. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/login.py +0 -0
  79. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/optimizations.py +0 -0
  80. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/org.py +0 -0
  81. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  82. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/signatures.py +0 -0
  83. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  84. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/traces.py +0 -0
  85. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/commands/valsets.py +0 -0
  86. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/credentials.py +0 -0
  87. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/deprecation.py +0 -0
  88. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/pagination.py +0 -0
  89. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/trace_render.py +0 -0
  90. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/tree_help.py +0 -0
  91. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/cli/verbs.py +0 -0
  92. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/context.py +0 -0
  93. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/dataset_sync.py +0 -0
  94. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/datasets.py +0 -0
  95. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/decorators.py +0 -0
  96. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/deployment_metadata.py +0 -0
  97. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/deployment_runs.py +0 -0
  98. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/eval_handler.py +0 -0
  99. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/execution.py +0 -0
  100. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/exporter.py +0 -0
  101. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/exporter_http.py +0 -0
  102. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/helpers.py +0 -0
  103. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/imaging.py +0 -0
  104. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/__init__.py +0 -0
  105. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/decode.py +0 -0
  106. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/encode.py +0 -0
  107. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/hash.py +0 -0
  108. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/program.py +0 -0
  109. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/reflection.py +0 -0
  110. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/types.py +0 -0
  111. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/ir/xxh64.py +0 -0
  112. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/lm_configuration.py +0 -0
  113. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/mcp_servers.py +0 -0
  114. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/models.py +0 -0
  115. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/named_programs.py +0 -0
  116. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/optimizers/__init__.py +0 -0
  117. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/optimizers/gepa.py +0 -0
  118. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  119. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/optimizers/resume.py +0 -0
  120. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/optimizers/tracker.py +0 -0
  121. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/packaging.py +0 -0
  122. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/references.py +0 -0
  123. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/retry.py +0 -0
  124. {cmpnd-0.52.0 → cmpnd-0.53.0}/cmpnd/traces.py +0 -0
  125. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/2026-04-02-code-review.md +0 -0
  126. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/custom-proposer.md +0 -0
  127. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  128. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  129. {cmpnd-0.52.0 → cmpnd-0.53.0}/docs/reading-traces.md +0 -0
  130. {cmpnd-0.52.0 → cmpnd-0.53.0}/examples/generalizing_proposer.py +0 -0
  131. {cmpnd-0.52.0 → cmpnd-0.53.0}/examples/local_ollama.py +0 -0
  132. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/LINEAGE.md +0 -0
  133. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/README.md +0 -0
  134. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  135. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  136. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  137. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  138. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  139. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  140. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/py.typed +0 -0
  141. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  142. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/retry.py +0 -0
  143. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  144. {cmpnd-0.52.0 → cmpnd-0.53.0}/ingest/pyproject.toml +0 -0
  145. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/audit-sdist.sh +0 -0
  146. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/capture_review_run.py +0 -0
  147. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/check-pip-install.sh +0 -0
  148. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/check_release_artifacts.py +0 -0
  149. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/fixtures/review_run.json.gz +0 -0
  150. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/gepa_resume_bug.py +0 -0
  151. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/release-stress.sh +0 -0
  152. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/require_version_bump.py +0 -0
  153. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/seed_review_run.py +0 -0
  154. {cmpnd-0.52.0 → cmpnd-0.53.0}/scripts/test-in-linux.sh +0 -0
  155. {cmpnd-0.52.0 → cmpnd-0.53.0}/stubs/dspy/__init__.pyi +0 -0
  156. {cmpnd-0.52.0 → cmpnd-0.53.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  157. {cmpnd-0.52.0 → cmpnd-0.53.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  158. {cmpnd-0.52.0 → cmpnd-0.53.0}/stubs/dspy/utils/__init__.pyi +0 -0
  159. {cmpnd-0.52.0 → cmpnd-0.53.0}/stubs/dspy/utils/callback.pyi +0 -0
  160. {cmpnd-0.52.0 → cmpnd-0.53.0}/stubs/dspy/utils/dummies.pyi +0 -0
  161. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/__init__.py +0 -0
  162. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/_deployment_signature_helpers.py +0 -0
  163. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/_exporter_helpers.py +0 -0
  164. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/_fake_clock.py +0 -0
  165. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/_identity_helpers.py +0 -0
  166. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/_resolve_refs.py +0 -0
  167. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/_traced_run.py +0 -0
  168. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/conftest.py +0 -0
  169. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/__init__.py +0 -0
  170. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/conftest.py +0 -0
  171. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  172. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  173. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/fake_lm.py +0 -0
  174. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/target_capabilities.py +0 -0
  175. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_assessments_cli.py +0 -0
  176. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_capture_prompts.py +0 -0
  177. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_composite_module.py +0 -0
  178. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  179. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_edge_cases.py +0 -0
  180. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_example_hash.py +0 -0
  181. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_gepa_optimization.py +0 -0
  182. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_interpreter_spans.py +0 -0
  183. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_lm_accuracy.py +0 -0
  184. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_module_tracing.py +0 -0
  185. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_optimization_lineage.py +0 -0
  186. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  187. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  188. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_parallel_export.py +0 -0
  189. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_project_attribution.py +0 -0
  190. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_react_tool_spans.py +0 -0
  191. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_save_load.py +0 -0
  192. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_trace_structure.py +0 -0
  193. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/e2e/test_traces_read.py +0 -0
  194. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  195. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  196. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  197. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  198. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  199. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  200. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  201. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  202. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  203. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/10_react.json +0 -0
  204. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/11_refine.json +0 -0
  205. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/12_retrieve.json +0 -0
  206. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/13_knn.json +0 -0
  207. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/14_parallel.json +0 -0
  208. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/identity_vectors/README.md +0 -0
  209. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/ingest_conformance.py +0 -0
  210. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/__init__.py +0 -0
  211. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/authored_optimize/judge.py +0 -0
  212. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  213. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/conftest.py +0 -0
  214. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/optimization_run_probe.py +0 -0
  215. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  216. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/test_logs_renders_traces.py +0 -0
  217. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/test_optimization_run.py +0 -0
  218. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/test_optimizing_progress.py +0 -0
  219. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/integration/test_unhappy_path.py +0 -0
  220. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/__init__.py +0 -0
  221. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/__main__.py +0 -0
  222. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/drain.py +0 -0
  223. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/ingest.py +0 -0
  224. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/latency_transport.py +0 -0
  225. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/rlm_shape.py +0 -0
  226. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/rlm_size_report.py +0 -0
  227. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/sweep.py +0 -0
  228. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/test_rlm_shape.py +0 -0
  229. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/load/test_rlm_size_report.py +0 -0
  230. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/__init__.py +0 -0
  231. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/conftest.py +0 -0
  232. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/seed_parity.py +0 -0
  233. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_auth.py +0 -0
  234. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_datasets.py +0 -0
  235. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_deployments.py +0 -0
  236. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_evals.py +0 -0
  237. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_health.py +0 -0
  238. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_modules.py +0 -0
  239. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_optimizations.py +0 -0
  240. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_programs.py +0 -0
  241. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_signatures.py +0 -0
  242. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_trace_streaming.py +0 -0
  243. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/parity/test_traces.py +0 -0
  244. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/span_reference_fixture.py +0 -0
  245. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/__init__.py +0 -0
  246. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/_provider.py +0 -0
  247. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/_readiness.py +0 -0
  248. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/_reliability.py +0 -0
  249. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/_result.py +0 -0
  250. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/mint_bedrock_token.py +0 -0
  251. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_multi_client_stress.py +0 -0
  252. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_optimize_client_committee.py +0 -0
  253. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_provider_roles.py +0 -0
  254. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_readiness.py +0 -0
  255. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_reliability.py +0 -0
  256. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_reliability_classify.py +0 -0
  257. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/stress/test_trace_search.py +0 -0
  258. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_adapter_reentrancy.py +0 -0
  259. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_assessments_api.py +0 -0
  260. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_authored.py +0 -0
  261. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_authored_bundle_collisions.py +0 -0
  262. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_authored_metric_contract.py +0 -0
  263. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_authored_named_models.py +0 -0
  264. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_callback.py +0 -0
  265. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_candidate_lineage.py +0 -0
  266. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/__init__.py +0 -0
  267. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/conftest.py +0 -0
  268. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_admin.py +0 -0
  269. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_api_client.py +0 -0
  270. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_assessments.py +0 -0
  271. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_auth.py +0 -0
  272. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_credentials.py +0 -0
  273. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_datasets.py +0 -0
  274. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_deployment_runs.py +0 -0
  275. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_deployments.py +0 -0
  276. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_evals.py +0 -0
  277. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_login.py +0 -0
  278. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_main.py +0 -0
  279. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_optimizations.py +0 -0
  280. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_org.py +0 -0
  281. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_pagination.py +0 -0
  282. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_parity.py +0 -0
  283. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_programs.py +0 -0
  284. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_provider_credentials.py +0 -0
  285. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_schema_sample.py +0 -0
  286. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_signatures.py +0 -0
  287. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_tool_servers.py +0 -0
  288. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_traces.py +0 -0
  289. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  290. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_tree_help.py +0 -0
  291. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cli/test_valsets.py +0 -0
  292. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_client_floor.py +0 -0
  293. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_clustering/__init__.py +0 -0
  294. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_clustering/conftest.py +0 -0
  295. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_clustering/test_edge_cases.py +0 -0
  296. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  297. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_clustering/test_type_conversion.py +0 -0
  298. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_cmp551_grouping_identity.py +0 -0
  299. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_configuration.py +0 -0
  300. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_context.py +0 -0
  301. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_context_propagation.py +0 -0
  302. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_dataset_polling.py +0 -0
  303. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_dataset_sync.py +0 -0
  304. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_datasets.py +0 -0
  305. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_decision_client_spans.py +0 -0
  306. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_decorators.py +0 -0
  307. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_deployment_metadata.py +0 -0
  308. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_deployment_runs.py +0 -0
  309. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_deployments_read.py +0 -0
  310. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_eval.py +0 -0
  311. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_eval_example_attribution.py +0 -0
  312. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_eval_start.py +0 -0
  313. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_eval_trace_grouping.py +0 -0
  314. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_exception_paths.py +0 -0
  315. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_execute.py +0 -0
  316. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_exporter.py +0 -0
  317. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_exporter_program_names.py +0 -0
  318. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_exporter_queue.py +0 -0
  319. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_exporter_real.py +0 -0
  320. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_fake_lm.py +0 -0
  321. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_gepa_callback.py +0 -0
  322. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_gepa_integration.py +0 -0
  323. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_gepa_output_normalization.py +0 -0
  324. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_gepa_resume.py +0 -0
  325. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_identity.py +0 -0
  326. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_imaging.py +0 -0
  327. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_import_weight.py +0 -0
  328. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_ingest_conformance.py +0 -0
  329. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_ingest_second_producer.py +0 -0
  330. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_integration.py +0 -0
  331. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_interpreter_callback.py +0 -0
  332. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_ir_encoder_properties.py +0 -0
  333. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_ir_golden_vectors.py +0 -0
  334. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_ir_roundtrip.py +0 -0
  335. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_lm15_native_calls.py +0 -0
  336. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_lm_configuration.py +0 -0
  337. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_lm_usage_shapes.py +0 -0
  338. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_mcp_tools.py +0 -0
  339. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_models.py +0 -0
  340. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_multi_client_stress_readiness.py +0 -0
  341. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimization_progress.py +0 -0
  342. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimization_start.py +0 -0
  343. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize_budget.py +0 -0
  344. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize_lift.py +0 -0
  345. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize_lms.py +0 -0
  346. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize_proposer.py +0 -0
  347. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize_reflection_lm.py +0 -0
  348. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_optimize_terminal_failure.py +0 -0
  349. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_packaging.py +0 -0
  350. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_packaging_callable_source.py +0 -0
  351. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_packaging_mcp_tools.py +0 -0
  352. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_packaging_program_source.py +0 -0
  353. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_poll_until.py +0 -0
  354. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_program_lineage_persist.py +0 -0
  355. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_project_payload.py +0 -0
  356. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_real_provider_twins_readiness.py +0 -0
  357. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_reflector_properties.py +0 -0
  358. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_reflector_smoke.py +0 -0
  359. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_release_stress_script.py +0 -0
  360. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_repro_reactv2_bugs.py +0 -0
  361. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_require_version_bump.py +0 -0
  362. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_retry.py +0 -0
  363. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_reversible_failures.py +0 -0
  364. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_rlm_patch.py +0 -0
  365. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_run_attribution_paths.py +0 -0
  366. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_runtime_tools.py +0 -0
  367. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_schemas.py +0 -0
  368. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_seed_review_run.py +0 -0
  369. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_signature_inputs.py +0 -0
  370. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_span_references.py +0 -0
  371. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_span_sent_once.py +0 -0
  372. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_system_one.py +0 -0
  373. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_trace_context_concurrency.py +0 -0
  374. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_trace_fact_wire_contract.py +0 -0
  375. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_trace_facts.py +0 -0
  376. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_trace_render.py +0 -0
  377. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_traces_read.py +0 -0
  378. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_tracked_gepa.py +0 -0
  379. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_tracker_enrich.py +0 -0
  380. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_truncation.py +0 -0
  381. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_upload_auth_headers.py +0 -0
  382. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_valsets_api.py +0 -0
  383. {cmpnd-0.52.0 → cmpnd-0.53.0}/tests/test_xxh64.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.52.0
3
+ Version: 0.53.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>
@@ -60,8 +60,20 @@ cmpnd platform. One call turns on tracing, and one more deploys a program.
60
60
  uv add cmpnd # or: pip install cmpnd
61
61
  ```
62
62
 
63
+ ## Authentication
64
+
65
+ The `cmpnd` library works with the cmpnd service at
66
+ [platform.cmpnd.ai](https://platform.cmpnd.ai). Create an API key on the
67
+ platform under Settings → API keys, and pass it as `api_key=` to
68
+ `cmpnd.configure()` or `cmpnd.Client()`. For a self-hosted cmpnd install, also
69
+ pass the install's URL as `endpoint=`.
70
+
63
71
  ## Quick start
64
72
 
73
+ `cmpnd.auto_instrument()` records a trace of every DSPy call in the process.
74
+ Your code needs no other change. Use it to sketch a [DSPy program](https://dspy.ai/) and see what it
75
+ does.
76
+
65
77
  ```python
66
78
  import cmpnd
67
79
  import dspy
@@ -78,36 +90,85 @@ cmpnd.trace_id(result) # "a1b2c3d4-...", or None outside instrumentation
78
90
  ```
79
91
 
80
92
  `cmpnd.trace_id()` links a result to its platform trace, for example to attach
81
- feedback later.
93
+ feedback later. Traces recorded this way have no program name. The platform
94
+ groups them by the structure of the program's modules. The API reference
95
+ below lists the other options of `cmpnd.configure()`.
82
96
 
83
- ## Configuration
97
+ ## Program names
84
98
 
85
- `cmpnd.configure()` reads `CMPND_API_KEY` and `CMPND_ENDPOINT` when you pass
86
- no arguments. The endpoint defaults to `https://platform.cmpnd.ai`.
99
+ When you’re ready to name programs, evolve them, and share them with your team, switch
100
+ to `cmpnd.Client`. A client replaces `configure()` and `auto_instrument()` and offers
101
+ more features. A client records only the programs you run through it, and each of
102
+ those programs has a program name. A client takes most of the same arguments as `configure()`.
87
103
 
88
- ```bash
89
- export CMPND_API_KEY="ck_your_api_key"
90
- export CMPND_ENDPOINT="https://platform.cmpnd.ai" # optional
104
+ A program name is the name your organization gives a program, such as `question-answerer`.
105
+ Traces, deployments and optimization runs under one program name go to one
106
+ program. The platform makes the program the first time your organization uses
107
+ the program name.
108
+
109
+ `@cmpnd.program(name)` above a `dspy.Module` class gives the class a program
110
+ name. Building the class takes its own arguments and a required `lm=`. The
111
+ `lm=` argument is the `dspy.LM` that the program runs on:
112
+
113
+ ```python
114
+ import cmpnd
115
+ import dspy
116
+
117
+ class Answer(dspy.Signature):
118
+ """Answer the question in one short sentence."""
119
+ question: str = dspy.InputField()
120
+ answer: str = dspy.OutputField()
121
+
122
+ @cmpnd.program("question-answerer")
123
+ class QA(dspy.Predict):
124
+ def __init__(self):
125
+ super().__init__(Answer)
126
+
127
+ qa1 = QA(lm=dspy.LM("openai/gpt-6-luna"))
91
128
  ```
92
129
 
130
+ A client runs the program and records its trace under the program name:
131
+
93
132
  ```python
94
- cmpnd.configure(
95
- api_key="ck_xxx", # required, or CMPND_API_KEY
96
- endpoint="https://platform.cmpnd.ai", # optional, or CMPND_ENDPOINT
97
- project_tags="my-project", # optional: one tag or a list of tags
98
- batch_size=100, # optional: spans per export batch
99
- flush_interval_seconds=5.0, # optional: seconds between flushes
100
- capture_inputs=True, # optional: record span inputs
101
- capture_outputs=True, # optional: record span outputs
102
- default_tags={"env": "prod"}, # optional: tags on every trace
133
+ gepa = dspy.GEPA(metric=metric, reflection_lm=dspy.LM("openai/gpt-6-luna"), auto="light")
134
+
135
+ with cmpnd.Client(api_key="ck_xxx", project_tags="my-project") as sdk:
136
+ # the trace will go to the program "question-answerer"
137
+ result = sdk.run_program(qa1, question="What is DSPy?")
138
+ qa2 = sdk.run_optimization(gepa, qa1, trainset=train, valset=val)
139
+ ```
140
+
141
+ A client is active from construction. The `with` form flushes the client's
142
+ traces and closes it on exit. Without `with`, the client stays active until
143
+ you call `close()` or the process exits, and its traces go out at exit:
144
+
145
+ ```python
146
+ sdk = cmpnd.Client(api_key="ck_xxx", project_tags="my-project")
147
+ sdk.run_program(qa2, question="What is DSPy?")
148
+
149
+ # optional: flushes the traces now, so a later read sees them
150
+ sdk.close()
151
+ ```
152
+
153
+ The `cmpnd.Program` constructor gives a program name to a module you already
154
+ have, such as a `dspy.Predict`. It makes the same kind of
155
+ program as the decorator:
156
+
157
+ ```python
158
+ qa3 = cmpnd.Program(
159
+ "question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
103
160
  )
104
161
  ```
105
162
 
106
- `project` is a deprecated alias for `project_tags`. Passing both raises
107
- `ValueError`. `CMPND_MAX_INPUT_SIZE` and `CMPND_MAX_OUTPUT_SIZE` set the
108
- captured input and output size limits, 65,536 bytes each by default.
163
+ - A program name starts with an ASCII letter or digit, then has letters,
164
+ digits, `.`, `_` or `-`, at most 64 characters. It does not start with `p_`.
165
+ A bad name raises `ValueError`. Declaring a program makes no network call.
166
+ - `run_optimization` returns a copy of the program that holds the optimized
167
+ module. The copy keeps the program name and the LM.
168
+ - Calling a `cmpnd.Program` directly while `auto_instrument()` is on raises a
169
+ `TypeError` that points to `cmpnd.Client`.
109
170
 
110
- ## Deployment
171
+ ## Deployed programs
111
172
 
112
173
  Every deployment belongs to a program, and each program has a program name.
113
174
  Give a DSPy module a program name with `cmpnd.Program`, then deploy it for
@@ -119,16 +180,17 @@ import dspy
119
180
 
120
181
  cmpnd.configure(api_key="ck_xxx")
121
182
 
122
- qa = cmpnd.Program("qa", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna"))
123
- deployed = cmpnd.deploy(qa)
183
+ qa4 = cmpnd.Program(
184
+ "question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
185
+ )
186
+ deployed = cmpnd.deploy(qa4)
124
187
 
125
188
  result = deployed(question="What is DSPy?") # runs server-side
126
189
  print(result.answer)
127
190
  ```
128
191
 
129
- `deploy()` packages the module's source into a ZIP, uploads it and polls until
130
- the server-side parser finishes. It then reads the deployment's persisted
131
- interface and returns a `DeployedProgram`. Call the program to execute it
192
+ `deploy()` packages the module's source, sends it to the platform and waits
193
+ until the platform has read it. It then returns a `DeployedProgram`. Call the program to execute it
132
194
  server-side. `str(deployed)` and `deployed.deployment_id` return the
133
195
  deployment ID. `deployed.artifact_metadata` holds the typed artifact record
134
196
  when the platform has inspected it. An unknown interface leaves `input_fields`
@@ -137,15 +199,7 @@ lists.
137
199
 
138
200
  The platform makes the program the first time your organization uses the
139
201
  program name. Later deploys under the same program name go to the same
140
- program. `@cmpnd.program("qa")` above a `dspy.Module`
141
- class declares the same program name. [`docs/client.md`](docs/client.md)
142
- describes both forms.
143
-
144
- To deploy a source file, run `cmpnd deploy program.py qa`. The CLI uploads
145
- the file's exact bytes and does not reconstruct the source from a live object.
146
- Use `--source-root` and repeated `--include` flags for sibling modules or
147
- data, and `cmpnd inspect <id> --source` to read the deployed entry file back.
148
- [`docs/cli.md`](docs/cli.md) covers the CLI.
202
+ program, and so do the traces of a client that runs it.
149
203
 
150
204
  ### Options
151
205
 
@@ -153,26 +207,20 @@ data, and `cmpnd inspect <id> --source` to read the deployed entry file back.
153
207
  cmpnd.deploy(
154
208
  program, # required: a cmpnd.Program
155
209
  metric=None, # optional: a metric callable, packaged for optimization
156
- timeout=300, # optional: seconds to wait for the parser after the upload
210
+ timeout=300, # optional: seconds to wait for the deployment to be ready
157
211
  metadata=None, # optional: a JSON-serializable dict, at most 64 KiB, stored with the deployment
158
212
  )
159
213
  ```
160
214
 
161
215
  ### How it works
162
216
 
163
- 1. The SDK generates source from the live module, including its LM
164
- configuration, signature and types.
165
- 2. `POST /api/v1/deployments` creates the deployment and returns an upload
166
- URL.
167
- 3. The SDK uploads the source ZIP to that URL. The bytes go to the worker.
168
- 4. The worker's parser extracts the program and its LM configuration.
169
- 5. The SDK polls until the status is `ready`, reads the artifact metadata and
170
- returns the `DeployedProgram`.
171
-
172
- The parser reads the model string, such as `openai/gpt-6-luna`, and its
173
- sampling settings from the source.
217
+ 1. The SDK packages the module's source, including its LM configuration,
218
+ signature and types.
219
+ 2. The platform reads the program, the model string and the sampling settings
220
+ from that source.
221
+ 3. `deploy()` returns the `DeployedProgram` when the deployment is ready.
174
222
 
175
- ## Optimization
223
+ ## Optimization on the platform
176
224
 
177
225
  `cmpnd.optimize()` optimizes a program through the platform. Like `deploy()`,
178
226
  it returns a `DeployedProgram` that you call directly, and the program's
@@ -184,13 +232,16 @@ import dspy
184
232
 
185
233
  cmpnd.configure(api_key="ck_xxx")
186
234
 
187
- program = cmpnd.Program("haiku", module=dspy.ChainOfThought("topic -> haiku"), lm=dspy.LM("openai/gpt-6-luna"))
235
+ program = cmpnd.Program(
236
+ "haiku", module=dspy.ChainOfThought("topic -> haiku"), lm=dspy.LM("openai/gpt-6-luna")
237
+ )
188
238
 
189
239
  # GEPA needs a five-argument feedback metric that returns dspy.Prediction(score=, feedback=)
190
240
  def metric(example, pred, trace=None, pred_name=None, pred_trace=None):
191
241
  ok = example.season.lower() not in pred.haiku.lower()
192
- return dspy.Prediction(score=float(ok),
193
- feedback=None if ok else "Don't name the season.")
242
+ return dspy.Prediction(
243
+ score=float(ok), feedback=None if ok else "Don't name the season."
244
+ )
194
245
 
195
246
  best = cmpnd.optimize(
196
247
  program,
@@ -224,7 +275,7 @@ warning.
224
275
 
225
276
  `gepa` is the only optimizer the platform runs. `optimize()` raises
226
277
  `ValueError` for the retired `bootstrap_fewshot` and `random_search` before
227
- any network call, and serve answers them with a 404 that names gepa.
278
+ any network call, and the platform answers them with a 404 that names gepa.
228
279
 
229
280
  ### A metric with its own model
230
281
 
@@ -260,7 +311,7 @@ rules:
260
311
  names.
261
312
  - `"default-lm"` is reserved for the program's own model, which comes from the
262
313
  deployment. Declaring it raises an error that names it.
263
- - Serve refuses a model your org holds no credential for when it dispatches
314
+ - The platform refuses a model your org holds no credential for when it dispatches
264
315
  the run, before the run starts. These LMs, like `reflection_lm`, must not set
265
316
  `api_key`, `api_base` or `base_url`.
266
317
 
@@ -268,9 +319,6 @@ The `lms` parameter does not change the arity check. Five or more positional
268
319
  arguments make a feedback metric, and a metric without `lms` never receives
269
320
  it.
270
321
 
271
- A run can also bring its own instruction proposer through `proposer`.
272
- [`docs/custom-proposer.md`](docs/custom-proposer.md) describes it.
273
-
274
322
  ### Reusing a deployment
275
323
 
276
324
  Pass the `deployment_id` of a ready deployment to skip the initial deploy:
@@ -291,8 +339,7 @@ cmpnd.optimize(
291
339
  trainset=train, # required: training examples
292
340
  valset=val, # required: validation examples
293
341
  metric=metric, # required: the metric, arity-checked
294
- proposer=None, # optional: the run's own instruction proposer
295
- config=None, # optional: optimizer config, allow-listed by serve
342
+ config=None, # optional: optimizer config, allow-listed by the platform
296
343
  deployment_id=None, # optional: a ready deployment to start from
297
344
  reflection_lm=None, # required: a dspy.LM or a bare model name
298
345
  lms=None, # optional: name -> dspy.LM, the run's named models
@@ -302,7 +349,7 @@ cmpnd.optimize(
302
349
  max_steps=10, # optional: the most optimize steps
303
350
  patience=2, # optional: stop after this many steps without improvement
304
351
  seed=0, # optional: the starting seed, advanced each step
305
- poll_interval=3.0, # optional: seconds between status polls
352
+ poll_interval=3.0, # optional: seconds between status checks
306
353
  timeout=600.0, # optional: seconds to wait for each step
307
354
  )
308
355
  ```
@@ -311,20 +358,41 @@ Pass exactly one budget: `max_metric_calls`, `auto` or
311
358
  `config["max_full_evals"]`. The SDK raises before any network call when the
312
359
  budget is missing.
313
360
 
314
- `optimize()` raises `cmpnd.OptimizeError` when serve answers a step's
361
+ `optimize()` raises `cmpnd.OptimizeError` when the platform answers a step's
315
362
  initiation with a 4xx, such as a 409 for missing data or a metric mismatch. It
316
363
  raises `cmpnd.OptimizeFailed` when a step reaches `failed`.
317
364
 
318
- ### From the CLI
365
+ ## Command line
366
+
367
+ The package installs the `cmpnd` command. `cmpnd login` saves your API key for
368
+ the command line. `cmpnd -h` lists the commands, and `cmpnd COMMAND -h`
369
+ describes one:
370
+
371
+ ```
372
+ usage: cmpnd [-h] [--version] [--api-key API_KEY] [--endpoint ENDPOINT]
373
+ {auth,login,logout,org,credentials,tool-servers,optimizations,programs,signatures,traces,evals,datasets,deployments,ps,status,logs,inspect,schema,sample,run,deploy,optimize}
374
+ ...
375
+
376
+ CMPND platform CLI — deploy, invoke, and inspect DSPy programs.
377
+
378
+ options:
379
+ -h, --help show this help message and exit
380
+ --version show program's version number and exit
381
+ --api-key API_KEY API key (or set CMPND_API_KEY)
382
+ --endpoint ENDPOINT API endpoint (or set CMPND_ENDPOINT)
383
+ ```
384
+
385
+ Deploy a source file under a program name, or optimize the program a file
386
+ declares:
319
387
 
320
388
  ```bash
389
+ cmpnd deploy program.py question-answerer
321
390
  cmpnd optimize gepa task.py haiku --reflection-model openai/gpt-6-luna --auto light
322
391
  ```
323
392
 
324
- The file, or `-` for stdin, binds `program`, `trainset`, `valset` and
325
- `metric`. The CLI prints the best deployment ID. The CLI deploys the file's
326
- program first under the program name, here `haiku`. With `--deployment-id`,
327
- the CLI starts from that deployment and needs no program name.
393
+ `cmpnd deploy` uploads the file as written. `cmpnd optimize` reads `program`,
394
+ `trainset`, `valset` and `metric` from the file, deploys the program under the
395
+ program name and prints the best deployment ID.
328
396
 
329
397
  ## Custom spans
330
398
 
@@ -374,11 +442,59 @@ def run_pipeline(query: str):
374
442
 
375
443
  ### `cmpnd.configure()`
376
444
 
377
- Sets the API key, endpoint and options.
445
+ Sets the global API key, endpoint and options that `auto_instrument()`,
446
+ `deploy()`, `optimize()` and `execute()` use:
447
+
448
+ ```python
449
+ cmpnd.configure(
450
+ api_key="ck_xxx", # required, or CMPND_API_KEY
451
+ endpoint="https://platform.cmpnd.ai", # optional, or CMPND_ENDPOINT
452
+ project_tags="my-project", # optional: one tag or a list of tags
453
+ batch_size=100, # optional: spans per export batch
454
+ flush_interval_seconds=5.0, # optional: seconds between flushes
455
+ capture_inputs=True, # optional: record span inputs
456
+ capture_outputs=True, # optional: record span outputs
457
+ default_tags={"env": "prod"}, # optional: tags on every trace
458
+ )
459
+ ```
460
+
461
+ `api_key` and `endpoint` fall back to the `CMPND_API_KEY` and
462
+ `CMPND_ENDPOINT` environment variables. `project` is a deprecated alias for
463
+ `project_tags`. Passing both raises `ValueError`. `CMPND_MAX_INPUT_SIZE` and `CMPND_MAX_OUTPUT_SIZE` set the
464
+ captured input and output size limits, 65,536 bytes each by default.
378
465
 
379
466
  ### `cmpnd.auto_instrument()`
380
467
 
381
- Registers the callback with DSPy.
468
+ Registers the callback with DSPy, so every DSPy call records a trace.
469
+
470
+ ### `cmpnd.Client()`
471
+
472
+ Takes most of the same arguments as `cmpnd.configure()` and keeps them apart from the
473
+ global config. Use it as a context manager or as a plain object.
474
+
475
+ - `run_program(program, **inputs)` runs a `cmpnd.Program` and records its trace
476
+ under the program name.
477
+ - `run_optimization(optimizer, program, trainset=..., valset=...)` compiles a
478
+ `cmpnd.Program` with a DSPy optimizer, records every rollout, and returns a
479
+ copy of the program that holds the optimized module. For `dspy.GEPA`, it
480
+ also records the optimization run.
481
+ - `list_traces(**filters)` and `get_trace(trace_id)` read traces with the
482
+ client's credentials. They flush the client's traces first.
483
+ - `close()` flushes the client's traces and closes the client. A closed
484
+ client raises `RuntimeError` on every method.
485
+
486
+ ### `cmpnd.program()`
487
+
488
+ `@cmpnd.program(name)` above a `dspy.Module` class returns a `cmpnd.Program`
489
+ class with the same class name. Building it takes the class's own arguments
490
+ and a required `lm=` keyword. The decorator refuses a class whose
491
+ constructor already takes `lm`. Give an instance of it to `cmpnd.Program` instead.
492
+
493
+ ### `cmpnd.Program()`
494
+
495
+ `cmpnd.Program(name, *, module, lm)` gives a DSPy module a program name and
496
+ the `dspy.LM` it runs on. `@cmpnd.program(name)` builds the same thing from a
497
+ `dspy.Module` class.
382
498
 
383
499
  ### `cmpnd.CmpndCallback`
384
500
 
@@ -407,14 +523,13 @@ Optimizes a program through the platform. It returns the best
407
523
 
408
524
  Submits one durable run by `deployment_id`, waits for the result within the
409
525
  local timeout and returns a `dspy.Prediction`. A `DeployedProgram` call goes
410
- through this function. The SDK sends `Prefer: wait=5`, shortened to fit the
411
- remaining budget, so a fast result arrives without polling. It never repeats
412
- the submission POST.
526
+ through this function. A fast result returns at once, and the SDK never
527
+ submits one run twice.
413
528
 
414
529
  `timeout` is the whole submit-and-wait budget in seconds, 30 by default, or
415
530
  `None` for no local limit. `program_name` and `lm` select a module and model
416
531
  and travel beside the inputs. `metadata` and `tags` take `dict[str, str]`
417
- values that serve applies to the run's root trace. Serve-owned names such as
532
+ values that the platform applies to the run's root trace. Names the platform sets, such as
418
533
  `deployment_run_id` raise `TypeError` before anything is sent. The errors:
419
534
 
420
535
  - A refused request raises `httpx.HTTPStatusError`.
@@ -423,7 +538,7 @@ values that serve applies to the run's root trace. Serve-owned names such as
423
538
  - An answer that expired before it was read raises `RunResultExpired`.
424
539
 
425
540
  `cmpnd.deployment_run_id(result)` returns the run ID of a result, or of an
426
- exception when serve had assigned a run.
541
+ exception when the platform had assigned a run.
427
542
 
428
543
  `cmpnd.submit_deployment_run(id, inputs)` returns the accepted handle without
429
544
  waiting. `cmpnd.list_deployment_runs()`, `get_deployment_run(id)`,