synth-optimizers 0.2.7.dev20260814__tar.gz → 0.2.9.dev20260814__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.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/Cargo.lock +5 -5
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/Cargo.toml +1 -1
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/PKG-INFO +1 -1
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/pyproject.toml +1 -1
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/codex_app_server.rs +59 -5
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/lib.rs +50 -19
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/runtime.rs +46 -6
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/README.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/Cargo.toml +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/README.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/openapi/gepa-service-v1.yaml +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/jesterky_workflow.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/machines.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/pipeline.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/planner.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/prompting_best_practices.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_gepa/src/service.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/Cargo.toml +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/README.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/README.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/app_server.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/codex_home.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/daytona.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/docker.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/jsonrpc_read_window.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/limits.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/local.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/mod.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/nano.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/role_agent.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/session.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/substrate.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/supervisor.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/agent_runtime/usage.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/artifact_store.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/artifacts.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/cache.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/candidates.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/checkpoints.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/config.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/configured_limits.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/container_contract.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/data_models.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/disk_budget.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/error.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/event_visualization.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/events.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/evidence.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/failures.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/fsm.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/http.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/invariants.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/jesterky.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/jobs.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/levers.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/lib.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/limit_engine.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/limits.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/observability.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/operations.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/process.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/projections.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/prompt_program.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/registry.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/resources.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/rollouts.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/runtime_records.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/scores.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/sensors.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/state_machine.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/stopper.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/storage_maintenance.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/usage.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizer_platform/src/workspace.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizers_py/Cargo.toml +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizers_py/README.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/rust/crates/synth_optimizers_py/src/lib.rs +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/README.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/__init__.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/_synth_optimizers.pyi +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/board_server.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/cli.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/discovery.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gelo/00-index.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gelo/10-cli.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gelo/20-sdk.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gelo/30-hosted.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gelo/containers/00-overview.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gelo/containers/20-contract.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/00-index.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/10-cli.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/20-sdk.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/algorithms/00-overview.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/algorithms/10-pipeline-modes.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/algorithms/20-proposer-and-policies.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/assets/synth-logo.png +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/containers/00-overview.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/containers/10-catalog.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs/gepa/containers/20-contract.md +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/docs_server.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/eval_stats.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/gelo.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/gepa.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/hosted.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/hosted_config.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/o11y.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/observability.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/py.typed +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/sdk.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/src/synth_optimizers/tunnels.py +0 -0
- {synth_optimizers-0.2.7.dev20260814 → synth_optimizers-0.2.9.dev20260814}/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.9"
|
|
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.9"
|
|
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.9"
|
|
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.9"
|
|
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.9"
|
|
1368
1368
|
dependencies = [
|
|
1369
1369
|
"pyo3",
|
|
1370
1370
|
"serde_json",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "synth-optimizers"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.9.dev20260814"
|
|
4
4
|
description = "Public Synth optimizer tooling with a Rust GEPA core."
|
|
5
5
|
authors = [{name = "Synth Laboratories", email = "josh@usesynth.ai"}]
|
|
6
6
|
readme = "README.md"
|
|
@@ -10,10 +10,10 @@ use reqwest::blocking::Client;
|
|
|
10
10
|
use serde_json::{json, Map, Value};
|
|
11
11
|
use synth_optimizer_platform::{
|
|
12
12
|
jesterky_workspace_read_model, looks_like_jesterky_manifest,
|
|
13
|
-
proposer_delta_chunks_from_protocol,
|
|
14
|
-
run_turn, AgentTurnOutcome, CodexTurnRequest,
|
|
15
|
-
|
|
16
|
-
SynthOptimizerConfig,
|
|
13
|
+
proposer_delta_chunks_from_protocol, proposer_uses_chatgpt_auth, read_jesterky_manifest,
|
|
14
|
+
record_manifest_validation, run_turn, AgentTurnOutcome, CodexTurnRequest,
|
|
15
|
+
NanoAgentTurnIdentity, NanoCodexExecution, NanoCodexSessionPool, NanoCodexTurnRequest,
|
|
16
|
+
OptimizerError, PromptProgram, Result, SynthOptimizerConfig,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
const GEPA_REFLECTIVE_FRAME_SCHEMA_VERSION: &str = "gepa_reflective_frame.v1";
|
|
@@ -556,7 +556,26 @@ fn normalize_proposer_usage(config: &SynthOptimizerConfig, model: &str, usage: V
|
|
|
556
556
|
let provider = config.proposer.provider.trim().to_ascii_lowercase();
|
|
557
557
|
let model_lower = model.trim().to_ascii_lowercase();
|
|
558
558
|
let reported_cost = usage_f64_from_map(&usage_map, "cost_usd")
|
|
559
|
-
.filter(|value| value.is_finite() && *value
|
|
559
|
+
.filter(|value| value.is_finite() && *value >= 0.0);
|
|
560
|
+
if proposer_uses_chatgpt_auth(&config.proposer.auth_mode) {
|
|
561
|
+
usage_map.insert(
|
|
562
|
+
"provider".to_string(),
|
|
563
|
+
Value::String("chatgpt_subscription".to_string()),
|
|
564
|
+
);
|
|
565
|
+
usage_map.insert("model".to_string(), Value::String(model.to_string()));
|
|
566
|
+
if reported_cost.is_none() {
|
|
567
|
+
// ChatGPT-authenticated Codex turns are subscription-backed rather
|
|
568
|
+
// than metered API calls. Record an explicit zero incremental API
|
|
569
|
+
// charge so the hard cost ledger does not mistake the absence of
|
|
570
|
+
// an API receipt for unknown spend.
|
|
571
|
+
usage_map.insert("cost_usd".to_string(), json!(0.0));
|
|
572
|
+
usage_map.insert(
|
|
573
|
+
"cost_source".to_string(),
|
|
574
|
+
Value::String("chatgpt_subscription_no_incremental_api_charge".to_string()),
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
return Value::Object(usage_map);
|
|
578
|
+
}
|
|
560
579
|
if provider.eq_ignore_ascii_case("openrouter") && model_lower == OPENROUTER_GROK43_MODEL {
|
|
561
580
|
return normalize_openrouter_grok43_usage(model, usage_map);
|
|
562
581
|
}
|
|
@@ -3378,3 +3397,38 @@ fn non_empty(value: Option<&str>) -> Option<&str> {
|
|
|
3378
3397
|
Some(value)
|
|
3379
3398
|
}
|
|
3380
3399
|
}
|
|
3400
|
+
|
|
3401
|
+
#[cfg(test)]
|
|
3402
|
+
mod cost_tests {
|
|
3403
|
+
use super::*;
|
|
3404
|
+
|
|
3405
|
+
#[test]
|
|
3406
|
+
fn chatgpt_proposer_emits_explicit_zero_incremental_api_cost() {
|
|
3407
|
+
let mut config = SynthOptimizerConfig::default();
|
|
3408
|
+
config.proposer.auth_mode = "chatgpt".to_string();
|
|
3409
|
+
let usage = normalize_proposer_usage(
|
|
3410
|
+
&config,
|
|
3411
|
+
"gpt-5.6-luna",
|
|
3412
|
+
json!({"prompt_tokens": 100, "completion_tokens": 20, "total_tokens": 120}),
|
|
3413
|
+
);
|
|
3414
|
+
assert_eq!(usage.get("cost_usd"), Some(&json!(0.0)));
|
|
3415
|
+
assert_eq!(
|
|
3416
|
+
usage.get("cost_source"),
|
|
3417
|
+
Some(&json!("chatgpt_subscription_no_incremental_api_charge"))
|
|
3418
|
+
);
|
|
3419
|
+
assert_eq!(usage.get("provider"), Some(&json!("chatgpt_subscription")));
|
|
3420
|
+
}
|
|
3421
|
+
|
|
3422
|
+
#[test]
|
|
3423
|
+
fn chatgpt_proposer_preserves_an_explicit_cost_receipt() {
|
|
3424
|
+
let mut config = SynthOptimizerConfig::default();
|
|
3425
|
+
config.proposer.auth_mode = "chatgpt".to_string();
|
|
3426
|
+
let usage = normalize_proposer_usage(
|
|
3427
|
+
&config,
|
|
3428
|
+
"gpt-5.6-luna",
|
|
3429
|
+
json!({"cost_usd": 0.25, "cost_source": "provider"}),
|
|
3430
|
+
);
|
|
3431
|
+
assert_eq!(usage.get("cost_usd"), Some(&json!(0.25)));
|
|
3432
|
+
assert_eq!(usage.get("cost_source"), Some(&json!("provider")));
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
@@ -3799,7 +3799,7 @@ fn consume_async_lane_work(
|
|
|
3799
3799
|
| OptimizerJobStatus::Cancelled
|
|
3800
3800
|
| OptimizerJobStatus::Expired => {
|
|
3801
3801
|
if let Some(outcome) =
|
|
3802
|
-
|
|
3802
|
+
schedule_failed_runtime_retry_if_allowed(context, state, resources, &job)?
|
|
3803
3803
|
{
|
|
3804
3804
|
if let Some(updated) =
|
|
3805
3805
|
state.cursor.pipeline_state.lane_leases.get_mut(&lease_key)
|
|
@@ -6956,7 +6956,7 @@ fn advance_pending_runtime_job(
|
|
|
6956
6956
|
});
|
|
6957
6957
|
}
|
|
6958
6958
|
if updated_job.status.is_terminal() {
|
|
6959
|
-
if let Some(outcome) =
|
|
6959
|
+
if let Some(outcome) = schedule_failed_runtime_retry_if_allowed(
|
|
6960
6960
|
context,
|
|
6961
6961
|
state,
|
|
6962
6962
|
resources,
|
|
@@ -7078,7 +7078,7 @@ fn advance_pending_runtime_job(
|
|
|
7078
7078
|
| OptimizerJobStatus::Cancelled
|
|
7079
7079
|
| OptimizerJobStatus::Expired => {
|
|
7080
7080
|
if let Some(outcome) =
|
|
7081
|
-
|
|
7081
|
+
schedule_failed_runtime_retry_if_allowed(context, state, resources, &job)?
|
|
7082
7082
|
{
|
|
7083
7083
|
return Ok(outcome);
|
|
7084
7084
|
}
|
|
@@ -9354,14 +9354,16 @@ fn consume_failed_rollout_attempt(
|
|
|
9354
9354
|
Ok(())
|
|
9355
9355
|
}
|
|
9356
9356
|
|
|
9357
|
-
fn
|
|
9357
|
+
fn schedule_failed_runtime_retry_if_allowed(
|
|
9358
9358
|
context: &mut GepaRunContext,
|
|
9359
9359
|
state: &mut GepaRunState,
|
|
9360
9360
|
resources: &GepaStepResources,
|
|
9361
9361
|
job: &OptimizerJob,
|
|
9362
9362
|
) -> Result<Option<GepaAdvanceOutcome>> {
|
|
9363
|
-
if !matches!(
|
|
9364
|
-
|
|
9363
|
+
if !matches!(
|
|
9364
|
+
job.kind,
|
|
9365
|
+
OptimizerJobKind::Rollout | OptimizerJobKind::Proposer
|
|
9366
|
+
) || matches!(job.status, OptimizerJobStatus::Cancelled)
|
|
9365
9367
|
{
|
|
9366
9368
|
return Ok(None);
|
|
9367
9369
|
}
|
|
@@ -9391,7 +9393,7 @@ fn schedule_failed_rollout_retry_if_allowed(
|
|
|
9391
9393
|
resources,
|
|
9392
9394
|
state.cursor.phase.clone(),
|
|
9393
9395
|
"retry_scheduled",
|
|
9394
|
-
"scheduled GEPA failed
|
|
9396
|
+
"scheduled GEPA failed runtime job retry",
|
|
9395
9397
|
Map::new(),
|
|
9396
9398
|
)?;
|
|
9397
9399
|
Ok(Some(GepaAdvanceOutcome {
|
|
@@ -9399,8 +9401,9 @@ fn schedule_failed_rollout_retry_if_allowed(
|
|
|
9399
9401
|
terminal: false,
|
|
9400
9402
|
result: None,
|
|
9401
9403
|
message: format!(
|
|
9402
|
-
"scheduled GEPA failed
|
|
9404
|
+
"scheduled GEPA failed runtime job retry: {} kind={} attempt={}/{}",
|
|
9403
9405
|
updated.job_id,
|
|
9406
|
+
updated.kind.as_str(),
|
|
9404
9407
|
updated.attempt.saturating_add(1),
|
|
9405
9408
|
updated.retry_policy.max_attempts
|
|
9406
9409
|
),
|
|
@@ -20225,17 +20228,7 @@ fn record_runtime_effect_job(
|
|
|
20225
20228
|
let mut job = OptimizerJob::new(input.job_id, input.run_id, input.kind);
|
|
20226
20229
|
job.status = input.status;
|
|
20227
20230
|
job.candidate_id = input.candidate_id.map(str::to_string);
|
|
20228
|
-
|
|
20229
|
-
job.retry_policy = RetryPolicy {
|
|
20230
|
-
max_attempts: 3,
|
|
20231
|
-
backoff_seconds: 2,
|
|
20232
|
-
retryable_failure_types: vec![
|
|
20233
|
-
"synth_optimizer_http_error".to_string(),
|
|
20234
|
-
"synth_optimizer_container_error".to_string(),
|
|
20235
|
-
"synth_optimizer_failed".to_string(),
|
|
20236
|
-
],
|
|
20237
|
-
};
|
|
20238
|
-
}
|
|
20231
|
+
job.retry_policy = runtime_effect_retry_policy(&job.kind);
|
|
20239
20232
|
job.attempt = if matches!(job.status, OptimizerJobStatus::Pending) {
|
|
20240
20233
|
input.effect.attempt.saturating_sub(1)
|
|
20241
20234
|
} else {
|
|
@@ -20301,6 +20294,26 @@ fn record_runtime_effect_job(
|
|
|
20301
20294
|
workspace.record_optimizer_job(&job)
|
|
20302
20295
|
}
|
|
20303
20296
|
|
|
20297
|
+
fn runtime_effect_retry_policy(kind: &OptimizerJobKind) -> RetryPolicy {
|
|
20298
|
+
match kind {
|
|
20299
|
+
OptimizerJobKind::Rollout => RetryPolicy {
|
|
20300
|
+
max_attempts: 3,
|
|
20301
|
+
backoff_seconds: 2,
|
|
20302
|
+
retryable_failure_types: vec![
|
|
20303
|
+
"synth_optimizer_http_error".to_string(),
|
|
20304
|
+
"synth_optimizer_container_error".to_string(),
|
|
20305
|
+
"synth_optimizer_failed".to_string(),
|
|
20306
|
+
],
|
|
20307
|
+
},
|
|
20308
|
+
OptimizerJobKind::Proposer => RetryPolicy {
|
|
20309
|
+
max_attempts: 2,
|
|
20310
|
+
backoff_seconds: 2,
|
|
20311
|
+
retryable_failure_types: vec!["synth_optimizer_proposer_error".to_string()],
|
|
20312
|
+
},
|
|
20313
|
+
_ => RetryPolicy::default(),
|
|
20314
|
+
}
|
|
20315
|
+
}
|
|
20316
|
+
|
|
20304
20317
|
fn budget_exceeded_error(run_id: &str, breach: &BudgetLimitBreach) -> OptimizerError {
|
|
20305
20318
|
OptimizerError::BudgetExceeded {
|
|
20306
20319
|
run_id: run_id.to_string(),
|
|
@@ -21714,4 +21727,22 @@ mod run_loop_terminalization_tests {
|
|
|
21714
21727
|
None
|
|
21715
21728
|
);
|
|
21716
21729
|
}
|
|
21730
|
+
|
|
21731
|
+
#[test]
|
|
21732
|
+
fn proposer_runtime_jobs_get_one_bounded_retry() {
|
|
21733
|
+
let policy = runtime_effect_retry_policy(&OptimizerJobKind::Proposer);
|
|
21734
|
+
assert_eq!(policy.max_attempts, 2);
|
|
21735
|
+
assert_eq!(policy.backoff_seconds, 2);
|
|
21736
|
+
assert_eq!(
|
|
21737
|
+
policy.retryable_failure_types,
|
|
21738
|
+
vec!["synth_optimizer_proposer_error".to_string()]
|
|
21739
|
+
);
|
|
21740
|
+
}
|
|
21741
|
+
|
|
21742
|
+
#[test]
|
|
21743
|
+
fn unrelated_runtime_jobs_keep_the_fail_closed_default() {
|
|
21744
|
+
let policy = runtime_effect_retry_policy(&OptimizerJobKind::Annotation);
|
|
21745
|
+
assert_eq!(policy.max_attempts, 1);
|
|
21746
|
+
assert!(policy.retryable_failure_types.is_empty());
|
|
21747
|
+
}
|
|
21717
21748
|
}
|
|
@@ -468,7 +468,7 @@ impl<'a> GepaRuntimeExecutor<'a> {
|
|
|
468
468
|
Ok(outcome) => outcome,
|
|
469
469
|
Err(error) => {
|
|
470
470
|
if let Some(retry) =
|
|
471
|
-
self.
|
|
471
|
+
self.schedule_runtime_retry_if_allowed(&running_job, &lease_id, &error)?
|
|
472
472
|
{
|
|
473
473
|
return Err(retry);
|
|
474
474
|
}
|
|
@@ -509,6 +509,7 @@ impl<'a> GepaRuntimeExecutor<'a> {
|
|
|
509
509
|
json!(self.config.gepa.rollout_submission_mode),
|
|
510
510
|
);
|
|
511
511
|
}
|
|
512
|
+
persist_runtime_outcome_before_completion(self.workspace, run_id, job_id, &outcome)?;
|
|
512
513
|
record_runtime_effect_completed(
|
|
513
514
|
self.workspace,
|
|
514
515
|
RuntimeEffectCompletionInput {
|
|
@@ -527,14 +528,13 @@ impl<'a> GepaRuntimeExecutor<'a> {
|
|
|
527
528
|
Ok(outcome)
|
|
528
529
|
}
|
|
529
530
|
|
|
530
|
-
fn
|
|
531
|
+
fn schedule_runtime_retry_if_allowed(
|
|
531
532
|
&self,
|
|
532
533
|
job: &OptimizerJob,
|
|
533
534
|
lease_id: &str,
|
|
534
535
|
error: &OptimizerError,
|
|
535
536
|
) -> Result<Option<OptimizerError>> {
|
|
536
|
-
if !
|
|
537
|
-
|| !is_retryable_rollout_runtime_error(error)
|
|
537
|
+
if !is_retryable_runtime_job_error(job, error)
|
|
538
538
|
|| job.attempt >= job.retry_policy.max_attempts
|
|
539
539
|
{
|
|
540
540
|
return Ok(None);
|
|
@@ -555,8 +555,9 @@ impl<'a> GepaRuntimeExecutor<'a> {
|
|
|
555
555
|
return Ok(None);
|
|
556
556
|
};
|
|
557
557
|
Ok(Some(OptimizerError::Failed(format!(
|
|
558
|
-
"retryable
|
|
558
|
+
"retryable runtime failure scheduled for retry job_id={} kind={} attempt={}/{} next_retry_at={}",
|
|
559
559
|
updated.job_id,
|
|
560
|
+
updated.kind.as_str(),
|
|
560
561
|
updated.attempt.saturating_add(1),
|
|
561
562
|
updated.retry_policy.max_attempts,
|
|
562
563
|
updated.next_retry_at.unwrap_or_else(|| "now".to_string())
|
|
@@ -666,7 +667,7 @@ impl<'a> GepaRuntimeExecutor<'a> {
|
|
|
666
667
|
.and_then(|usage| usage.get("cost_usd"))
|
|
667
668
|
.or_else(|| response.get("cost_usd"))
|
|
668
669
|
.and_then(Value::as_f64)
|
|
669
|
-
.filter(|value| value.is_finite() && *value
|
|
670
|
+
.filter(|value| value.is_finite() && *value >= 0.0)
|
|
670
671
|
.or_else(|| proposer_static_cost_usd(self.config, &usage, &response));
|
|
671
672
|
let cost_usd = reported_cost_usd.unwrap_or(0.0);
|
|
672
673
|
let backend = response
|
|
@@ -1096,6 +1097,32 @@ fn is_retryable_rollout_runtime_error(error: &OptimizerError) -> bool {
|
|
|
1096
1097
|
)
|
|
1097
1098
|
}
|
|
1098
1099
|
|
|
1100
|
+
fn is_retryable_runtime_job_error(job: &OptimizerJob, error: &OptimizerError) -> bool {
|
|
1101
|
+
match job.kind {
|
|
1102
|
+
OptimizerJobKind::Rollout => is_retryable_rollout_runtime_error(error),
|
|
1103
|
+
OptimizerJobKind::Proposer => matches!(error, OptimizerError::Proposer(_)),
|
|
1104
|
+
_ => false,
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
#[cfg(test)]
|
|
1109
|
+
mod runtime_job_retry_tests {
|
|
1110
|
+
use super::*;
|
|
1111
|
+
|
|
1112
|
+
#[test]
|
|
1113
|
+
fn proposer_errors_are_retryable_runtime_job_errors() {
|
|
1114
|
+
let job = OptimizerJob::new("proposer-job", "run", OptimizerJobKind::Proposer);
|
|
1115
|
+
assert!(is_retryable_runtime_job_error(
|
|
1116
|
+
&job,
|
|
1117
|
+
&OptimizerError::Proposer("app-server stalled".to_string())
|
|
1118
|
+
));
|
|
1119
|
+
assert!(!is_retryable_runtime_job_error(
|
|
1120
|
+
&job,
|
|
1121
|
+
&OptimizerError::Config("invalid proposer config".to_string())
|
|
1122
|
+
));
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1099
1126
|
fn dispatch_async_rollout(
|
|
1100
1127
|
client: &ContainerClient,
|
|
1101
1128
|
request: &Value,
|
|
@@ -1566,6 +1593,19 @@ fn ensure_job_lease(
|
|
|
1566
1593
|
Ok(())
|
|
1567
1594
|
}
|
|
1568
1595
|
|
|
1596
|
+
fn persist_runtime_outcome_before_completion(
|
|
1597
|
+
workspace: &WorkspaceStore,
|
|
1598
|
+
run_id: &str,
|
|
1599
|
+
job_id: &str,
|
|
1600
|
+
outcome: &RuntimeEffectOutcome,
|
|
1601
|
+
) -> Result<()> {
|
|
1602
|
+
let stored = crate::stored_runtime_outcome(outcome)?;
|
|
1603
|
+
let mut job = workspace.optimizer_job(run_id, job_id)?;
|
|
1604
|
+
job.payload
|
|
1605
|
+
.insert("runtime_outcome".to_string(), serde_json::to_value(stored)?);
|
|
1606
|
+
workspace.record_optimizer_job(&job)
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1569
1609
|
fn runtime_lease_id(worker_id: &str, job_id: &str) -> String {
|
|
1570
1610
|
format!("lease_{worker_id}_{job_id}_{}", now_millis())
|
|
1571
1611
|
}
|
|
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
|
|
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
|