Skip to main content

Fix Code Generation Resilience

Summary​

Improved strategy code generation resilience after OpenAI Responses API/network failures caused long waits, stuck tool states, blank code previews, and duplicate user turns during durable replay.

Root Cause​

  • The Codex/OpenAI Responses adapter had no bounded request timeout, no stream idle timeout, and no retry path for transient provider or transport failures.
  • write_strategy_code let provider errors bubble through as a generic tool failure, after which the planner could continue and re-enter tool calls.
  • Code preview hydration only trusted codeSoFar, so persisted progress in meta.code_so_far or final/partial result.codeText could render as an empty Code Generation block.
  • Durable replay inserted the run-start user turn by durable id only, so an optimistic local user turn with the same text could remain and make the message appear duplicated.

Changes​

  • Added bounded OpenAI Responses API handling in services/backend/src/lib/ai/openai-responses-adapter.ts:
    • 120s request timeout
    • 90s stream idle timeout
    • one retry for transient HTTP statuses and transport failures
    • request-id-aware error messages
    • abort propagation when streams are cancelled
  • Updated write_strategy_code in services/backend/src/routes/bots/bots-chat-handlers.ts:
    • retries transient generation failures once
    • emits initial and partial code_so_far progress
    • preserves partial code in tool error results when available
    • stops further tool replanning after strategy/analysis code-generation tool failures
    • fails with a clear no-save error when generation cannot complete
  • Updated durable replay in services/frontend/src/routes/bots/BotDetailPage.tsx:
    • restores code preview from codeSoFar, meta.code_so_far, or result.codeText
    • dedupes replayed user turns by matching message text and sender
    • reuses optimistic assistant turns for the durable run assistant
    • settles stale running tool calls when runs finish, error, cancel, or hydrate with no active run
  • Updated packages/chat-ui/src/StreamingChatPanel.tsx:
    • preserves code preview from final/partial tool results
    • settles running tools on done, error, cancelled, stream close, and non-abort catch paths
    • shows a nonblank running code panel with Waiting for the first code chunk... before the first streamed code delta

Key Snippets​

const RESPONSES_API_REQUEST_TIMEOUT_MS = 120_000;
const RESPONSES_API_STREAM_IDLE_TIMEOUT_MS = 90_000;
const RESPONSES_API_RETRY_STATUS_CODES = new Set([408, 409, 429, 500, 502, 503, 504, 520, 522, 524]);
const partialResult = latestCodeSoFar
? { ok: false, error: errorMsg, codeText: latestCodeSoFar, partial: true }
: null;
const extractToolCodePreview = (value) =>
value.codeSoFar ?? value.meta?.code_so_far ?? value.result?.codeText;

Validation​

  • pnpm --filter @quantago/api typecheck passed.
  • pnpm --filter @quantago/frontend typecheck passed.
  • pnpm --filter @quantago/api lint passed with existing warning-only baseline.
  • pnpm --filter @quantago/frontend lint passed with existing warning-only baseline.
  • pnpm typecheck passed for API, frontend, admin, docs, and landing.
  • pnpm lint passed with existing warning-only baseline.

Deployments​

  • Dev backend version: a6e70e3d-c148-4632-9544-c6038bd906f7
  • Production backend version: 0bdfee8c-36b2-4c5b-925b-08a1fd55ce4b
  • Dev frontend Pages: https://a2ec6c65.quantago-app.pages.dev (https://develop.quantago-app.pages.dev)
  • Production frontend Pages: https://787647d9.quantago-app.pages.dev

Health Checks​

  • Dev API: HTTP 200
  • Production API: HTTP 200
  • Dev frontend: HTTP 200
  • Production frontend: HTTP 200