-
Notifications
You must be signed in to change notification settings - Fork 1
Python SDK 3.1.2: lazy imports, attribution header, SSE forward-compat, answer safesearch #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,6 +61,8 @@ strings work in any case. `country="us"` and `safesearch="STRICT"` are both | |
| accepted. Elsewhere, pass the value as the API spells it (all lowercase) or | ||
| import the enum from `youdotcom.models`. | ||
|
|
||
| The snippets below assume the [Quickstart](#quickstart) client is in scope as `you`. | ||
|
|
||
| ### Answer | ||
|
|
||
| A synthesized answer with citations, grounded in live web results. | ||
|
|
@@ -69,6 +71,7 @@ A synthesized answer with citations, grounded in live web results. | |
| res = you.answer( | ||
| query="What are the tradeoffs of vector vs. keyword search?", | ||
| freshness="month", | ||
| safesearch="strict", | ||
| include_domains=["arxiv.org"], | ||
| ) | ||
|
|
||
|
|
@@ -243,14 +246,21 @@ from youdotcom.research_helpers import stream_research | |
|
|
||
| for evt in stream_research(you, task_id=task.task_id): | ||
| print(evt.event, evt.data) | ||
| if evt.event in ("response.done", "completed", "error", "failed", "cancelled"): | ||
| if evt.event in ("response.done", "complete", "completed", "error", "failed", "cancelled"): | ||
| break | ||
| ``` | ||
|
|
||
| `stream_research()` tolerates event names outside the documented set, yielding | ||
| them as raw dicts. Prefer it over `you.stream_research_task()`, which validates | ||
| strictly and will raise on an unrecognized event. Pass `from_id` to resume a | ||
| stream after a disconnect. | ||
| `stream_research()` yields `RawStreamEvent` objects, whose `.event` is the raw | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] Add In the if evt.event in ("response.done", "complete", "completed", "error", "failed", "cancelled"):
break |
||
| event name as a `str` and whose `.data` is the parsed JSON payload (or the raw | ||
| string when a frame is not valid JSON, which it tolerates). Since 3.1.2 both | ||
| methods tolerate event names outside the documented set — `you.stream_research_task()` | ||
| surfaces an unenumerated name as a plain `str` rather than raising — so the | ||
| remaining difference is which frames reach you: `stream_research()` yields | ||
| data-less frames (a bare `event: ping` heartbeat, or one carrying only | ||
| `id:`/`retry:`), whereas `you.stream_research_task()` silently drops them and | ||
| requires every frame to carry an `id` and a JSON-object `data`. Prefer | ||
| `stream_research()` when you need every frame, including keep-alives. Pass | ||
| `from_id` to resume a stream after a disconnect. | ||
|
|
||
| Each helper has an `_async` twin: `research_and_wait_async`, | ||
| `research_background_async`, `poll_research_task_async`, `stream_research_async`. | ||
|
|
@@ -356,6 +366,52 @@ is the exception: the helpers under | |
| [Long-running research](#long-running-research) manage their own deadlines, so | ||
| `timeout_s` there bounds the wait rather than `timeout_ms`. | ||
|
|
||
| ### Attribution | ||
|
|
||
| Every SDK request emits an `X-Client-Info` header so the analytics layer can | ||
| split SDK traffic from MCP traffic. The wire format is: | ||
|
|
||
| ``` | ||
| sdk[; client=<name>[/<version>]][; title=<title>][; url=<url>]; ua=python/<V> httpx/<V> | ||
| ``` | ||
|
|
||
| The leading `sdk` token names the channel, matching the `mcp` and `skill` | ||
| tokens other You.com surfaces emit. The calling language stays recoverable | ||
| from `ua=` (`python/…` here, `node/…` from the TypeScript SDK), and the SDK's | ||
| own version travels in the `User-Agent` (`youdotcom-python-sdk/<version>`). | ||
|
|
||
| Identify your application with `app_name` / `app_version`, which populate the | ||
| `client=` segment, and optionally `app_title` / `app_url`: | ||
|
|
||
| ```python | ||
| import os | ||
| from youdotcom import You | ||
|
|
||
| with You( | ||
| api_key_auth=os.getenv("YDC_API_KEY"), | ||
| app_name="acme-bot", | ||
| app_version="2.4.0", | ||
| app_title="Acme Bot", | ||
| app_url="https://acme.example", | ||
| timeout_ms=60_000, | ||
| ) as you: | ||
| res = you.search(query="...") | ||
| ``` | ||
|
|
||
| All four are optional and keyword-only; existing call sites are unaffected. | ||
| When `app_name` is | ||
| unset the `client=` segment is dropped entirely, so a request from an | ||
| undeclared caller is simply `sdk; ua=python/… httpx/…`. | ||
|
|
||
| Values must be printable ASCII excluding `;`, and `app_name` / `app_version` | ||
| additionally exclude `/` since they are joined as `<name>/<version>`. Passing | ||
| `app_version` without `app_name` is an error, since a bare version has nowhere | ||
| to go. Invalid values raise `ValueError` at construction time. | ||
|
|
||
| The MCP-specific `X-MCP-Attribution` header is never set by the SDK — it is | ||
| assembled on the MCP server, which is the only layer that can populate its | ||
| `keyless` / `payment` / `ip` flags accurately. | ||
|
|
||
| ### Servers | ||
|
|
||
| `search` and `contents` go to `https://ydc-index.io`. Everything else goes to | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] Make the Answer example runnable
The “Answer” snippet calls
you.answer(...)but doesn’t show imports or constructingYou(it assumes prior context); AGENTS.md treatsdocs/**/*.mdexample blocks as copy-paste runnable and requires showingwith You(api_key_auth=os.getenv("YDC_API_KEY"), timeout_ms=60_000) as you:for network calls. Since this PR edits the snippet, please expand it to be self-contained (or restructure to make the dependency explicit).