Python SDK 2.5.0 (research background mode + frontier effort)#24
Python SDK 2.5.0 (research background mode + frontier effort)#24tyler5673 wants to merge 17 commits into
Conversation
Adds background-mode research (async task submission, polling, streaming) to the SDK. Adds you.research(background=True), you.get_research_task(), you.stream_research_task(), and the hand-maintained youdotcom.research_helpers module. All 2.4.0 features unchanged. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- Remove dead RawStreamEvent.retry field (never read by helpers/tests) - Extract _resolve_from_final_get[_async] helpers (dedup 4x final-GET logic) - Table-drive _raise_stream_error[_async] via _STREAM_ERROR_BRANCHES tuple - Factor _stream_build_kwargs/_stream_hook_ctx shared by sync/async stream-open - Inline _poll_detail[_async] into their single callers - P1 fix: replace daemon-thread + consumer.join with single-threaded loop using httpx read timeout (no more leaked blocked threads on socket hangs) - P2 fix: remove dead deadline/time.monotonic() inner check (unreachable - httpx.TimeoutException already enforces the timeout) - P2 fix: remove stream_exc/except BaseException indirection (fossil of threaded design; exceptions now propagate naturally) - P3: fix research_and_wait docstring (one GET -> a GET, second in fallback) - P3: document retry_config=None divergence from generated stream_research_task - Add 7 new typed-error tests (403/500/4XX/5XX/async 401/403/500) - Fix live test TypeError masking: check 'TaskResponse' in str(e) before skip - Extract _make_wait_handler factory + shared mock stream classes in tests 158/158 tests pass, pylint 10.00/10, mypy clean. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…fallback, TypeError masking) - CHANGELOG: fix stream_research_task terminal event list (was missing 'completed' in ok set and 'failed' in err set; now matches the actual _TERMINAL_STREAM_EVENTS_OK/ERR frozensets in research_helpers.py) - CHANGELOG: document research_and_wait timeout/stream-close fallback GET behavior (was described as just 'fetch the final TaskDetail') - MIGRATION: fix streaming example terminal event set to include 'complete' (was only 'response.done' + 'completed') - MIGRATION: document research_and_wait fallback GET behavior - examples: fix research_and_wait_example TypeError masking — check 'TaskResponse' in str(e) before skipping, re-raise real TypeErrors (matches the fix applied to test_live.py) - PR #23 description: fix research_and_wait row (was 'No polling fallback'; now documents the final-GET fallback) and stream_research_task terminal event list Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…atches async) Addresses PR feedback (claude[bot] review 2026-07-22): sync research_and_wait used timeout_s only as a per-read stall timeout (httpx read timeout), while the async variant used asyncio.wait_for as a total wall-clock budget. This meant a server streaming heartbeats forever would never time out in sync mode. Fix: add a total deadline check inside the stream loop that breaks and sets timed_out=True when time.monotonic() >= deadline. Both sync and async now enforce timeout_s as a total budget. Added test_research_and_wait_total_deadline_not_stall_timeout: streams non-terminal 'ping' events every 10ms (fast enough to not trip the per-read timeout) and verifies the total deadline fires at timeout_s=0.5s. 159/159 tests pass, pylint 10.00/10, mypy clean. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…t-non-completed test Addresses PR feedback (claude[bot] review 2026-07-22T00:57): - Fix Go mockserver comment: said 'four' terminal events but SDK treats six (OK: response.done, complete, completed; ERROR: error, failed, cancelled) - Add test_research_and_wait_ok_event_but_get_non_completed_raises: covers the defensive branch where stream emits response.done but the follow-up GET returns non-completed status (RuntimeError path in _resolve_from_final_get) 160/160 tests pass, pylint 10.00/10, mypy clean, Go builds clean. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add ResearchEffort.FRONTIER for the highest-quality, longest-running research tasks (up to 4 hours). Frontier only works with background=true; sending it without returns 422. The enum value is injected via overlay (overlays/python_overlay.yaml) so it survives Speakeasy regenerations. - Update docstrings in researcheffort.py, researchop.py, sdk.py - Update CHANGELOG.md, MIGRATION.md, docs/models/researcheffort.md, docs/sdks/you/README.md - Add tests: frontier+background happy path, frontier-without-background 422 - Add research_stream_example() to examples/api-example-calls.py - Update PR #23 description Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…ll defaults research_and_wait now auto-selects timeout_s based on research_effort when omitted: 600s (10 min) for standard/deep/exhaustive, 14400s (4 hr) for frontier. Explicit timeout_s always takes precedence. poll_research_task cannot auto-detect (receives task_id, not effort) so its defaults (interval_s=2.0, timeout_s=600.0) are now documented in docstrings and MIGRATION.md with a per-tier guidance table. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Add LITE tier to FinanceResearchEffort enum (overlay-injected, same pattern as ResearchEffort.FRONTIER). Update docstrings, docs, CHANGELOG, and MIGRATION. Add test_finance_research_lite_effort. Fix three PR #24 review items: 1. _resolve_from_final_get now re-polls up to 3 times (1s interval) when the stream signals OK but GET returns non-completed, tolerating backend commit races. Updated test_research_and_wait_ok_event_but_get_non_completed_raises and added test_research_and_wait_ok_event_repoll_succeeds. 2. research_and_wait_async now catches httpx.TimeoutException in addition to asyncio.TimeoutError, matching sync behavior. Added test_async_research_and_wait_httpx_readtimeout_falls_back_to_get. 3. Removed misplaced pylint disable-next=protected-access in stream_research. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
- test_frontier_background_completes: submits frontier task with background=true via research_and_wait, verifies TaskDetail completed. Passed live in 607s. - test_frontier_without_background_raises_422: verifies 422 when frontier is sent without background=true. Passed live. - test_finance_research_lite_effort: verifies LITE returns a quick answer. Skips gracefully when server hasn't deployed the tier yet (422). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
research_and_wait_async now passes stream_timeout_ms=int(timeout_s*1000) when the caller didn't set an explicit timeout_ms, matching the sync variant. Without this, a caller-set You(timeout_ms=60000) would cap SSE reads at 60s and cause premature TimeoutError on frontier tasks with auto timeout_s=14400. Also updated the async docstring to note the per-read timeout parity. Addresses PR #24 review comment 3640119913. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…final_get When the re-poll loop hits a terminal non-completed status (failed/ cancelled) on the first GET, raise immediately with a clear message instead of falling through to the misleading after-N-attempts error. Added test_research_and_wait_ok_event_but_get_failed_raises_immediately to cover the early-break branch. Addresses PR #24 review comments 3640244682 and 3640245293. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…ests Sync research_and_wait now honors caller timeout_ms for the stream read when provided (matching async), falling back to timeout_s*1000 when not. Updated both docstrings to accurately describe the shared behavior. Added async mirrors for repoll-succeeds and ok-event-but-get-failed tests, closing the coverage gap flagged in review. Addresses PR #24 review comments 3640262585 and 3640262855 (the latter was already fixed in 039fee1 but commented on an older revision). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
… at timeout_s 1. research_and_wait[_async] now catches stream-open failures (transient 500, 404 on just-created task, etc.) and falls back to poll_research_task so a successfully-submitted task is never abandoned. 2. SSE per-read timeout is now capped at timeout_s*1000 in both variants, preventing a caller-set timeout_ms larger than timeout_s from causing the sync wall-clock to exceed the budget. 3. Added test_async_frontier_auto_timeout_completes_without_premature_timeout to mirror the sync frontier auto-timeout coverage. Addresses PR #24 review comments 3640308132, 3640308929, 3640309427. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
The sync variant previously only caught httpx.TimeoutException during stream iteration, letting non-timeout errors (RemoteProtocolError, ConnectError on dropped connections) propagate unrecoverably. Now catches Exception and falls back to poll_research_task, matching the async variant's behavior and the stream-open failure fallback. Addresses PR #24 review comment 3640374576. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…from timeout_ms - Change `except Exception` to `except httpx.TransportError` for both stream-open and mid-stream fallbacks (sync + async). Typed auth errors (401/403/404/500 from _raise_stream_error) now propagate to the caller instead of being swallowed and masked by a different error type from poll_research_task. - Decouple SSE per-read timeout from caller's timeout_ms. Always use int(timeout_s * 1000) for stream reads. Previously, a caller with timeout_ms=30000 on a frontier task (timeout_s=14400) would get a misleading "did not complete within 14400s" after only 30s. - Add 5 new tests: stream-open TransportError -> poll succeeds (sync + async), stream-open 401 -> typed error propagates (sync + async), mid-stream TransportError -> poll succeeds (sync). Addresses PR #24 review comments 3640425979 and 3640426348. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…andler The `return poll_research_task(...)` inside the `try` block meant `finally: stream.close()` only ran after the entire poll loop completed, keeping the failed SSE connection open during polling. Now calling `stream.close()` explicitly before the return so cleanup happens first. Addresses PR #24 review comment 3640517073. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Review Summary — 2.5.0 (research background mode + frontier effort)Reviewed with focus on the hand-maintained surfaces ( Code quality & correctness ✅
Test coverage ✅ (excellent)
Documentation ✅
Breaking changes ✅The Security ✅No hardcoded secrets, no injection surface. Test/mock credentials are obvious placeholders ( Minor / non-blocking
🤖 Generated with Claude Code |
The SSE per-read timeout was decoupled from timeout_ms in a previous commit but the sync docstring still mentioned "(or the caller's timeout_ms when provided)". Now matches the actual behavior and the async variant's docstring. Addresses PR #24 review comment 3640569229. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…rs (#25) * feat: Python SDK 2.5.0 — Research Background Mode Adds background-mode research (async task submission, polling, streaming) to the SDK. Adds you.research(background=True), you.get_research_task(), you.stream_research_task(), and the hand-maintained youdotcom.research_helpers module. All 2.4.0 features unchanged. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * refactor: ponytail shrinks + P2 fixes for research_helpers - Remove dead RawStreamEvent.retry field (never read by helpers/tests) - Extract _resolve_from_final_get[_async] helpers (dedup 4x final-GET logic) - Table-drive _raise_stream_error[_async] via _STREAM_ERROR_BRANCHES tuple - Factor _stream_build_kwargs/_stream_hook_ctx shared by sync/async stream-open - Inline _poll_detail[_async] into their single callers - P1 fix: replace daemon-thread + consumer.join with single-threaded loop using httpx read timeout (no more leaked blocked threads on socket hangs) - P2 fix: remove dead deadline/time.monotonic() inner check (unreachable - httpx.TimeoutException already enforces the timeout) - P2 fix: remove stream_exc/except BaseException indirection (fossil of threaded design; exceptions now propagate naturally) - P3: fix research_and_wait docstring (one GET -> a GET, second in fallback) - P3: document retry_config=None divergence from generated stream_research_task - Add 7 new typed-error tests (403/500/4XX/5XX/async 401/403/500) - Fix live test TypeError masking: check 'TaskResponse' in str(e) before skip - Extract _make_wait_handler factory + shared mock stream classes in tests 158/158 tests pass, pylint 10.00/10, mypy clean. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * docs: fix 2.5.0 doc inaccuracies (terminal events, research_and_wait fallback, TypeError masking) - CHANGELOG: fix stream_research_task terminal event list (was missing 'completed' in ok set and 'failed' in err set; now matches the actual _TERMINAL_STREAM_EVENTS_OK/ERR frozensets in research_helpers.py) - CHANGELOG: document research_and_wait timeout/stream-close fallback GET behavior (was described as just 'fetch the final TaskDetail') - MIGRATION: fix streaming example terminal event set to include 'complete' (was only 'response.done' + 'completed') - MIGRATION: document research_and_wait fallback GET behavior - examples: fix research_and_wait_example TypeError masking — check 'TaskResponse' in str(e) before skipping, re-raise real TypeErrors (matches the fix applied to test_live.py) - PR #23 description: fix research_and_wait row (was 'No polling fallback'; now documents the final-GET fallback) and stream_research_task terminal event list Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: sync research_and_wait now enforces total wall-clock deadline (matches async) Addresses PR feedback (claude[bot] review 2026-07-22): sync research_and_wait used timeout_s only as a per-read stall timeout (httpx read timeout), while the async variant used asyncio.wait_for as a total wall-clock budget. This meant a server streaming heartbeats forever would never time out in sync mode. Fix: add a total deadline check inside the stream loop that breaks and sets timed_out=True when time.monotonic() >= deadline. Both sync and async now enforce timeout_s as a total budget. Added test_research_and_wait_total_deadline_not_stall_timeout: streams non-terminal 'ping' events every 10ms (fast enough to not trip the per-read timeout) and verifies the total deadline fires at timeout_s=0.5s. 159/159 tests pass, pylint 10.00/10, mypy clean. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * test: fix Go mock comment (four->six terminal events) + add ok-but-get-non-completed test Addresses PR feedback (claude[bot] review 2026-07-22T00:57): - Fix Go mockserver comment: said 'four' terminal events but SDK treats six (OK: response.done, complete, completed; ERROR: error, failed, cancelled) - Add test_research_and_wait_ok_event_but_get_non_completed_raises: covers the defensive branch where stream emits response.done but the follow-up GET returns non-completed status (RuntimeError path in _resolve_from_final_get) 160/160 tests pass, pylint 10.00/10, mypy clean, Go builds clean. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * feat: add frontier research effort tier + streaming example Add ResearchEffort.FRONTIER for the highest-quality, longest-running research tasks (up to 4 hours). Frontier only works with background=true; sending it without returns 422. The enum value is injected via overlay (overlays/python_overlay.yaml) so it survives Speakeasy regenerations. - Update docstrings in researcheffort.py, researchop.py, sdk.py - Update CHANGELOG.md, MIGRATION.md, docs/models/researcheffort.md, docs/sdks/you/README.md - Add tests: frontier+background happy path, frontier-without-background 422 - Add research_stream_example() to examples/api-example-calls.py - Update PR #23 description Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * feat: auto-adjust research_and_wait timeout for frontier + surface poll defaults research_and_wait now auto-selects timeout_s based on research_effort when omitted: 600s (10 min) for standard/deep/exhaustive, 14400s (4 hr) for frontier. Explicit timeout_s always takes precedence. poll_research_task cannot auto-detect (receives task_id, not effort) so its defaults (interval_s=2.0, timeout_s=600.0) are now documented in docstrings and MIGRATION.md with a per-tier guidance table. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * feat: add FinanceResearchEffort.LITE + fix PR review findings Add LITE tier to FinanceResearchEffort enum (overlay-injected, same pattern as ResearchEffort.FRONTIER). Update docstrings, docs, CHANGELOG, and MIGRATION. Add test_finance_research_lite_effort. Fix three PR #24 review items: 1. _resolve_from_final_get now re-polls up to 3 times (1s interval) when the stream signals OK but GET returns non-completed, tolerating backend commit races. Updated test_research_and_wait_ok_event_but_get_non_completed_raises and added test_research_and_wait_ok_event_repoll_succeeds. 2. research_and_wait_async now catches httpx.TimeoutException in addition to asyncio.TimeoutError, matching sync behavior. Added test_async_research_and_wait_httpx_readtimeout_falls_back_to_get. 3. Removed misplaced pylint disable-next=protected-access in stream_research. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * test: add live tests for frontier research + finance lite effort - test_frontier_background_completes: submits frontier task with background=true via research_and_wait, verifies TaskDetail completed. Passed live in 607s. - test_frontier_without_background_raises_422: verifies 422 when frontier is sent without background=true. Passed live. - test_finance_research_lite_effort: verifies LITE returns a quick answer. Skips gracefully when server hasn't deployed the tier yet (422). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: bound async SSE per-read timeout to timeout_s (match sync variant) research_and_wait_async now passes stream_timeout_ms=int(timeout_s*1000) when the caller didn't set an explicit timeout_ms, matching the sync variant. Without this, a caller-set You(timeout_ms=60000) would cap SSE reads at 60s and cause premature TimeoutError on frontier tasks with auto timeout_s=14400. Also updated the async docstring to note the per-read timeout parity. Addresses PR #24 review comment 3640119913. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: distinguish early-break from exhausted re-poll in _resolve_from_final_get When the re-poll loop hits a terminal non-completed status (failed/ cancelled) on the first GET, raise immediately with a clear message instead of falling through to the misleading after-N-attempts error. Added test_research_and_wait_ok_event_but_get_failed_raises_immediately to cover the early-break branch. Addresses PR #24 review comments 3640244682 and 3640245293. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: align sync/async stream timeout_ms handling + add async repoll tests Sync research_and_wait now honors caller timeout_ms for the stream read when provided (matching async), falling back to timeout_s*1000 when not. Updated both docstrings to accurately describe the shared behavior. Added async mirrors for repoll-succeeds and ok-event-but-get-failed tests, closing the coverage gap flagged in review. Addresses PR #24 review comments 3640262585 and 3640262855 (the latter was already fixed in 039fee1 but commented on an older revision). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: stream-open failure falls back to polling + cap per-read timeout at timeout_s 1. research_and_wait[_async] now catches stream-open failures (transient 500, 404 on just-created task, etc.) and falls back to poll_research_task so a successfully-submitted task is never abandoned. 2. SSE per-read timeout is now capped at timeout_s*1000 in both variants, preventing a caller-set timeout_ms larger than timeout_s from causing the sync wall-clock to exceed the budget. 3. Added test_async_frontier_auto_timeout_completes_without_premature_timeout to mirror the sync frontier auto-timeout coverage. Addresses PR #24 review comments 3640308132, 3640308929, 3640309427. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: sync research_and_wait falls back to polling on mid-stream errors The sync variant previously only caught httpx.TimeoutException during stream iteration, letting non-timeout errors (RemoteProtocolError, ConnectError on dropped connections) propagate unrecoverably. Now catches Exception and falls back to poll_research_task, matching the async variant's behavior and the stream-open failure fallback. Addresses PR #24 review comment 3640374576. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: narrow fallback to httpx.TransportError + decouple SSE per-read from timeout_ms - Change `except Exception` to `except httpx.TransportError` for both stream-open and mid-stream fallbacks (sync + async). Typed auth errors (401/403/404/500 from _raise_stream_error) now propagate to the caller instead of being swallowed and masked by a different error type from poll_research_task. - Decouple SSE per-read timeout from caller's timeout_ms. Always use int(timeout_s * 1000) for stream reads. Previously, a caller with timeout_ms=30000 on a frontier task (timeout_s=14400) would get a misleading "did not complete within 14400s" after only 30s. - Add 5 new tests: stream-open TransportError -> poll succeeds (sync + async), stream-open 401 -> typed error propagates (sync + async), mid-stream TransportError -> poll succeeds (sync). Addresses PR #24 review comments 3640425979 and 3640426348. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: close stream before fallback poll in mid-stream TransportError handler The `return poll_research_task(...)` inside the `try` block meant `finally: stream.close()` only ran after the entire poll loop completed, keeping the failed SSE connection open during polling. Now calling `stream.close()` explicitly before the return so cleanup happens first. Addresses PR #24 review comment 3640517073. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * docs: fix sync docstring to drop stale timeout_ms parenthetical The SSE per-read timeout was decoupled from timeout_ms in a previous commit but the sync docstring still mentioned "(or the caller's timeout_ms when provided)". Now matches the actual behavior and the async variant's docstring. Addresses PR #24 review comment 3640569229. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * ci: add Droid Auto Review workflow for automated PR reviews Triggers on PR open/synchronize/reopen for internal contributors. External contributors can be reviewed via workflow_dispatch. Requires FACTORY_API_KEY secret and Factory Droid GitHub App installed. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * ci: remove Claude Code review workflow in favor of Droid Auto Review The droid-review.yml workflow now handles automated PR reviews. Removes the claude.yml workflow that used anthropics/claude-code-action. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: sync Speakeasy version files to 2.5.0 gen.yaml python.version and gen.lock releaseVersion were left at 2.4.0 while pyproject.toml and _version.py were already 2.5.0. Without this sync, the next speakeasy run would silently revert the version bump. Addresses PR #25 review comment 3640806529. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * chore: remove .speakeasy config and generate-sdk workflow No longer using Speakeasy for SDK generation. Removes: - .speakeasy/ (gen.yaml, gen.lock, workflow.yaml, workflow.lock, etc.) - .github/workflows/generate-sdk.yml (depended on speakeasy bump/run) Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: address Droid Auto Review feedback (P0/P1/P2) - P0: Fix actions/checkout@v7 -> @v4 (v7 not published) - P1: Fix broken link in README.md (models/.md -> researchtaskstreamevent.md) - P1: Make MIGRATION.md code blocks self-contained with imports + You() - P2: Add TODO comment for curl|sh integrity verification in workflow_dispatch Addresses PR #25 review comments 3641083815, 3641083827, 3641083831, 3641083837. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * docs: fix TaskDetail/TaskResponse timestamp types (date -> datetime) Generated docs incorrectly linked to Python date objects instead of datetime. Updated to match the actual SDK types in taskdetail.py and taskresponse.py. Addresses PR #25 review comments 3641189866 and 3641189887. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * docs: add frontier to ResearchRequest research_effort field docs The researchrequest.md docs listed lite/standard/deep/exhaustive but omitted frontier (which requires background=true). Added frontier with the background constraint note. Addresses PR #25 review comment 3641288647. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --------- Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Summary
Python SDK 2.5.0 release introducing background-mode research: async task submission, polling, and streaming for long-running research tasks. Also adds the new
frontierresearch effort tier for highest-quality, long-running research, and the newlitefinance research effort tier for quick financial questions.New Features
you.research(background=True)TaskResponsewithtask_idandstream_urlinstead of blocking for inlineResearchResponseyou.get_research_task(task_id=...)GET /v1/research/{task_id}, returnsTaskDetailwithresultpopulated on completionyou.stream_research_task(task_id=..., from_id=0)GET /v1/research/{task_id}/stream. Terminal event names:response.done,complete,completed(success);error,failed,cancelled(failure)ResearchEffort.FRONTIERbackground=true); sendingfrontierwithoutbackground=truereturns a422.FinanceResearchEffort.LITEdeep. No migration required; existingDEEPandEXHAUSTIVEvalues are unchanged.Convenience Helpers (
youdotcom.research_helpers)Hand-maintained, regen-safe module:
research_background()/_async()TaskResponsedirectly (no Union narrowing)poll_research_task()/_async()completed,failed,cancelled). Defaults:interval_s=2.0,timeout_s=600.0. Forfrontiertasks, passtimeout_s=14400explicitly.research_and_wait()/_async()TaskDetail.timeout_sauto-adjusts based onresearch_effort: 600s for standard/deep/exhaustive, 14400s (4 hours) forfrontier. Bounded re-poll tolerates backend commit races.stream_research()/_async()stream_research_task()for real tasks)Key Changes
you.research()return type widened toUnion[ResearchResponse, TaskResponse]. Runtime behavior unchanged whenbackground=False(default). Statically-typed callers accessingres.outputmay need anisinstance(res, ResearchResponse)narrow to satisfy mypy/pyright.ResearchEffort.FRONTIERenum value for the highest-quality, longest-running research tier. Documented inCHANGELOG.md,MIGRATION.md,docs/models/researcheffort.md, anddocs/sdks/you/README.md.FinanceResearchEffort.LITEenum value for quick finance research answers. Documented inCHANGELOG.md,MIGRATION.md,docs/models/financeresearcheffort.md, anddocs/sdks/you/README.md.TaskResponse,TaskDetail,ResearchTaskStreamEvent,Eventenum, and 8 typed error classes.stream_researchrecommended overstream_research_taskfor real tasks — the server emits intermediate workflow events not in the strictEventenum, which causesResponseValidationErrorin the generated decoder. The tolerant helper surfaces them as raw dicts instead._resolve_from_final_getre-polls up to 3 times when the stream signals OK but the GET status hasn't caught up, with a clear error for terminal non-completed vs. exhausted attempts.research_and_waitvariants bound the SSE per-read timeout totimeout_s(or caller'stimeout_mswhen provided) and catchhttpx.TimeoutExceptionfor graceful fallback.Testing
test_research_frontier_effort_with_background,test_frontier_without_background_raises_422,test_finance_research_lite_effort, frontier auto-timeout, completion-race re-poll (sync+async), asynchttpx.ReadTimeoutfallbackSee
CHANGELOG.mdfor full release notes andMIGRATION.mdfor upgrade guidance from 2.4.0.