synth-optimizers 0.2.9.dev20260814__tar.gz → 0.2.12__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.
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/Cargo.lock +5 -5
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/Cargo.toml +1 -1
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/PKG-INFO +15 -5
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/README.md +14 -4
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/pyproject.toml +1 -1
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/openapi/gepa-service-v1.yaml +41 -1
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/service.rs +258 -1
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/config.rs +4 -2
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/__init__.py +10 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/algorithms/20-proposer-and-policies.md +1 -1
- synth_optimizers-0.2.12/src/synth_optimizers/future_algorithms.py +39 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/hosted.py +20 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/Cargo.toml +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/README.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/codex_app_server.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/jesterky_workflow.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/lib.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/machines.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/pipeline.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/planner.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/prompting_best_practices.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/runtime.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/Cargo.toml +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/README.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/README.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/app_server.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/codex_home.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/daytona.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/docker.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/jsonrpc_read_window.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/limits.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/local.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/mod.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/nano.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/role_agent.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/session.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/substrate.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/supervisor.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/agent_runtime/usage.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/artifact_store.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/artifacts.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/cache.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/candidates.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/checkpoints.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/configured_limits.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/container_contract.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/data_models.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/disk_budget.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/error.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/event_visualization.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/events.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/evidence.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/failures.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/fsm.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/http.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/invariants.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/jesterky.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/jobs.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/levers.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/lib.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/limit_engine.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/limits.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/observability.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/operations.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/process.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/projections.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/prompt_program.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/registry.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/resources.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/rollouts.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/runtime_records.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/scores.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/sensors.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/state_machine.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/stopper.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/storage_maintenance.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/usage.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizer_platform/src/workspace.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizers_py/Cargo.toml +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizers_py/README.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_optimizers_py/src/lib.rs +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/README.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/_synth_optimizers.pyi +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/board_server.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/cli.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/discovery.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gelo/00-index.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gelo/10-cli.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gelo/20-sdk.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gelo/30-hosted.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gelo/containers/00-overview.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gelo/containers/20-contract.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/00-index.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/10-cli.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/20-sdk.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/algorithms/00-overview.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/algorithms/10-pipeline-modes.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/assets/synth-logo.png +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/containers/00-overview.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/containers/10-catalog.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs/gepa/containers/20-contract.md +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs_server.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/eval_stats.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/gelo.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/gepa.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/hosted_config.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/o11y.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/observability.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/py.typed +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/sdk.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/tunnels.py +0 -0
- {synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/victorialogs.py +0 -0
|
@@ -1306,7 +1306,7 @@ dependencies = [
|
|
|
1306
1306
|
|
|
1307
1307
|
[[package]]
|
|
1308
1308
|
name = "synth_gepa"
|
|
1309
|
-
version = "0.2.
|
|
1309
|
+
version = "0.2.12"
|
|
1310
1310
|
dependencies = [
|
|
1311
1311
|
"base64",
|
|
1312
1312
|
"fs2",
|
|
@@ -1321,7 +1321,7 @@ dependencies = [
|
|
|
1321
1321
|
|
|
1322
1322
|
[[package]]
|
|
1323
1323
|
name = "synth_mapo"
|
|
1324
|
-
version = "0.2.
|
|
1324
|
+
version = "0.2.12"
|
|
1325
1325
|
dependencies = [
|
|
1326
1326
|
"serde",
|
|
1327
1327
|
"serde_json",
|
|
@@ -1333,7 +1333,7 @@ dependencies = [
|
|
|
1333
1333
|
|
|
1334
1334
|
[[package]]
|
|
1335
1335
|
name = "synth_marl_promptopt"
|
|
1336
|
-
version = "0.2.
|
|
1336
|
+
version = "0.2.12"
|
|
1337
1337
|
dependencies = [
|
|
1338
1338
|
"clap",
|
|
1339
1339
|
"serde",
|
|
@@ -1347,7 +1347,7 @@ dependencies = [
|
|
|
1347
1347
|
|
|
1348
1348
|
[[package]]
|
|
1349
1349
|
name = "synth_optimizer_platform"
|
|
1350
|
-
version = "0.2.
|
|
1350
|
+
version = "0.2.12"
|
|
1351
1351
|
dependencies = [
|
|
1352
1352
|
"fs2",
|
|
1353
1353
|
"libc",
|
|
@@ -1364,7 +1364,7 @@ dependencies = [
|
|
|
1364
1364
|
|
|
1365
1365
|
[[package]]
|
|
1366
1366
|
name = "synth_optimizers_py"
|
|
1367
|
-
version = "0.2.
|
|
1367
|
+
version = "0.2.12"
|
|
1368
1368
|
dependencies = [
|
|
1369
1369
|
"pyo3",
|
|
1370
1370
|
"serde_json",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: synth-optimizers
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.12
|
|
4
4
|
Requires-Dist: pydantic>=2.0.0
|
|
5
5
|
Requires-Dist: synth-containers==0.4.1.dev20260814
|
|
6
6
|
Requires-Dist: websocket-client>=1.8.0
|
|
@@ -43,12 +43,22 @@ contract.
|
|
|
43
43
|
| --- | --- | --- | --- |
|
|
44
44
|
| **GEPA** — reflective prompt evolution | Supported | [`rust/crates/synth_gepa/`](rust/crates/synth_gepa/) (Rust engine + service), [`src/synth_optimizers/gepa.py`](src/synth_optimizers/gepa.py) (Python API), [`skills/gepa/SKILL.md`](skills/gepa/SKILL.md) (agent runbook) | [Paper](https://arxiv.org/abs/2507.19457) · [gepa-ai docs](https://gepa-ai.github.io/gepa/) · bundled HTML via `gepa console` |
|
|
45
45
|
| **GELO** — Go-Explore in prompt space (hosted) | Hosted submit | [`src/synth_optimizers/gelo.py`](src/synth_optimizers/gelo.py), [`skills/gelo/SKILL.md`](skills/gelo/SKILL.md), [`GELO_HOSTED_SDK_CLI_SPEC.md`](GELO_HOSTED_SDK_CLI_SPEC.md) | Bundled HTML via `gelo console` — [`src/synth_optimizers/docs/gelo/`](src/synth_optimizers/docs/gelo/) |
|
|
46
|
+
| **SFT** — supervised fine-tuning (hosted) | Hosted submit | `HostedOptimizerClient.submit_sft()` / `submit_sft()` | Executed by the private Optimizers-beta runtime; the public client uses the shared hosted run API. |
|
|
46
47
|
|
|
47
48
|
The shared [`synth_optimizer_platform`](rust/crates/synth_optimizer_platform/)
|
|
48
49
|
crate is the substrate for optimizer implementations; GEPA is the first public
|
|
49
|
-
local algorithm; GELO
|
|
50
|
-
hosted optimizer infrastructure.
|
|
51
|
-
|
|
50
|
+
local algorithm; GELO and SFT are hosted-only in the public package and run on
|
|
51
|
+
Synth hosted optimizer infrastructure. Hosted GEPA, GELO, and SFT submission is
|
|
52
|
+
covered in [`docs/hosted-optimizers.md`](docs/hosted-optimizers.md).
|
|
53
|
+
|
|
54
|
+
## Future hosted-algorithm compatibility
|
|
55
|
+
|
|
56
|
+
MAPO, OHCO, Online Reflexion, and MARL prompt-optimization identifiers are retained
|
|
57
|
+
in [`future_algorithms.py`](src/synth_optimizers/future_algorithms.py) so clients can
|
|
58
|
+
parse hosted catalogs and historical runs. They are **not supported public optimizer
|
|
59
|
+
algorithms**: they carry no local executor, cookbook, or release commitment. New
|
|
60
|
+
public algorithms graduate into the table above only after their public API contract,
|
|
61
|
+
replay semantics, and end-to-end evidence are ready.
|
|
52
62
|
|
|
53
63
|
## Install
|
|
54
64
|
|
|
@@ -173,7 +183,7 @@ policy can stay on OpenAI. See [skills/gepa/SKILL.md](skills/gepa/SKILL.md) for
|
|
|
173
183
|
|
|
174
184
|
- **OpenAI API key proposer** — run-local Codex home; does not use your host `~/.codex` login.
|
|
175
185
|
- **OpenRouter proposer** — provider-aware Codex config and base URL; OpenRouter works for policy rollouts too.
|
|
176
|
-
- **ChatGPT subscription proposer** — `auth_mode = "chatgpt"` with required `codex_home` (OAuth via [Codex CLI](https://github.com/openai/codex) or [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth)); models include `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.3-codex-spark`, `gpt-5.5`; proposer usage is $0, policy rollouts still bill normally.
|
|
186
|
+
- **ChatGPT subscription proposer** — `auth_mode = "chatgpt"` with required `codex_home` (OAuth via [Codex CLI](https://github.com/openai/codex) or [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth)); models include `gpt-5.4-mini`, `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.3-codex-spark`, `gpt-5.5`, `gpt-5.6-luna`, `gpt-5.6-sol`, and `gpt-5.6-terra`; proposer usage is $0, policy rollouts still bill normally.
|
|
177
187
|
- **Nano-Codex proposer harness** — explicit `[proposer.nano_codex]` opt-in keeps one ChatGPT-authenticated app-server session warm across compatible GEPA generations, caches static task/program context by content digest, records monotonic JSONL events and typed turn receipts, and can replay receipts with zero live model or tool calls. See [`dev_examples/nano_codex_gepa/`](dev_examples/nano_codex_gepa/).
|
|
178
188
|
- **Live usage** — `SYNTH_OPTIMIZERS_TERMINAL=1` prints running token and cost splits (`usage total=… policy=… proposer=…`).
|
|
179
189
|
- **Docker proposer** — `runtime_substrate = "docker"` with `[proposer.docker].image`; workspaces stage under `~/.cache/synth-gepa-docker-workspaces/`, sync back, then cleanup; image: `docker/codex-gepa-proposer/Dockerfile`.
|
|
@@ -21,12 +21,22 @@ contract.
|
|
|
21
21
|
| --- | --- | --- | --- |
|
|
22
22
|
| **GEPA** — reflective prompt evolution | Supported | [`rust/crates/synth_gepa/`](rust/crates/synth_gepa/) (Rust engine + service), [`src/synth_optimizers/gepa.py`](src/synth_optimizers/gepa.py) (Python API), [`skills/gepa/SKILL.md`](skills/gepa/SKILL.md) (agent runbook) | [Paper](https://arxiv.org/abs/2507.19457) · [gepa-ai docs](https://gepa-ai.github.io/gepa/) · bundled HTML via `gepa console` |
|
|
23
23
|
| **GELO** — Go-Explore in prompt space (hosted) | Hosted submit | [`src/synth_optimizers/gelo.py`](src/synth_optimizers/gelo.py), [`skills/gelo/SKILL.md`](skills/gelo/SKILL.md), [`GELO_HOSTED_SDK_CLI_SPEC.md`](GELO_HOSTED_SDK_CLI_SPEC.md) | Bundled HTML via `gelo console` — [`src/synth_optimizers/docs/gelo/`](src/synth_optimizers/docs/gelo/) |
|
|
24
|
+
| **SFT** — supervised fine-tuning (hosted) | Hosted submit | `HostedOptimizerClient.submit_sft()` / `submit_sft()` | Executed by the private Optimizers-beta runtime; the public client uses the shared hosted run API. |
|
|
24
25
|
|
|
25
26
|
The shared [`synth_optimizer_platform`](rust/crates/synth_optimizer_platform/)
|
|
26
27
|
crate is the substrate for optimizer implementations; GEPA is the first public
|
|
27
|
-
local algorithm; GELO
|
|
28
|
-
hosted optimizer infrastructure.
|
|
29
|
-
|
|
28
|
+
local algorithm; GELO and SFT are hosted-only in the public package and run on
|
|
29
|
+
Synth hosted optimizer infrastructure. Hosted GEPA, GELO, and SFT submission is
|
|
30
|
+
covered in [`docs/hosted-optimizers.md`](docs/hosted-optimizers.md).
|
|
31
|
+
|
|
32
|
+
## Future hosted-algorithm compatibility
|
|
33
|
+
|
|
34
|
+
MAPO, OHCO, Online Reflexion, and MARL prompt-optimization identifiers are retained
|
|
35
|
+
in [`future_algorithms.py`](src/synth_optimizers/future_algorithms.py) so clients can
|
|
36
|
+
parse hosted catalogs and historical runs. They are **not supported public optimizer
|
|
37
|
+
algorithms**: they carry no local executor, cookbook, or release commitment. New
|
|
38
|
+
public algorithms graduate into the table above only after their public API contract,
|
|
39
|
+
replay semantics, and end-to-end evidence are ready.
|
|
30
40
|
|
|
31
41
|
## Install
|
|
32
42
|
|
|
@@ -151,7 +161,7 @@ policy can stay on OpenAI. See [skills/gepa/SKILL.md](skills/gepa/SKILL.md) for
|
|
|
151
161
|
|
|
152
162
|
- **OpenAI API key proposer** — run-local Codex home; does not use your host `~/.codex` login.
|
|
153
163
|
- **OpenRouter proposer** — provider-aware Codex config and base URL; OpenRouter works for policy rollouts too.
|
|
154
|
-
- **ChatGPT subscription proposer** — `auth_mode = "chatgpt"` with required `codex_home` (OAuth via [Codex CLI](https://github.com/openai/codex) or [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth)); models include `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.3-codex-spark`, `gpt-5.5`; proposer usage is $0, policy rollouts still bill normally.
|
|
164
|
+
- **ChatGPT subscription proposer** — `auth_mode = "chatgpt"` with required `codex_home` (OAuth via [Codex CLI](https://github.com/openai/codex) or [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth)); models include `gpt-5.4-mini`, `gpt-5.4`, `gpt-5.3-codex`, `gpt-5.3-codex-spark`, `gpt-5.5`, `gpt-5.6-luna`, `gpt-5.6-sol`, and `gpt-5.6-terra`; proposer usage is $0, policy rollouts still bill normally.
|
|
155
165
|
- **Nano-Codex proposer harness** — explicit `[proposer.nano_codex]` opt-in keeps one ChatGPT-authenticated app-server session warm across compatible GEPA generations, caches static task/program context by content digest, records monotonic JSONL events and typed turn receipts, and can replay receipts with zero live model or tool calls. See [`dev_examples/nano_codex_gepa/`](dev_examples/nano_codex_gepa/).
|
|
156
166
|
- **Live usage** — `SYNTH_OPTIMIZERS_TERMINAL=1` prints running token and cost splits (`usage total=… policy=… proposer=…`).
|
|
157
167
|
- **Docker proposer** — `runtime_substrate = "docker"` with `[proposer.docker].image`; workspaces stage under `~/.cache/synth-gepa-docker-workspaces/`, sync back, then cleanup; image: `docker/codex-gepa-proposer/Dockerfile`.
|
|
@@ -32,6 +32,28 @@ servers:
|
|
|
32
32
|
description: Local single-workspace server
|
|
33
33
|
|
|
34
34
|
paths:
|
|
35
|
+
/v1/optimizer/capabilities:
|
|
36
|
+
get:
|
|
37
|
+
operationId: getOptimizerCapabilities
|
|
38
|
+
summary: Advertise Workshop optimizer compatibility
|
|
39
|
+
responses:
|
|
40
|
+
'200':
|
|
41
|
+
description: Optimizer algorithms, recipes, and runtime capabilities.
|
|
42
|
+
content:
|
|
43
|
+
application/json:
|
|
44
|
+
schema: { $ref: '#/components/schemas/OptimizerCapabilities' }
|
|
45
|
+
|
|
46
|
+
/v1/optimizer/status:
|
|
47
|
+
get:
|
|
48
|
+
operationId: getOptimizerStatus
|
|
49
|
+
summary: Return the Workshop-compatible optimizer status document
|
|
50
|
+
responses:
|
|
51
|
+
'200':
|
|
52
|
+
description: Alias of the optimizer capability document for compatibility.
|
|
53
|
+
content:
|
|
54
|
+
application/json:
|
|
55
|
+
schema: { $ref: '#/components/schemas/OptimizerCapabilities' }
|
|
56
|
+
|
|
35
57
|
# ---------------------------------------------------------------------------
|
|
36
58
|
# Submission + lifecycle
|
|
37
59
|
# ---------------------------------------------------------------------------
|
|
@@ -648,7 +670,6 @@ paths:
|
|
|
648
670
|
|
|
649
671
|
# =============================================================================
|
|
650
672
|
components:
|
|
651
|
-
|
|
652
673
|
parameters:
|
|
653
674
|
RunId:
|
|
654
675
|
name: run_id
|
|
@@ -698,6 +719,25 @@ components:
|
|
|
698
719
|
schema: { $ref: '#/components/schemas/ErrorEnvelope' }
|
|
699
720
|
|
|
700
721
|
schemas:
|
|
722
|
+
OptimizerCapabilities:
|
|
723
|
+
type: object
|
|
724
|
+
required: [status, algorithms, recipes, replay, cancellation, compatibleTemplateIds]
|
|
725
|
+
properties:
|
|
726
|
+
status: { type: string, const: ok }
|
|
727
|
+
algorithms:
|
|
728
|
+
type: array
|
|
729
|
+
minItems: 1
|
|
730
|
+
items: { type: string }
|
|
731
|
+
recipes:
|
|
732
|
+
type: array
|
|
733
|
+
minItems: 1
|
|
734
|
+
items: { type: string }
|
|
735
|
+
replay: { type: boolean }
|
|
736
|
+
cancellation: { type: boolean }
|
|
737
|
+
compatibleTemplateIds:
|
|
738
|
+
type: array
|
|
739
|
+
minItems: 1
|
|
740
|
+
items: { type: string }
|
|
701
741
|
|
|
702
742
|
# ---- Enums -------------------------------------------------------------
|
|
703
743
|
RunStatus:
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/service.rs
RENAMED
|
@@ -1508,6 +1508,9 @@ fn route_request(request: HttpRequest, runtime: GepaServiceRuntime) -> HttpRespo
|
|
|
1508
1508
|
let config = &runtime.config;
|
|
1509
1509
|
match (request.method.as_str(), segments.as_slice()) {
|
|
1510
1510
|
("GET", ["health"]) => json_response(200, &json!({"status": "ok"})),
|
|
1511
|
+
("GET", ["v1", "optimizer", "capabilities"]) | ("GET", ["v1", "optimizer", "status"]) => {
|
|
1512
|
+
json_response(200, &optimizer_capabilities_payload())
|
|
1513
|
+
}
|
|
1511
1514
|
("GET", ["whoami"]) => json_response(
|
|
1512
1515
|
200,
|
|
1513
1516
|
&service_identity_payload(config, &runtime.service_url, &runtime.started_at, None),
|
|
@@ -1583,15 +1586,65 @@ fn route_request(request: HttpRequest, runtime: GepaServiceRuntime) -> HttpRespo
|
|
|
1583
1586
|
Ok(None) => run_not_found_response(run_id),
|
|
1584
1587
|
Err(error) => optimizer_error_response(error),
|
|
1585
1588
|
},
|
|
1589
|
+
// `route_not_found`, not `run_not_found`. They share a status but mean
|
|
1590
|
+
// opposite things to a client polling a live run: a run that is not
|
|
1591
|
+
// indexed yet may appear at any moment, while a route that does not
|
|
1592
|
+
// exist never will. Reusing the run code told Workshop to keep retrying
|
|
1593
|
+
// a route this build does not serve for as long as the run lasted,
|
|
1594
|
+
// paying for rollouts whose events could never be read.
|
|
1586
1595
|
_ => error_response(
|
|
1587
1596
|
404,
|
|
1588
|
-
"
|
|
1597
|
+
"route_not_found",
|
|
1589
1598
|
&format!("route not found: {} {}", request.method, path),
|
|
1590
1599
|
None,
|
|
1591
1600
|
),
|
|
1592
1601
|
}
|
|
1593
1602
|
}
|
|
1594
1603
|
|
|
1604
|
+
/// What this service can do, answered by this service.
|
|
1605
|
+
///
|
|
1606
|
+
/// Two rules, both learned from the handshake gap that blocked v0.4:
|
|
1607
|
+
///
|
|
1608
|
+
/// 1. **Only facts this runtime owns.** Recipe ids and visual template ids are
|
|
1609
|
+
/// Workshop's vocabulary — they appear nowhere in this crate and only ever
|
|
1610
|
+
/// reached it because Workshop's install payload supplied them. Echoing them
|
|
1611
|
+
/// back proves nothing except that we were told what to say, and would tie a
|
|
1612
|
+
/// plugin release to every new host template. Workshop resolves those itself.
|
|
1613
|
+
/// 2. **Derived, never asserted.** `replay` and `cancellation` are read off the
|
|
1614
|
+
/// router below rather than written as literals, so they cannot claim a
|
|
1615
|
+
/// capability this build does not serve. A hand-written `replay: true` is
|
|
1616
|
+
/// true only by accident of which branch it was cut from.
|
|
1617
|
+
fn optimizer_capabilities_payload() -> Value {
|
|
1618
|
+
json!({
|
|
1619
|
+
"status": "ok",
|
|
1620
|
+
"contractVersion": OPTIMIZER_CONTRACT_VERSION,
|
|
1621
|
+
"serviceVersion": env!("CARGO_PKG_VERSION"),
|
|
1622
|
+
"algorithms": ["gepa"],
|
|
1623
|
+
"replay": documents_route("/runs/{run_id}/optimizer-events"),
|
|
1624
|
+
"cancellation": documents_route("/runs/{run_id}/cancel"),
|
|
1625
|
+
})
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
/// Workshop's capability contract revision this service implements.
|
|
1629
|
+
const OPTIMIZER_CONTRACT_VERSION: &str = "optimizer.contract.v1";
|
|
1630
|
+
|
|
1631
|
+
/// Is this route in the spec this build ships and serves at `/openapi.yaml`?
|
|
1632
|
+
///
|
|
1633
|
+
/// Not a second list to keep in step: the spec is a real artifact compiled into
|
|
1634
|
+
/// the binary and served to clients, so answering from it means a capability
|
|
1635
|
+
/// claim and the published contract cannot disagree. A hand-written
|
|
1636
|
+
/// `replay: true` has no such tether — it stays `true` when the route is
|
|
1637
|
+
/// dropped, or when the payload is copied to a branch that never had it, which
|
|
1638
|
+
/// is precisely how a green handshake ends up in front of a missing endpoint.
|
|
1639
|
+
///
|
|
1640
|
+
/// `router_and_spec_agree` closes the remaining gap by checking the spec
|
|
1641
|
+
/// against what the router actually serves.
|
|
1642
|
+
fn documents_route(path: &str) -> bool {
|
|
1643
|
+
GEPA_SERVICE_OPENAPI_YAML
|
|
1644
|
+
.lines()
|
|
1645
|
+
.any(|line| line.trim_end().trim_end_matches(':').trim() == path)
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1595
1648
|
fn handle_websocket_connection(
|
|
1596
1649
|
stream: &mut TcpStream,
|
|
1597
1650
|
runtime: GepaServiceRuntime,
|
|
@@ -5772,6 +5825,210 @@ mod tests {
|
|
|
5772
5825
|
);
|
|
5773
5826
|
}
|
|
5774
5827
|
|
|
5828
|
+
#[test]
|
|
5829
|
+
/// The handshake answers for this service and nothing else.
|
|
5830
|
+
///
|
|
5831
|
+
/// The previous form of this test read the payload's own literals back and
|
|
5832
|
+
/// asserted they were non-empty strings — it tested the constant against
|
|
5833
|
+
/// itself, and would have stayed green with `replay: true` on a build
|
|
5834
|
+
/// serving no events route. Assert the two properties that can actually be
|
|
5835
|
+
/// wrong instead: that we do not speak for Workshop, and that every boolean
|
|
5836
|
+
/// is tied to a route this build ships.
|
|
5837
|
+
#[test]
|
|
5838
|
+
fn workshop_capability_handshake_answers_only_for_this_service() {
|
|
5839
|
+
let capabilities = optimizer_capabilities_payload();
|
|
5840
|
+
|
|
5841
|
+
// Workshop's vocabulary. This service does not define recipe ids or
|
|
5842
|
+
// visual template ids and must not claim to.
|
|
5843
|
+
for host_owned in ["recipes", "compatibleTemplateIds"] {
|
|
5844
|
+
assert!(
|
|
5845
|
+
capabilities.get(host_owned).is_none(),
|
|
5846
|
+
"capabilities must not answer for Workshop's `{host_owned}`"
|
|
5847
|
+
);
|
|
5848
|
+
}
|
|
5849
|
+
|
|
5850
|
+
let algorithms = capabilities["algorithms"].as_array().unwrap();
|
|
5851
|
+
assert!(!algorithms.is_empty());
|
|
5852
|
+
assert!(algorithms.iter().all(Value::is_string));
|
|
5853
|
+
assert!(algorithms.iter().any(|id| id == "gepa"));
|
|
5854
|
+
assert_eq!(capabilities["contractVersion"], OPTIMIZER_CONTRACT_VERSION);
|
|
5855
|
+
assert_eq!(capabilities["serviceVersion"], env!("CARGO_PKG_VERSION"));
|
|
5856
|
+
|
|
5857
|
+
// Every boolean is derived from the shipped spec, so it cannot outlive
|
|
5858
|
+
// the route it describes.
|
|
5859
|
+
assert_eq!(
|
|
5860
|
+
capabilities["replay"],
|
|
5861
|
+
documents_route("/runs/{run_id}/optimizer-events")
|
|
5862
|
+
);
|
|
5863
|
+
assert_eq!(
|
|
5864
|
+
capabilities["cancellation"],
|
|
5865
|
+
documents_route("/runs/{run_id}/cancel")
|
|
5866
|
+
);
|
|
5867
|
+
assert_eq!(capabilities["replay"], true);
|
|
5868
|
+
assert_eq!(capabilities["cancellation"], true);
|
|
5869
|
+
|
|
5870
|
+
// The derivation has to be capable of saying no, or it is a literal
|
|
5871
|
+
// wearing a function's clothes.
|
|
5872
|
+
assert!(!documents_route("/runs/{run_id}/route-that-does-not-exist"));
|
|
5873
|
+
}
|
|
5874
|
+
|
|
5875
|
+
/// The spec backs the capability booleans, so a route the router serves but
|
|
5876
|
+
/// the spec omits would let a true claim rest on a stale document — and a
|
|
5877
|
+
/// route the spec claims but the router drops would make it simply false.
|
|
5878
|
+
#[test]
|
|
5879
|
+
fn router_and_spec_agree_on_the_capability_routes() {
|
|
5880
|
+
for path in [
|
|
5881
|
+
"/health",
|
|
5882
|
+
"/runs/{run_id}/optimizer-events",
|
|
5883
|
+
"/runs/{run_id}/cancel",
|
|
5884
|
+
"/v1/optimizer/capabilities",
|
|
5885
|
+
] {
|
|
5886
|
+
assert!(
|
|
5887
|
+
documents_route(path),
|
|
5888
|
+
"{path} is served but missing from gepa-service-v1.yaml"
|
|
5889
|
+
);
|
|
5890
|
+
}
|
|
5891
|
+
}
|
|
5892
|
+
|
|
5893
|
+
/// Drive the real service over a real socket.
|
|
5894
|
+
///
|
|
5895
|
+
/// Everything above inspects functions and constants. This starts
|
|
5896
|
+
/// `run_gepa_service` on a loopback port and speaks HTTP to it, so the
|
|
5897
|
+
/// routes are asserted the way Workshop reaches them. The gap this closes
|
|
5898
|
+
/// is the one that cost v0.4 an acceptance run: every test on both sides
|
|
5899
|
+
/// passed while the endpoint Workshop required did not exist, because
|
|
5900
|
+
/// nothing on either side had ever spoken to the other over a socket.
|
|
5901
|
+
#[test]
|
|
5902
|
+
fn the_running_service_answers_the_workshop_contract() {
|
|
5903
|
+
use std::io::{Read, Write};
|
|
5904
|
+
use std::net::TcpStream;
|
|
5905
|
+
|
|
5906
|
+
let db = scratch_path("contract");
|
|
5907
|
+
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
|
5908
|
+
let addr = listener.local_addr().unwrap();
|
|
5909
|
+
drop(listener);
|
|
5910
|
+
let mut config = GepaServiceConfig::new(db, addr.to_string());
|
|
5911
|
+
config.worker_count = 1;
|
|
5912
|
+
thread::spawn(move || {
|
|
5913
|
+
let _ = run_gepa_service(config);
|
|
5914
|
+
});
|
|
5915
|
+
|
|
5916
|
+
let get = |path: &str| -> (u16, String) {
|
|
5917
|
+
// The service is starting concurrently; retry briefly rather than
|
|
5918
|
+
// race it.
|
|
5919
|
+
for attempt in 0..50 {
|
|
5920
|
+
let Ok(mut stream) = TcpStream::connect(addr) else {
|
|
5921
|
+
thread::sleep(Duration::from_millis(40));
|
|
5922
|
+
continue;
|
|
5923
|
+
};
|
|
5924
|
+
let request =
|
|
5925
|
+
format!("GET {path} HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n");
|
|
5926
|
+
if stream.write_all(request.as_bytes()).is_err() {
|
|
5927
|
+
thread::sleep(Duration::from_millis(40));
|
|
5928
|
+
continue;
|
|
5929
|
+
}
|
|
5930
|
+
let mut raw = String::new();
|
|
5931
|
+
if stream.read_to_string(&mut raw).is_err() && attempt < 49 {
|
|
5932
|
+
thread::sleep(Duration::from_millis(40));
|
|
5933
|
+
continue;
|
|
5934
|
+
}
|
|
5935
|
+
let status = raw
|
|
5936
|
+
.split_whitespace()
|
|
5937
|
+
.nth(1)
|
|
5938
|
+
.and_then(|code| code.parse().ok())
|
|
5939
|
+
.unwrap_or(0);
|
|
5940
|
+
let body = raw.split("\r\n\r\n").nth(1).unwrap_or("").to_string();
|
|
5941
|
+
return (status, body);
|
|
5942
|
+
}
|
|
5943
|
+
panic!("service never accepted a connection on {addr}");
|
|
5944
|
+
};
|
|
5945
|
+
|
|
5946
|
+
let (status, body) = get("/health");
|
|
5947
|
+
assert_eq!(status, 200, "/health: {body}");
|
|
5948
|
+
|
|
5949
|
+
// The route whose absence blocked v0.4.
|
|
5950
|
+
let (status, body) = get("/v1/optimizer/capabilities");
|
|
5951
|
+
assert_eq!(status, 200, "/v1/optimizer/capabilities: {body}");
|
|
5952
|
+
let capabilities: Value = serde_json::from_str(&body).unwrap();
|
|
5953
|
+
assert!(capabilities["algorithms"]
|
|
5954
|
+
.as_array()
|
|
5955
|
+
.unwrap()
|
|
5956
|
+
.iter()
|
|
5957
|
+
.any(|id| id == "gepa"));
|
|
5958
|
+
assert_eq!(capabilities["replay"], true);
|
|
5959
|
+
assert_eq!(capabilities["cancellation"], true);
|
|
5960
|
+
assert!(capabilities.get("recipes").is_none());
|
|
5961
|
+
assert!(capabilities.get("compatibleTemplateIds").is_none());
|
|
5962
|
+
|
|
5963
|
+
// Served, and 404s for an unknown run rather than for an unknown route.
|
|
5964
|
+
let (status, body) = get("/runs/no_such_run/optimizer-events?after_sequence=0&limit=10");
|
|
5965
|
+
assert_eq!(status, 404, "unexpected status for a missing run: {body}");
|
|
5966
|
+
let error: Value = serde_json::from_str(&body).unwrap();
|
|
5967
|
+
assert_eq!(
|
|
5968
|
+
error["error"]["code"], "run_not_found",
|
|
5969
|
+
"a served route with a missing run must say run_not_found: {body}"
|
|
5970
|
+
);
|
|
5971
|
+
|
|
5972
|
+
// And an unknown route is reported as such, so a client can tell "this
|
|
5973
|
+
// build cannot do that" from "not indexed yet".
|
|
5974
|
+
let (status, body) = get("/runs/no_such_run/not-a-route");
|
|
5975
|
+
assert_eq!(status, 404);
|
|
5976
|
+
let error: Value = serde_json::from_str(&body).unwrap();
|
|
5977
|
+
assert_eq!(
|
|
5978
|
+
error["error"]["code"], "route_not_found",
|
|
5979
|
+
"an unknown route must not masquerade as a missing run: {body}"
|
|
5980
|
+
);
|
|
5981
|
+
}
|
|
5982
|
+
|
|
5983
|
+
/// The wheel version and the crate version are set in different files and
|
|
5984
|
+
/// neither is derived from the other, so only a test keeps them in step.
|
|
5985
|
+
///
|
|
5986
|
+
/// `/whoami` and the capability handshake both report `CARGO_PKG_VERSION`.
|
|
5987
|
+
/// When only `pyproject.toml` is bumped, an installed 0.2.12 wheel reports
|
|
5988
|
+
/// itself as 0.2.9 over HTTP, and every version floor keyed on that number
|
|
5989
|
+
/// is checking a value the release never had.
|
|
5990
|
+
#[test]
|
|
5991
|
+
fn the_wheel_and_the_crate_report_the_same_release() {
|
|
5992
|
+
let pyproject = include_str!("../../../../pyproject.toml");
|
|
5993
|
+
let declared = pyproject
|
|
5994
|
+
.lines()
|
|
5995
|
+
.find_map(|line| line.trim().strip_prefix("version = "))
|
|
5996
|
+
.map(|value| value.trim().trim_matches('"'))
|
|
5997
|
+
.expect("pyproject version");
|
|
5998
|
+
// PEP 440 pre-release suffixes (`0.2.12.dev20260816`) have no Cargo
|
|
5999
|
+
// equivalent; the release triple in front of them must still match.
|
|
6000
|
+
let release: String = declared
|
|
6001
|
+
.split('.')
|
|
6002
|
+
.take(3)
|
|
6003
|
+
.collect::<Vec<_>>()
|
|
6004
|
+
.join(".");
|
|
6005
|
+
assert_eq!(
|
|
6006
|
+
release,
|
|
6007
|
+
env!("CARGO_PKG_VERSION"),
|
|
6008
|
+
"pyproject.toml ({declared}) and the workspace Cargo.toml disagree; \
|
|
6009
|
+
/whoami and the capability handshake report the Cargo value"
|
|
6010
|
+
);
|
|
6011
|
+
}
|
|
6012
|
+
|
|
6013
|
+
/// An unknown route is not a missing run. Workshop retries the latter for
|
|
6014
|
+
/// the life of a paid run and fails fast on the former.
|
|
6015
|
+
#[test]
|
|
6016
|
+
fn unknown_routes_are_not_reported_as_missing_runs() {
|
|
6017
|
+
let source = include_str!("service.rs");
|
|
6018
|
+
let router = source
|
|
6019
|
+
.split("fn optimizer_capabilities_payload")
|
|
6020
|
+
.next()
|
|
6021
|
+
.expect("router source");
|
|
6022
|
+
let fallback = router
|
|
6023
|
+
.rfind("route not found: ")
|
|
6024
|
+
.expect("router fallback arm");
|
|
6025
|
+
let arm = &router[fallback.saturating_sub(200)..fallback];
|
|
6026
|
+
assert!(
|
|
6027
|
+
arm.contains("route_not_found"),
|
|
6028
|
+
"the router fallback must report route_not_found, not run_not_found"
|
|
6029
|
+
);
|
|
6030
|
+
}
|
|
6031
|
+
|
|
5775
6032
|
#[test]
|
|
5776
6033
|
fn optimizer_event_pages_are_cursor_idempotent_and_run_isolated() {
|
|
5777
6034
|
let path = scratch_path("cursor");
|
|
@@ -1252,6 +1252,7 @@ pub const CHATGPT_PROPOSER_MODELS: &[&str] = &[
|
|
|
1252
1252
|
"gpt-5.5",
|
|
1253
1253
|
"gpt-5.6-luna",
|
|
1254
1254
|
"gpt-5.6-sol",
|
|
1255
|
+
"gpt-5.6-terra",
|
|
1255
1256
|
];
|
|
1256
1257
|
|
|
1257
1258
|
pub fn proposer_auth_mode_normalized(auth_mode: &str) -> String {
|
|
@@ -2895,8 +2896,8 @@ mod tests {
|
|
|
2895
2896
|
use super::*;
|
|
2896
2897
|
|
|
2897
2898
|
#[test]
|
|
2898
|
-
fn
|
|
2899
|
-
for model in ["gpt-5.6-luna", "gpt-5.6-sol"] {
|
|
2899
|
+
fn locked_5_6_chatgpt_proposers_are_allowed() {
|
|
2900
|
+
for model in ["gpt-5.6-luna", "gpt-5.6-sol", "gpt-5.6-terra"] {
|
|
2900
2901
|
assert!(CHATGPT_PROPOSER_MODELS.contains(&model));
|
|
2901
2902
|
validate_chatgpt_proposer_model(model).expect("locked ChatGPT proposer model");
|
|
2902
2903
|
validate_chatgpt_proposer_model(&model.to_ascii_uppercase())
|
|
@@ -2911,6 +2912,7 @@ mod tests {
|
|
|
2911
2912
|
assert!(error.to_string().contains("not allowed"));
|
|
2912
2913
|
assert!(error.to_string().contains("gpt-5.6-luna"));
|
|
2913
2914
|
assert!(error.to_string().contains("gpt-5.6-sol"));
|
|
2915
|
+
assert!(error.to_string().contains("gpt-5.6-terra"));
|
|
2914
2916
|
}
|
|
2915
2917
|
|
|
2916
2918
|
#[test]
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/__init__.py
RENAMED
|
@@ -79,10 +79,16 @@ from .hosted import (
|
|
|
79
79
|
OptimizerStartupCatalog,
|
|
80
80
|
RunStatus as HostedRunStatus,
|
|
81
81
|
submit_mapo,
|
|
82
|
+
submit_sft,
|
|
82
83
|
submit_online_reflexion,
|
|
83
84
|
validate_online_reflexion_evidence_notes,
|
|
84
85
|
)
|
|
85
86
|
from .hosted_config import HostedOptimizerConfig
|
|
87
|
+
from .future_algorithms import (
|
|
88
|
+
FUTURE_HOSTED_ALGORITHMS,
|
|
89
|
+
FutureHostedAlgorithm,
|
|
90
|
+
FutureHostedAlgorithmSlug,
|
|
91
|
+
)
|
|
86
92
|
from .o11y import (
|
|
87
93
|
LiveProgress,
|
|
88
94
|
RegistryRecord,
|
|
@@ -220,6 +226,9 @@ __all__ = [
|
|
|
220
226
|
"HostedOptimizerClient",
|
|
221
227
|
"HostedOptimizerError",
|
|
222
228
|
"HostedOptimizerConfig",
|
|
229
|
+
"FUTURE_HOSTED_ALGORITHMS",
|
|
230
|
+
"FutureHostedAlgorithm",
|
|
231
|
+
"FutureHostedAlgorithmSlug",
|
|
223
232
|
"HostedRunStatus",
|
|
224
233
|
"InvariantError",
|
|
225
234
|
"InMemoryRunLog",
|
|
@@ -287,6 +296,7 @@ __all__ = [
|
|
|
287
296
|
"gepa_delete_run_storage",
|
|
288
297
|
"gepa_serve",
|
|
289
298
|
"submit_mapo",
|
|
299
|
+
"submit_sft",
|
|
290
300
|
"submit_online_reflexion",
|
|
291
301
|
"validate_online_reflexion_evidence_notes",
|
|
292
302
|
]
|
|
@@ -18,7 +18,7 @@ The proposer is a Codex app-server. Configure it under `[proposer]` (TOML) or
|
|
|
18
18
|
| `runtime_substrate` | `local` (host) or `docker` (`[proposer.docker].image`). |
|
|
19
19
|
| `provider` | `openai`, `openrouter`, `deepseek`. |
|
|
20
20
|
| `auth_mode` | `auto`, `api_key`, `chatgpt`, or `host`. |
|
|
21
|
-
| `model` | e.g. `gpt-5.4-
|
|
21
|
+
| `model` | e.g. `gpt-5.4-mini`, `gpt-5.5`, `gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`. |
|
|
22
22
|
| `reasoning_effort` | `none` / `low` / `medium` / `high`. |
|
|
23
23
|
| `execution_mode` | `local_process` / `stdio` (JSON-RPC over stdin/stdout) or `websocket` / `ws`. |
|
|
24
24
|
| `service_tier` | `default` or `fast` (Codex Fast mode; requires ChatGPT auth). |
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Compatibility identifiers for hosted algorithms not yet publicly supported.
|
|
2
|
+
|
|
3
|
+
These identifiers let the SDK parse a hosted catalog and preserve run history without
|
|
4
|
+
implying that the package provides a supported local executor, cookbook, or release
|
|
5
|
+
commitment. Promote an entry only when its public contract and end-to-end evidence
|
|
6
|
+
are ready.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass
|
|
12
|
+
from enum import StrEnum
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FutureHostedAlgorithmSlug(StrEnum):
|
|
16
|
+
MAPO = "mapo"
|
|
17
|
+
OHCO = "ohco"
|
|
18
|
+
ONLINE_REFLEXION = "online-reflexion"
|
|
19
|
+
MARL_PROMPTOPT = "marl-promptopt"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True, slots=True)
|
|
23
|
+
class FutureHostedAlgorithm:
|
|
24
|
+
slug: FutureHostedAlgorithmSlug
|
|
25
|
+
summary: str
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
FUTURE_HOSTED_ALGORITHMS: tuple[FutureHostedAlgorithm, ...] = (
|
|
29
|
+
FutureHostedAlgorithm(FutureHostedAlgorithmSlug.MAPO, "Private hosted compatibility lane."),
|
|
30
|
+
FutureHostedAlgorithm(FutureHostedAlgorithmSlug.OHCO, "Private hosted compatibility lane."),
|
|
31
|
+
FutureHostedAlgorithm(
|
|
32
|
+
FutureHostedAlgorithmSlug.ONLINE_REFLEXION,
|
|
33
|
+
"Gated hosted compatibility lane pending release evidence.",
|
|
34
|
+
),
|
|
35
|
+
FutureHostedAlgorithm(
|
|
36
|
+
FutureHostedAlgorithmSlug.MARL_PROMPTOPT,
|
|
37
|
+
"Research executable; not a public hosted product lane.",
|
|
38
|
+
),
|
|
39
|
+
)
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/hosted.py
RENAMED
|
@@ -85,6 +85,7 @@ _USAGE_REGISTRATION_TIMEOUT_SECONDS = 2.0
|
|
|
85
85
|
class OptimizerAlgorithmSlug(StrEnum):
|
|
86
86
|
GEPA = "gepa"
|
|
87
87
|
GELO = "go-ex"
|
|
88
|
+
SFT = "sft"
|
|
88
89
|
MAPO = "mapo"
|
|
89
90
|
OHCO = "ohco"
|
|
90
91
|
ONLINE_REFLEXION = "online-reflexion"
|
|
@@ -392,6 +393,14 @@ class HostedOptimizerClient:
|
|
|
392
393
|
) -> OptimizerRunSubmitResponse:
|
|
393
394
|
return self._submit(OptimizerAlgorithmSlug.GELO, config, **kwargs)
|
|
394
395
|
|
|
396
|
+
def submit_sft(
|
|
397
|
+
self,
|
|
398
|
+
config: Mapping[str, Any] | Any,
|
|
399
|
+
**kwargs: Any,
|
|
400
|
+
) -> OptimizerRunSubmitResponse:
|
|
401
|
+
"""Submit a hosted SFT run executed by the Optimizers-beta backend."""
|
|
402
|
+
return self._submit(OptimizerAlgorithmSlug.SFT, config, **kwargs)
|
|
403
|
+
|
|
395
404
|
def submit_mapo(
|
|
396
405
|
self,
|
|
397
406
|
config: Mapping[str, Any] | Any,
|
|
@@ -983,6 +992,17 @@ def submit_mapo(
|
|
|
983
992
|
return active_client.submit_mapo(config, **kwargs)
|
|
984
993
|
|
|
985
994
|
|
|
995
|
+
def submit_sft(
|
|
996
|
+
config: Mapping[str, Any] | Any,
|
|
997
|
+
*,
|
|
998
|
+
client: HostedOptimizerClient | None = None,
|
|
999
|
+
**kwargs: Any,
|
|
1000
|
+
) -> OptimizerRunSubmitResponse:
|
|
1001
|
+
"""Submit an SFT run through the public hosted Optimizers API."""
|
|
1002
|
+
active_client = client or HostedOptimizerClient()
|
|
1003
|
+
return active_client.submit_sft(config, **kwargs)
|
|
1004
|
+
|
|
1005
|
+
|
|
986
1006
|
def submit_online_reflexion(
|
|
987
1007
|
config: Mapping[str, Any] | Any,
|
|
988
1008
|
*,
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/Cargo.toml
RENAMED
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/lib.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/planner.rs
RENAMED
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/rust/crates/synth_gepa/src/runtime.rs
RENAMED
|
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
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/README.md
RENAMED
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/board_server.py
RENAMED
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/discovery.py
RENAMED
|
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
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/docs_server.py
RENAMED
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/eval_stats.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/hosted_config.py
RENAMED
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/observability.py
RENAMED
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/tunnels.py
RENAMED
|
File without changes
|
{synth_optimizers-0.2.9.dev20260814 → synth_optimizers-0.2.12}/src/synth_optimizers/victorialogs.py
RENAMED
|
File without changes
|