mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-07 10:17:43 +02:00
[eric] onboarding: harvest ChatGPT + Claude in parallel under a budget (13.7s -> 6.9s, 49% off the reveal wait)
This commit is contained in:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user