From 658f3191472ee1b9ded767312e1ac203ba91247f Mon Sep 17 00:00:00 2001 From: kshitijk4poor <82637225+kshitijk4poor@users.noreply.github.com> Date: Tue, 15 Sep 2026 15:04:32 +0000 Subject: [PATCH] fix(free-tier): setup.ready carries the failure block flat, the shape setup.status already spreads `SetupRecord.as_payload()` serialised the record verbatim, so the broadcast nested `failure: {...}` while `setup.status` spread the same four keys flat. A client keyed on `error_code` saw it on one surface and not the other. Flatten it in `as_payload`, declare the three optional keys on `SetupReadyPayload`, and regenerate the TS/OpenRPC contract. --- apps/shared/src/gateway-contract.generated.ts | 3 ++ apps/shared/src/gateway-contract.openrpc.json | 36 +++++++++++++++++++ hermes_cli/free_tier_bootstrap.py | 6 +++- tui_gateway/contracts/events.py | 4 +++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/apps/shared/src/gateway-contract.generated.ts b/apps/shared/src/gateway-contract.generated.ts index e6bd64dc3a..8c1f85edd5 100644 --- a/apps/shared/src/gateway-contract.generated.ts +++ b/apps/shared/src/gateway-contract.generated.ts @@ -3838,6 +3838,9 @@ export interface SetupReadyPayload { has_identity: boolean other_providers: boolean error?: string + error_code?: string | null + retryable?: boolean | null + retry_after?: number | null finished_at: number [key: string]: unknown } diff --git a/apps/shared/src/gateway-contract.openrpc.json b/apps/shared/src/gateway-contract.openrpc.json index 543fda53b7..a05d5905fe 100644 --- a/apps/shared/src/gateway-contract.openrpc.json +++ b/apps/shared/src/gateway-contract.openrpc.json @@ -27293,6 +27293,42 @@ "title": "Error", "type": "string" }, + "error_code": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Code" + }, + "retryable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retryable" + }, + "retry_after": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Retry After" + }, "finished_at": { "title": "Finished At", "type": "number" diff --git a/hermes_cli/free_tier_bootstrap.py b/hermes_cli/free_tier_bootstrap.py index c77cd71988..ea7f21514c 100644 --- a/hermes_cli/free_tier_bootstrap.py +++ b/hermes_cli/free_tier_bootstrap.py @@ -45,7 +45,11 @@ class SetupRecord: finished_at: float = field(default_factory=time.time) def as_payload(self) -> Dict[str, Any]: - return asdict(self) + # The broadcast carries the failure block flat, the same shape ``setup.status`` spreads, + # so a client keys on ``error_code`` identically whichever surface it read. + payload = asdict(self) + payload.update(payload.pop("failure")) + return payload def failure_fields(self) -> Dict[str, Any]: return dict(self.failure) diff --git a/tui_gateway/contracts/events.py b/tui_gateway/contracts/events.py index 6904f690da..85c8b16881 100644 --- a/tui_gateway/contracts/events.py +++ b/tui_gateway/contracts/events.py @@ -72,6 +72,10 @@ class SetupReadyPayload(OpenPayload): has_identity: bool other_providers: bool error: str = "" + # Present only when the free-tier mint did not happen (``anon_auth.MintFailure.as_payload``). + error_code: str | None = None + retryable: bool | None = None + retry_after: int | None = None finished_at: float