Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions CLAUDE.md

Large diffs are not rendered by default.

54 changes: 47 additions & 7 deletions dashboard/backend/api/routers/backtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1765,6 +1765,7 @@ def run_backtest_background(
stdin_payload=execution_handoff_payload or "",
timeout=subprocess_timeout,
live_run_id=resolved_live_run_id,
redact_secret=financial_datasets_api_key,
)

# Print script output for debugging
Expand All @@ -1775,14 +1776,18 @@ def run_backtest_background(
# byte the child ever wrote held in parent RAM for the whole run; the
# head this comment used to promise (universe, decision source, FX
# bootstrap) is exactly what the head half of that buffer keeps.
if result.stdout:
# Relayed ERROR: llm. lines were already printed live by _drain_stream;
# dumping them again would count every quota event twice in the log.
dumped_stdout = _without_relayed_lines(result.stdout or "")
dumped_stderr = _without_relayed_lines(result.stderr or "")
if dumped_stdout:
print(
f"STDOUT:\n{_redact_credentials(result.stdout, financial_datasets_api_key)}",
f"STDOUT:\n{_redact_credentials(dumped_stdout, financial_datasets_api_key)}",
flush=True,
)
if result.stderr:
if dumped_stderr:
print(
f"STDERR:\n{_redact_credentials(result.stderr, financial_datasets_api_key)}",
f"STDERR:\n{_redact_credentials(dumped_stderr, financial_datasets_api_key)}",
flush=True,
)
print(f"Return code: {result.returncode}", flush=True)
Expand Down Expand Up @@ -2544,7 +2549,27 @@ def text(self) -> str:
)


def _drain_stream(stream: Any, capture: _BoundedStreamCapture) -> None:
_RELAYED_CHILD_LINE_PREFIX = "ERROR: llm."


def _without_relayed_lines(text: str) -> str:
"""Drop the lines ``_drain_stream`` already echoed to the service log.

Applied to the end-of-run dump only, so a relayed line reaches the log
once. The capture itself keeps them: it also feeds the failure summary.
"""
return "".join(
line
for line in text.splitlines(keepends=True)
if not line.startswith(_RELAYED_CHILD_LINE_PREFIX)
)


def _drain_stream(
stream: Any,
capture: _BoundedStreamCapture,
redact_secret: Optional[str] = None,
) -> None:
"""Copy one child stream into a bounded capture until EOF.

This is what makes ``Popen`` + ``wait`` safe: without a reader the child
Expand All @@ -2555,6 +2580,16 @@ def _drain_stream(stream: Any, capture: _BoundedStreamCapture) -> None:
try:
for line in iter(stream.readline, ""):
capture.feed(line)
if line.startswith(_RELAYED_CHILD_LINE_PREFIX):
# Echoed live, not left to the capture: the timeout path never
# dumps it, a normal exit dumps it only when the run ends, and
# a long run's middle is elided. Redacted like the dump, since
# the prefix is all that selects a line for this path.
print(
_redact_credentials(line, redact_secret),
end="",
flush=True,
)
except (OSError, ValueError):
# The pipe was closed under us, which is the kill path doing its job.
# Whatever was read before that still stands and is still worth logging.
Expand Down Expand Up @@ -2586,6 +2621,7 @@ def _run_backtest_subprocess(
stdin_payload: str,
timeout: int,
live_run_id: Optional[str],
redact_secret: Optional[str] = None,
) -> _BacktestSubprocessOutcome:
"""Run the backtest child, draining its output into bounded buffers.

Expand Down Expand Up @@ -2632,10 +2668,14 @@ def _run_backtest_subprocess(
stderr_capture = _BoundedStreamCapture()
readers = [
_StreamReaderThread(
target=_drain_stream, args=(process.stdout, stdout_capture), daemon=True
target=_drain_stream,
args=(process.stdout, stdout_capture, redact_secret),
daemon=True,
),
_StreamReaderThread(
target=_drain_stream, args=(process.stderr, stderr_capture), daemon=True
target=_drain_stream,
args=(process.stderr, stderr_capture, redact_secret),
daemon=True,
),
]
for reader in readers:
Expand Down
37 changes: 37 additions & 0 deletions dashboard/backend/domain/model_providers/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
CredentialNotFoundError,
CredentialOwnershipError,
ProviderNotFoundError,
COMMONSTACK_ALLOWLIST_BACKFILLS,
SEEDED_PROVIDERS,
commonstack_allowlist_backfill,
deserialize_capabilities,
serialize_capabilities,
validate_adapter_type,
Expand Down Expand Up @@ -156,6 +158,7 @@ def _init_schema(self) -> None:
),
)
self._migrate_legacy_openrouter_platform_flag(conn)
self._migrate_commonstack_allowlist(conn)
conn.commit()
conn.close()

Expand Down Expand Up @@ -205,6 +208,40 @@ def _migrate_legacy_openrouter_platform_flag(conn: sqlite3.Connection) -> None:
(migration_id, _utcnow_iso()),
)

@staticmethod
def _migrate_commonstack_allowlist(conn: sqlite3.Connection) -> None:
"""Backfill newly verified CommonStack models into a seeded row, once.

Each backfill appends only the ids it introduced, and is recorded even
when nothing changed, so an admin who removes one of those models --
before or after it runs -- is not overridden on a later boot.
"""

for migration_id, model_ids in COMMONSTACK_ALLOWLIST_BACKFILLS:
if conn.execute(
"SELECT 1 FROM model_provider_migrations WHERE migration_id = ?",
(migration_id,),
).fetchone():
continue
now = _utcnow_iso()
provider = conn.execute(
"SELECT capabilities_json FROM provider_registry WHERE provider_id = 'commonstack'"
).fetchone()
updated = (
commonstack_allowlist_backfill(provider["capabilities_json"], model_ids)
if provider
else None
)
if updated is not None:
conn.execute(
"UPDATE provider_registry SET capabilities_json = ?, updated_at = ? WHERE provider_id = 'commonstack'",
(updated, now),
)
conn.execute(
"INSERT INTO model_provider_migrations (migration_id, applied_at) VALUES (?, ?)",
(migration_id, now),
)

@staticmethod
def _ensure_user_credential_columns(conn: sqlite3.Connection) -> None:
columns = {
Expand Down
41 changes: 41 additions & 0 deletions dashboard/backend/domain/model_providers/repository_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,17 @@ def secret_fingerprint(secret: str) -> str:
"anthropic/claude-sonnet-4-6",
"deepseek/deepseek-v4-pro",
"qwen/qwen3.7-plus",
"anthropic/claude-haiku-4-5",
)

# The seed below is ``ON CONFLICT DO NOTHING``, so an id appended to the
# allowlist above never reaches a deployment whose row already exists. Each
# addition therefore ships a one-shot backfill naming ONLY the ids it
# introduced -- never "whatever the allowlist now holds", which would re-add
# every model an admin had removed from the live row. Append a new entry
# (``-v2``, ...) with the next addition; never edit a shipped one.
COMMONSTACK_ALLOWLIST_BACKFILLS: tuple[tuple[str, tuple[str, ...]], ...] = (
("commonstack-allowlist-v1", ("anthropic/claude-haiku-4-5",)),
)


Expand Down Expand Up @@ -253,6 +264,36 @@ def serialize_capabilities(value: ProviderCapabilities | dict) -> str:
return json.dumps(capabilities.model_dump(), sort_keys=True, separators=(",", ":"))


def commonstack_allowlist_backfill(
capabilities_json: str | None,
model_ids: tuple[str, ...],
) -> str | None:
"""Return ``capabilities_json`` with ``model_ids`` appended where missing.

Only appends: an id an admin added stays and nothing is reordered. Returns
None when there is nothing to add, when the stored allowlist is empty (an
empty allowlist routes nothing, so it is how an admin turns the lane off,
and adding one model would turn it back on), or when the stored row cannot
be read -- ``deserialize_capabilities`` turns an unreadable row into
default capabilities, and writing that back would erase whatever it held.
"""
try:
capabilities = ProviderCapabilities.model_validate(
json.loads(capabilities_json or "")
)
except (TypeError, ValueError):
return None
current = capabilities.model_allowlist
if not current:
return None
missing = tuple(model_id for model_id in model_ids if model_id not in current)
if not missing:
return None
return serialize_capabilities(
capabilities.model_copy(update={"model_allowlist": current + missing})
)


def deserialize_capabilities(value: str | None) -> ProviderCapabilities:
try:
return ProviderCapabilities.model_validate(json.loads(value or "{}"))
Expand Down
39 changes: 39 additions & 0 deletions dashboard/backend/domain/model_providers/repository_postgres.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
CredentialNotFoundError,
CredentialOwnershipError,
ProviderNotFoundError,
COMMONSTACK_ALLOWLIST_BACKFILLS,
SEEDED_PROVIDERS,
commonstack_allowlist_backfill,
deserialize_capabilities,
serialize_capabilities,
validate_adapter_type,
Expand Down Expand Up @@ -230,6 +232,7 @@ def _init_schema(self) -> None:
),
)
self._migrate_legacy_openrouter_platform_flag(cur)
self._migrate_commonstack_allowlist(cur)

@staticmethod
def _migrate_legacy_openrouter_platform_flag(cur) -> None:
Expand Down Expand Up @@ -282,6 +285,42 @@ def _migrate_legacy_openrouter_platform_flag(cur) -> None:
(migration_id, now),
)

@staticmethod
def _migrate_commonstack_allowlist(cur) -> None:
"""Backfill newly verified CommonStack models into a seeded row, once.

Each backfill appends only the ids it introduced, and is recorded even
when nothing changed, so an admin who removes one of those models --
before or after it runs -- is not overridden on a later boot.
"""

for migration_id, model_ids in COMMONSTACK_ALLOWLIST_BACKFILLS:
cur.execute(
"SELECT 1 FROM model_provider_migrations WHERE migration_id = %s",
(migration_id,),
)
if cur.fetchone():
continue
now = _utcnow_iso()
cur.execute(
"SELECT capabilities_json FROM provider_registry WHERE provider_id = 'commonstack'"
)
provider = cur.fetchone()
updated = (
commonstack_allowlist_backfill(provider["capabilities_json"], model_ids)
if provider
else None
)
if updated is not None:
cur.execute(
"UPDATE provider_registry SET capabilities_json = %s, updated_at = %s WHERE provider_id = 'commonstack'",
(updated, now),
)
cur.execute(
"INSERT INTO model_provider_migrations (migration_id, applied_at) VALUES (%s, %s)",
(migration_id, now),
)

def list_enabled_providers(self, *, mode: str = "byok") -> list[dict[str, Any]]:
if mode not in {"byok", "platform"}:
raise ValueError("unsupported provider mode")
Expand Down
Loading
Loading