cmpnd 0.78.0__tar.gz → 0.79.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 (405) hide show
  1. {cmpnd-0.78.0 → cmpnd-0.79.0}/PKG-INFO +1 -1
  2. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/admin.py +31 -2
  3. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/cli.md +10 -0
  4. {cmpnd-0.78.0 → cmpnd-0.79.0}/pyproject.toml +1 -1
  5. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_admin.py +91 -5
  6. {cmpnd-0.78.0 → cmpnd-0.79.0}/uv.lock +1 -1
  7. {cmpnd-0.78.0 → cmpnd-0.79.0}/.gitignore +0 -0
  8. {cmpnd-0.78.0 → cmpnd-0.79.0}/AGENTS.md +0 -0
  9. {cmpnd-0.78.0 → cmpnd-0.79.0}/CLAUDE.md +0 -0
  10. {cmpnd-0.78.0 → cmpnd-0.79.0}/README.md +0 -0
  11. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/__init__.py +0 -0
  12. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_assessments.py +0 -0
  13. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_authored_import.py +0 -0
  14. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_deployments.py +0 -0
  15. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_exporter_pool.py +0 -0
  16. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_gepa_patch.py +0 -0
  17. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_http.py +0 -0
  18. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_program_patch.py +0 -0
  19. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_rlm_patch.py +0 -0
  20. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_runtime_tools.py +0 -0
  21. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_timespec.py +0 -0
  22. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_traces.py +0 -0
  23. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/_valsets.py +0 -0
  24. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/authored.py +0 -0
  25. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/callback.py +0 -0
  26. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/__init__.py +0 -0
  27. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/api_client.py +0 -0
  28. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/__init__.py +0 -0
  29. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/assessments.py +0 -0
  30. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/auth.py +0 -0
  31. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/datasets.py +0 -0
  32. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/deployments.py +0 -0
  33. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/evals.py +0 -0
  34. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/login.py +0 -0
  35. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/optimizations.py +0 -0
  36. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/org.py +0 -0
  37. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/programs.py +0 -0
  38. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  39. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  40. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/top.py +0 -0
  41. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/traces.py +0 -0
  42. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/commands/valsets.py +0 -0
  43. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/credentials.py +0 -0
  44. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/deprecation.py +0 -0
  45. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/pagination.py +0 -0
  46. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/shell.py +0 -0
  47. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/trace_render.py +0 -0
  48. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/tree_help.py +0 -0
  49. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/verbs.py +0 -0
  50. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/cli/views.py +0 -0
  51. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/client.py +0 -0
  52. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/configuration.py +0 -0
  53. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/context.py +0 -0
  54. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/credentials.py +0 -0
  55. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/dataset_sync.py +0 -0
  56. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/datasets.py +0 -0
  57. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/decorators.py +0 -0
  58. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/deployment.py +0 -0
  59. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/deployment_metadata.py +0 -0
  60. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/deployment_runs.py +0 -0
  61. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/eval_handler.py +0 -0
  62. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/execution.py +0 -0
  63. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/exporter.py +0 -0
  64. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/exporter_http.py +0 -0
  65. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/helpers.py +0 -0
  66. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/identity.py +0 -0
  67. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/imaging.py +0 -0
  68. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/__init__.py +0 -0
  69. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/decode.py +0 -0
  70. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/encode.py +0 -0
  71. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/hash.py +0 -0
  72. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/program.py +0 -0
  73. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/reflection.py +0 -0
  74. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/types.py +0 -0
  75. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/ir/xxh64.py +0 -0
  76. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/lm_configuration.py +0 -0
  77. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/mcp_servers.py +0 -0
  78. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/models.py +0 -0
  79. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/named_programs.py +0 -0
  80. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/optimization.py +0 -0
  81. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/optimizers/__init__.py +0 -0
  82. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/optimizers/gepa.py +0 -0
  83. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  84. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/optimizers/resume.py +0 -0
  85. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/optimizers/tracker.py +0 -0
  86. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/packaging.py +0 -0
  87. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/program_naming.py +0 -0
  88. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/programs.py +0 -0
  89. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/references.py +0 -0
  90. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/retry.py +0 -0
  91. {cmpnd-0.78.0 → cmpnd-0.79.0}/cmpnd/traces.py +0 -0
  92. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/2026-04-02-code-review.md +0 -0
  93. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/client.md +0 -0
  94. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/custom-proposer.md +0 -0
  95. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  96. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  97. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/reading-traces.md +0 -0
  98. {cmpnd-0.78.0 → cmpnd-0.79.0}/docs/sdk-instrumentation.md +0 -0
  99. {cmpnd-0.78.0 → cmpnd-0.79.0}/examples/generalizing_proposer.py +0 -0
  100. {cmpnd-0.78.0 → cmpnd-0.79.0}/examples/local_ollama.py +0 -0
  101. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/LINEAGE.md +0 -0
  102. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/README.md +0 -0
  103. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  104. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  105. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  106. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  107. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  108. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  109. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/py.typed +0 -0
  110. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  111. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/retry.py +0 -0
  112. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  113. {cmpnd-0.78.0 → cmpnd-0.79.0}/ingest/pyproject.toml +0 -0
  114. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/audit-sdist.sh +0 -0
  115. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/capture_review_run.py +0 -0
  116. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/check-pip-install.sh +0 -0
  117. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/check_release_artifacts.py +0 -0
  118. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/fixtures/review_run.json.gz +0 -0
  119. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/gepa_resume_bug.py +0 -0
  120. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/install-test-env.sh +0 -0
  121. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/release-gate.sh +0 -0
  122. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/release-real-models.sh +0 -0
  123. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/require_version_bump.py +0 -0
  124. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/seed_review_run.py +0 -0
  125. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/selfhost_compat.py +0 -0
  126. {cmpnd-0.78.0 → cmpnd-0.79.0}/scripts/test-in-linux.sh +0 -0
  127. {cmpnd-0.78.0 → cmpnd-0.79.0}/stubs/dspy/__init__.pyi +0 -0
  128. {cmpnd-0.78.0 → cmpnd-0.79.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  129. {cmpnd-0.78.0 → cmpnd-0.79.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  130. {cmpnd-0.78.0 → cmpnd-0.79.0}/stubs/dspy/utils/__init__.pyi +0 -0
  131. {cmpnd-0.78.0 → cmpnd-0.79.0}/stubs/dspy/utils/callback.pyi +0 -0
  132. {cmpnd-0.78.0 → cmpnd-0.79.0}/stubs/dspy/utils/dummies.pyi +0 -0
  133. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/__init__.py +0 -0
  134. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_credential_route.py +0 -0
  135. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_deployment_signature_helpers.py +0 -0
  136. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_exporter_helpers.py +0 -0
  137. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_fake_clock.py +0 -0
  138. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_identity_helpers.py +0 -0
  139. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_resolve_refs.py +0 -0
  140. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/_traced_run.py +0 -0
  141. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/conftest.py +0 -0
  142. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/__init__.py +0 -0
  143. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/committee_task.py +0 -0
  144. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/conftest.py +0 -0
  145. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/continuation_task.py +0 -0
  146. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  147. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  148. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/fake_lm.py +0 -0
  149. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/helpers.py +0 -0
  150. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/target_capabilities.py +0 -0
  151. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_assessments_cli.py +0 -0
  152. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_capture_prompts.py +0 -0
  153. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_composite_module.py +0 -0
  154. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  155. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_deploy_execute.py +0 -0
  156. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_deploy_pandas.py +0 -0
  157. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_deploy_programs.py +0 -0
  158. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_edge_cases.py +0 -0
  159. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_example_hash.py +0 -0
  160. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_gepa_optimization.py +0 -0
  161. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_interpreter_spans.py +0 -0
  162. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_lm_accuracy.py +0 -0
  163. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_module_tracing.py +0 -0
  164. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimization_lineage.py +0 -0
  165. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  166. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
  167. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_continuation.py +0 -0
  168. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
  169. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_failures.py +0 -0
  170. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_loop.py +0 -0
  171. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  172. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
  173. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_parallel_export.py +0 -0
  174. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_project_attribution.py +0 -0
  175. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_react_tool_spans.py +0 -0
  176. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_save_load.py +0 -0
  177. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_trace_structure.py +0 -0
  178. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_traces_read.py +0 -0
  179. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_user_attribution.py +0 -0
  180. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/e2e/test_valsets_cli.py +0 -0
  181. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  182. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  183. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  184. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  185. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  186. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  187. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  188. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  189. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  190. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/10_react.json +0 -0
  191. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/11_refine.json +0 -0
  192. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/12_retrieve.json +0 -0
  193. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/13_knn.json +0 -0
  194. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/14_parallel.json +0 -0
  195. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/identity_vectors/README.md +0 -0
  196. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/ingest_conformance.py +0 -0
  197. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/__init__.py +0 -0
  198. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/authored_optimize/judge.py +0 -0
  199. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  200. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/conftest.py +0 -0
  201. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
  202. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/hosted_optimize_probe.py +0 -0
  203. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/optimization_run_probe.py +0 -0
  204. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  205. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/test_logs_renders_traces.py +0 -0
  206. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/test_optimization_run.py +0 -0
  207. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/test_optimizing_progress.py +0 -0
  208. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/integration/test_unhappy_path.py +0 -0
  209. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/__init__.py +0 -0
  210. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/__main__.py +0 -0
  211. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/drain.py +0 -0
  212. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/ingest.py +0 -0
  213. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/latency_transport.py +0 -0
  214. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/rlm_shape.py +0 -0
  215. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/rlm_size_report.py +0 -0
  216. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/sweep.py +0 -0
  217. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/test_rlm_shape.py +0 -0
  218. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/load/test_rlm_size_report.py +0 -0
  219. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/__init__.py +0 -0
  220. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/conftest.py +0 -0
  221. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/seed_parity.py +0 -0
  222. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_auth.py +0 -0
  223. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_datasets.py +0 -0
  224. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_deployments.py +0 -0
  225. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_evals.py +0 -0
  226. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_health.py +0 -0
  227. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_modules.py +0 -0
  228. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_optimizations.py +0 -0
  229. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_programs.py +0 -0
  230. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_signatures.py +0 -0
  231. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_trace_streaming.py +0 -0
  232. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/parity/test_traces.py +0 -0
  233. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/__init__.py +0 -0
  234. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/_provider.py +0 -0
  235. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/_readiness.py +0 -0
  236. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/_reliability.py +0 -0
  237. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/_result.py +0 -0
  238. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/mint_bedrock_token.py +0 -0
  239. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_bedrock_converse.py +0 -0
  240. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_deploy_programs.py +0 -0
  241. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_multi_client_stress.py +0 -0
  242. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_optimize_client_committee.py +0 -0
  243. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_optimize_continuation.py +0 -0
  244. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_optimize_loop.py +0 -0
  245. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
  246. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_optimize_stress.py +0 -0
  247. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_provider_roles.py +0 -0
  248. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_readiness.py +0 -0
  249. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_real_provider_twins.py +0 -0
  250. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_reliability.py +0 -0
  251. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_reliability_classify.py +0 -0
  252. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_rlm_wasm.py +0 -0
  253. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/real_models/test_trace_search.py +0 -0
  254. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/span_reference_fixture.py +0 -0
  255. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_adapter_reentrancy.py +0 -0
  256. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_assessments_api.py +0 -0
  257. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_authored.py +0 -0
  258. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_authored_binding_credentials.py +0 -0
  259. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_authored_bundle_collisions.py +0 -0
  260. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_authored_metric_contract.py +0 -0
  261. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_authored_named_models.py +0 -0
  262. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_authored_optimize.py +0 -0
  263. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_callback.py +0 -0
  264. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_candidate_lineage.py +0 -0
  265. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/__init__.py +0 -0
  266. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/conftest.py +0 -0
  267. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_api_client.py +0 -0
  268. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_assessments.py +0 -0
  269. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_auth.py +0 -0
  270. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_credentials.py +0 -0
  271. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_datasets.py +0 -0
  272. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_deployment_runs.py +0 -0
  273. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_deployments.py +0 -0
  274. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_evals.py +0 -0
  275. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_login.py +0 -0
  276. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_main.py +0 -0
  277. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_optimizations.py +0 -0
  278. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_org.py +0 -0
  279. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_pagination.py +0 -0
  280. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_parity.py +0 -0
  281. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_programs.py +0 -0
  282. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_provider_credentials.py +0 -0
  283. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_schema_sample.py +0 -0
  284. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_shell.py +0 -0
  285. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_tool_servers.py +0 -0
  286. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_top.py +0 -0
  287. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_traces.py +0 -0
  288. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
  289. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  290. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_tree_help.py +0 -0
  291. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cli/test_valsets.py +0 -0
  292. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_client.py +0 -0
  293. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_client_floor.py +0 -0
  294. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_client_program_names.py +0 -0
  295. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_clustering/__init__.py +0 -0
  296. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_clustering/conftest.py +0 -0
  297. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_clustering/test_edge_cases.py +0 -0
  298. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  299. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_clustering/test_type_conversion.py +0 -0
  300. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_cmp551_grouping_identity.py +0 -0
  301. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_configuration.py +0 -0
  302. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_context.py +0 -0
  303. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_context_propagation.py +0 -0
  304. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_credential_kwargs.py +0 -0
  305. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_credential_selection.py +0 -0
  306. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_credential_values.py +0 -0
  307. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_dataset_polling.py +0 -0
  308. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_dataset_sync.py +0 -0
  309. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_datasets.py +0 -0
  310. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_decision_client_spans.py +0 -0
  311. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_decorators.py +0 -0
  312. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_deploy.py +0 -0
  313. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_deploy_mcp_tool_references.py +0 -0
  314. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_deploy_program_id.py +0 -0
  315. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_deployment_metadata.py +0 -0
  316. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_deployment_runs.py +0 -0
  317. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_deployments_read.py +0 -0
  318. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_eval.py +0 -0
  319. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_eval_example_attribution.py +0 -0
  320. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_eval_program_id.py +0 -0
  321. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_eval_start.py +0 -0
  322. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_eval_trace_grouping.py +0 -0
  323. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_exception_paths.py +0 -0
  324. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_execute.py +0 -0
  325. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_execute_run_identity.py +0 -0
  326. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_exporter.py +0 -0
  327. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_exporter_program_names.py +0 -0
  328. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_exporter_queue.py +0 -0
  329. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_exporter_real.py +0 -0
  330. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_fake_lm.py +0 -0
  331. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_gepa_callback.py +0 -0
  332. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_gepa_integration.py +0 -0
  333. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_gepa_output_normalization.py +0 -0
  334. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_gepa_resume.py +0 -0
  335. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_identity.py +0 -0
  336. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_imaging.py +0 -0
  337. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_import_weight.py +0 -0
  338. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_ingest_conformance.py +0 -0
  339. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_ingest_second_producer.py +0 -0
  340. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_integration.py +0 -0
  341. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_interpreter_callback.py +0 -0
  342. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_ir_encoder_properties.py +0 -0
  343. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_ir_golden_vectors.py +0 -0
  344. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_ir_roundtrip.py +0 -0
  345. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_lm15_native_calls.py +0 -0
  346. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_lm_configuration.py +0 -0
  347. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_lm_usage_shapes.py +0 -0
  348. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_mcp_tools.py +0 -0
  349. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_models.py +0 -0
  350. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_multi_client_stress_readiness.py +0 -0
  351. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_no_signature_hash_on_the_wire.py +0 -0
  352. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimization_phase_callback.py +0 -0
  353. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimization_program_names.py +0 -0
  354. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimization_progress.py +0 -0
  355. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimization_start.py +0 -0
  356. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize.py +0 -0
  357. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize_budget.py +0 -0
  358. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize_lift.py +0 -0
  359. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize_lms.py +0 -0
  360. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize_proposer.py +0 -0
  361. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize_reflection_lm.py +0 -0
  362. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_optimize_terminal_failure.py +0 -0
  363. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_packaging.py +0 -0
  364. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_packaging_callable_source.py +0 -0
  365. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_packaging_mcp_tools.py +0 -0
  366. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_packaging_program_source.py +0 -0
  367. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_poll_until.py +0 -0
  368. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_program_id_deprecation.py +0 -0
  369. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_program_identity.py +0 -0
  370. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_program_lineage_persist.py +0 -0
  371. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_program_names_in_deploy.py +0 -0
  372. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_program_naming.py +0 -0
  373. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_programs_create.py +0 -0
  374. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_project_payload.py +0 -0
  375. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_real_provider_twins_readiness.py +0 -0
  376. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_reflector_properties.py +0 -0
  377. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_reflector_smoke.py +0 -0
  378. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_release_gate_script.py +0 -0
  379. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_release_real_models_script.py +0 -0
  380. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_replaced_names.py +0 -0
  381. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_repro_reactv2_bugs.py +0 -0
  382. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_require_version_bump.py +0 -0
  383. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_retry.py +0 -0
  384. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_reversible_failures.py +0 -0
  385. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_rlm_patch.py +0 -0
  386. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_run_attribution_paths.py +0 -0
  387. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_runtime_tools.py +0 -0
  388. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_schemas.py +0 -0
  389. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_seal_lm_credential.py +0 -0
  390. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_seed_review_run.py +0 -0
  391. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_signature_inputs.py +0 -0
  392. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_span_references.py +0 -0
  393. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_span_sent_once.py +0 -0
  394. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_system_one.py +0 -0
  395. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_trace_context_concurrency.py +0 -0
  396. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_trace_fact_wire_contract.py +0 -0
  397. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_trace_facts.py +0 -0
  398. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_trace_render.py +0 -0
  399. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_traces_read.py +0 -0
  400. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_tracked_gepa.py +0 -0
  401. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_tracker_enrich.py +0 -0
  402. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_truncation.py +0 -0
  403. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_upload_auth_headers.py +0 -0
  404. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_valsets_api.py +0 -0
  405. {cmpnd-0.78.0 → cmpnd-0.79.0}/tests/test_xxh64.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.78.0
3
+ Version: 0.79.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>
@@ -182,8 +182,14 @@ def _register_user(sub: _SubParsersAction[ArgumentParser]) -> None:
182
182
  create.add_argument("--admin", dest="admin", action="store_true", help="Grant platform-admin")
183
183
  create.set_defaults(func=handle_user_create)
184
184
 
185
- approve = usub.add_parser("approve", help="Approve a pending signup")
185
+ approve = usub.add_parser("approve", help="Approve a pending membership")
186
186
  approve.add_argument("id", help="User id")
187
+ approve.add_argument(
188
+ "--org-id",
189
+ dest="org_id",
190
+ default="",
191
+ help="Org whose membership to approve (default: the user's active org)",
192
+ )
187
193
  approve.set_defaults(func=handle_user_approve)
188
194
 
189
195
  promote = usub.add_parser("promote", help="Grant platform-admin")
@@ -457,7 +463,30 @@ def handle_user_create(client: api_client.ApiClient, args: Any) -> Any:
457
463
 
458
464
 
459
465
  def handle_user_approve(client: api_client.ApiClient, args: Any) -> Any:
460
- return client.patch(f"/api/v1/admin/users/{args.id}", json={"is_approved": True})
466
+ user_path = f"/api/v1/admin/users/{args.id}"
467
+ org_id = args.org_id or client.get(user_path)["org_id"]
468
+ try:
469
+ return client.post(f"{user_path}/approve", json={"org_id": org_id})
470
+ except api_client.CliError as err:
471
+ if not _route_unmounted(err):
472
+ raise
473
+ # A server older than the approve route approves only the active org,
474
+ # through PATCH.
475
+ if args.org_id:
476
+ raise api_client.CliError(
477
+ "This server cannot approve a membership in a named org. Upgrade it, or omit --org-id "
478
+ "to approve the membership in the user's active org."
479
+ ) from err
480
+ return client.patch(user_path, json={"is_approved": True})
481
+
482
+
483
+ def _route_unmounted(err: api_client.CliError) -> bool:
484
+ """Whether a 404 came from a server that has no such route.
485
+
486
+ Go's ServeMux answers an unmounted route with plain text. A mounted route's
487
+ own 404 is JSON, such as an approval for a membership that does not exist.
488
+ """
489
+ return err.status_code == 404 and "404 page not found" in str(err)
461
490
 
462
491
 
463
492
  def handle_user_promote(client: api_client.ApiClient, args: Any) -> Any:
@@ -494,6 +494,8 @@ stores one key per org per endpoint in `~/.config/cmpnd/credentials.json`, or
494
494
  `$CMPND_CONFIG_DIR/credentials.json` when that variable is set. The file has
495
495
  mode 0600. An active pointer names the org whose key commands use.
496
496
  `cmpnd login` stores a new key beside the others and makes its org active.
497
+ When you belong to more than one org, the approval page asks which org the
498
+ key is for and starts on your active org in the web app.
497
499
 
498
500
  - `cmpnd login --org <slug-or-id>` mints a key for that org instead of the
499
501
  active one. The approval page names the org, and serve refuses an org where
@@ -891,6 +893,14 @@ EMAIL` withdraws the open owner invites sent to that address, and the links
891
893
  stop working. `cmpnd admin org show` lists pending addresses under
892
894
  `seed.pending_owner_emails`.
893
895
 
896
+ `cmpnd admin user approve USER_ID --org-id ORG_ID` approves the user's pending
897
+ membership in that org, which need not be their active org. Without
898
+ `--org-id` it approves the membership in their active org, and a server
899
+ older than the approve route approves it the way older releases did. Serve applies the
900
+ operator queue's rules. A member waiting to join an org that has its own owner
901
+ belongs to that owner's queue, so serve refuses it with 400. `cmpnd admin user
902
+ reject USER_ID --org-id ORG_ID` declines a pending membership.
903
+
894
904
  ### Plans, limits and signups
895
905
 
896
906
  Every org has a plan, `free`, `pro` or `enterprise`, and each plan sets
@@ -5,7 +5,7 @@ name = "cmpnd"
5
5
  # it's new) — no git tags. Bump with `uv version --bump {minor,patch}` or by
6
6
  # hand. Runtime `cmpnd.__version__` reads installed metadata, so it tracks
7
7
  # this automatically. See docs/plans/2026-07-02-sdk-pypi-tag-free-publish.md.
8
- version = "0.78.0"
8
+ version = "0.79.0"
9
9
  description = "DSPy observability and deployment SDK for cmpnd"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.11"
@@ -2,8 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
5
6
  from argparse import Namespace
7
+ from collections.abc import Callable
8
+ from unittest import mock
6
9
 
10
+ import httpx
11
+ import pytest
12
+
13
+ from cmpnd.cli import api_client
7
14
  from cmpnd.cli.commands import admin
8
15
 
9
16
 
@@ -183,11 +190,15 @@ class TestAdminUser:
183
190
  },
184
191
  )
185
192
 
186
- def test_approve_patches_is_approved(self, mock_client):
187
- mock_client.patch.return_value = {"id": "u_1", "is_approved": True}
188
- result = admin.handle_user_approve(mock_client, Namespace(id="u_1"))
189
- mock_client.patch.assert_called_once_with("/api/v1/admin/users/u_1", json={"is_approved": True})
190
- assert result["is_approved"] is True
193
+ def test_approve_parser_takes_an_optional_org(self):
194
+ from argparse import ArgumentParser
195
+
196
+ parser = ArgumentParser()
197
+ admin.register(parser.add_subparsers())
198
+ args = parser.parse_args(["admin", "user", "approve", "u_1", "--org-id", "o_2"])
199
+ assert args.org_id == "o_2"
200
+ assert args.func is admin.handle_user_approve
201
+ assert parser.parse_args(["admin", "user", "approve", "u_1"]).org_id == ""
191
202
 
192
203
  def test_promote_patches_is_admin_true(self, mock_client):
193
204
  mock_client.patch.return_value = {"id": "u_1", "is_admin": True}
@@ -413,3 +424,78 @@ class TestAdminSignup:
413
424
  with pytest.raises(SystemExit):
414
425
  args.func(mock_client, args)
415
426
  mock_client.patch.assert_not_called()
427
+
428
+
429
+ def _serve(answer: Callable[[httpx.Request], httpx.Response]):
430
+ """A real ApiClient over a captured transport: `sent` collects each request."""
431
+ sent: list[httpx.Request] = []
432
+
433
+ def handle(request: httpx.Request) -> httpx.Response:
434
+ sent.append(request)
435
+ return answer(request)
436
+
437
+ real = httpx.Client
438
+ patch = mock.patch("httpx.Client", lambda **kwargs: real(**kwargs, transport=httpx.MockTransport(handle)))
439
+ return api_client.ApiClient("k", "http://serve.test"), sent, patch
440
+
441
+
442
+ def _wire(sent: list[httpx.Request]) -> list[tuple[str, str, object]]:
443
+ return [(r.method, r.url.path, json.loads(r.content) if r.content else None) for r in sent]
444
+
445
+
446
+ # Go's ServeMux answers an unmounted route with this plain-text 404.
447
+ _UNMOUNTED = httpx.Response(404, text="404 page not found\n")
448
+
449
+
450
+ class TestAdminUserApproveWire:
451
+ def test_approve_posts_the_named_org(self):
452
+ client, sent, patch = _serve(lambda _r: httpx.Response(200, json={"newly_approved": True}))
453
+ with patch:
454
+ result = admin.handle_user_approve(client, _parse("user", "approve", "u_1", "--org-id", "o_2"))
455
+ assert _wire(sent) == [("POST", "/api/v1/admin/users/u_1/approve", {"org_id": "o_2"})]
456
+ assert result["newly_approved"] is True
457
+
458
+ def test_approve_without_org_approves_the_active_org(self):
459
+ def answer(request: httpx.Request) -> httpx.Response:
460
+ if request.method == "GET":
461
+ return httpx.Response(200, json={"id": "u_1", "org_id": "o_1"})
462
+ return httpx.Response(200, json={"newly_approved": True})
463
+
464
+ client, sent, patch = _serve(answer)
465
+ with patch:
466
+ admin.handle_user_approve(client, _parse("user", "approve", "u_1"))
467
+ assert _wire(sent) == [
468
+ ("GET", "/api/v1/admin/users/u_1", None),
469
+ ("POST", "/api/v1/admin/users/u_1/approve", {"org_id": "o_1"}),
470
+ ]
471
+
472
+ def test_approve_without_org_falls_back_to_patch_on_a_server_without_the_route(self):
473
+ def answer(request: httpx.Request) -> httpx.Response:
474
+ if request.method == "GET":
475
+ return httpx.Response(200, json={"id": "u_1", "org_id": "o_1"})
476
+ if request.method == "POST":
477
+ return _UNMOUNTED
478
+ return httpx.Response(200, json={"id": "u_1", "is_approved": True})
479
+
480
+ client, sent, patch = _serve(answer)
481
+ with patch:
482
+ result = admin.handle_user_approve(client, _parse("user", "approve", "u_1"))
483
+ assert _wire(sent)[-1] == ("PATCH", "/api/v1/admin/users/u_1", {"is_approved": True})
484
+ assert result["is_approved"] is True
485
+
486
+ def test_approve_with_org_on_a_server_without_the_route_says_so(self):
487
+ client, sent, patch = _serve(lambda _r: _UNMOUNTED)
488
+ with patch, pytest.raises(api_client.CliError, match="--org-id"):
489
+ admin.handle_user_approve(client, _parse("user", "approve", "u_1", "--org-id", "o_2"))
490
+ assert [r.method for r in sent] == ["POST"]
491
+
492
+ def test_a_missing_membership_is_not_mistaken_for_an_old_server(self):
493
+ def answer(request: httpx.Request) -> httpx.Response:
494
+ if request.method == "GET":
495
+ return httpx.Response(200, json={"id": "u_1", "org_id": "o_1"})
496
+ return httpx.Response(404, json={"error": "no membership for that user in that org"})
497
+
498
+ client, sent, patch = _serve(answer)
499
+ with patch, pytest.raises(api_client.CliError, match="no membership"):
500
+ admin.handle_user_approve(client, _parse("user", "approve", "u_1"))
501
+ assert [r.method for r in sent] == ["GET", "POST"]
@@ -505,7 +505,7 @@ wheels = [
505
505
 
506
506
  [[package]]
507
507
  name = "cmpnd"
508
- version = "0.78.0"
508
+ version = "0.79.0"
509
509
  source = { editable = "." }
510
510
  default-groups = ["dspy-3-4-1"]
511
511
  dependencies = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes