[eric] onboarding: harvest ChatGPT + Claude in parallel under a budget (13.7s -> 6.9s, 49% off the reveal wait)

This commit is contained in:
ciregenz
2026-07-21 19:11:56 -07:00
parent 1042942d88
commit dc91a4225f
+25 -7
View File
@@ -5,11 +5,25 @@ the user's machine and providers; nothing here mutates state or leaves the box
except the prep call, which goes to the user's own configured model.
"""
import asyncio
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Awaitable
from typeguard import typechecked
# Hard cap on any single provider harvest so a wedged endpoint can't hold the whole reveal hostage
# (the raw-httpx paths already carry a 20s per-request timeout; this bounds the multi-request loop).
P_HARVEST_BUDGET_S = 26.0
async def p_budgeted(coro: Awaitable[str]) -> str:
"""Await a harvest under the budget; any failure (timeout, provider down) fails open to ''."""
try:
return await asyncio.wait_for(coro, timeout=P_HARVEST_BUDGET_S)
except Exception:
return ""
from backend.apps.onboarding.identity import build_identity
from backend.apps.onboarding.local_scan import run_local_scan
from backend.apps.onboarding.models import PrepRequest
@@ -48,16 +62,20 @@ async def post_prep(body: PrepRequest) -> dict:
from backend.apps.settings.store import load_settings
# ALWAYS read the ENTIRE recent conversations (not just titles) from the rich providers, ChatGPT via
# the codex connect token, Claude via the user's own browser session cookies, and PREFER that over
# whatever the frontend read. The frontend reads only the single connected provider, which for a
# Gemini/antigravity user is a titles-only DOM scrape that can surface a stale topic (the "skincare
# app" the user hasn't touched in ages). Multiple providers connected? We take all the rich ones and
# let the clustering pass merge them into one profile. Each fails open to "", so a missing one drops.
# the codex connect token (platform-independent), Claude via the user's own browser session cookies,
# and PREFER that over whatever the frontend read. The frontend reads only the single connected
# provider, which for a Gemini/antigravity user is a titles-only DOM scrape that can surface a stale
# topic (the "skincare app" the user hasn't touched in ages). Multiple providers connected? We take
# all the rich ones and let the clustering pass merge them. Each fails open to "", so a missing one
# drops. Harvested in PARALLEL under a budget: stacked awaits added a ~15s ChatGPT pull ON TOP of a
# ~8s Claude pull for ~23s of dead reveal time; gathered they overlap to the slower of the two.
chatgpt, claude = await asyncio.gather(
p_budgeted(harvest_chatgpt_usage()),
p_budgeted(harvest_claude_usage()),
)
parts: list[str] = []
chatgpt = await harvest_chatgpt_usage()
if chatgpt:
parts.append("ChatGPT conversations:\n" + chatgpt)
claude = await harvest_claude_usage()
if claude:
parts.append("Claude conversations:\n" + claude)
if parts: