diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 6538ca9..6d78745 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.8.0" + ".": "0.9.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 6d316e1..98e8c8a 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev%2Fcontext.dev-5afee68d7308a77a9ef51fb53917080746f96327c6d745fc029363a7d1494c3c.yml -openapi_spec_hash: b2e32bb58d92a00f6ede04c4f7bf1a34 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev%2Fcontext.dev-ca8e38b0f28a9967dab631b8868f1d59bc035fd994a717e0125c77ca592bd105.yml +openapi_spec_hash: ef0a5df01201a032dcc41f9a25b733e6 config_hash: 7d13dca2b2c6f71fc463cb6062efa5ea diff --git a/CHANGELOG.md b/CHANGELOG.md index cc6b274..543fc7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.9.0 (2026-04-23) + +Full Changelog: [v0.8.0...v0.9.0](https://github.com/context-dot-dev/context-python-sdk/compare/v0.8.0...v0.9.0) + +### Features + +* **api:** api update ([83063fc](https://github.com/context-dot-dev/context-python-sdk/commit/83063fc4358dde5756a27d9a30e4eaf48929ff58)) +* **api:** api update ([7ce5f5b](https://github.com/context-dot-dev/context-python-sdk/commit/7ce5f5b35800d3dee0d8505c56a158b457868bdb)) +* **api:** api update ([90dcf23](https://github.com/context-dot-dev/context-python-sdk/commit/90dcf237bc7ee1363ad988e68bb62003d1784d5e)) + + +### Chores + +* **internal:** more robust bootstrap script ([c0a50fe](https://github.com/context-dot-dev/context-python-sdk/commit/c0a50fe104044dd08ed93d342f6f8152bfa4c602)) + ## 0.8.0 (2026-04-19) Full Changelog: [v0.7.0...v0.8.0](https://github.com/context-dot-dev/context-python-sdk/compare/v0.7.0...v0.8.0) diff --git a/pyproject.toml b/pyproject.toml index 8a95885..370218e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "context.dev" -version = "0.8.0" +version = "0.9.0" description = "The official Python library for the context.dev API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/scripts/bootstrap b/scripts/bootstrap index 4638ec6..5a23841 100755 --- a/scripts/bootstrap +++ b/scripts/bootstrap @@ -4,7 +4,7 @@ set -e cd "$(dirname "$0")/.." -if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "$SKIP_BREW" != "1" ] && [ -t 0 ]; then +if [ -f "Brewfile" ] && [ "$(uname -s)" = "Darwin" ] && [ "${SKIP_BREW:-}" != "1" ] && [ -t 0 ]; then brew bundle check >/dev/null 2>&1 || { echo -n "==> Install Homebrew dependencies? (y/N): " read -r response diff --git a/src/context/dev/_version.py b/src/context/dev/_version.py index e505869..a5aba43 100644 --- a/src/context/dev/_version.py +++ b/src/context/dev/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "context.dev" -__version__ = "0.8.0" # x-release-please-version +__version__ = "0.9.0" # x-release-please-version diff --git a/src/context/dev/resources/web.py b/src/context/dev/resources/web.py index 2b68c4f..5fca4db 100644 --- a/src/context/dev/resources/web.py +++ b/src/context/dev/resources/web.py @@ -251,6 +251,7 @@ def web_crawl_md( follow_subdomains: bool | Omit = omit, include_images: bool | Omit = omit, include_links: bool | Omit = omit, + max_age_ms: int | Omit = omit, max_depth: int | Omit = omit, max_pages: int | Omit = omit, shorten_base64_images: bool | Omit = omit, @@ -278,6 +279,10 @@ def web_crawl_md( include_links: Preserve hyperlinks in the Markdown output + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + max_depth: Maximum link depth from the starting URL (0 = only the starting page) max_pages: Maximum number of pages to crawl. Hard cap: 500. @@ -305,6 +310,7 @@ def web_crawl_md( "follow_subdomains": follow_subdomains, "include_images": include_images, "include_links": include_links, + "max_age_ms": max_age_ms, "max_depth": max_depth, "max_pages": max_pages, "shorten_base64_images": shorten_base64_images, @@ -478,6 +484,7 @@ def web_scrape_sitemap( *, domain: str, max_links: int | Omit = omit, + url_regex: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -494,6 +501,9 @@ def web_scrape_sitemap( max_links: Maximum number of links to return from the sitemap crawl. Defaults to 10,000. Minimum is 1, maximum is 100,000. + url_regex: Optional RE2-compatible regex pattern. Only URLs matching this pattern are + returned and counted against maxLinks. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -513,6 +523,7 @@ def web_scrape_sitemap( { "domain": domain, "max_links": max_links, + "url_regex": url_regex, }, web_web_scrape_sitemap_params.WebWebScrapeSitemapParams, ), @@ -733,6 +744,7 @@ async def web_crawl_md( follow_subdomains: bool | Omit = omit, include_images: bool | Omit = omit, include_links: bool | Omit = omit, + max_age_ms: int | Omit = omit, max_depth: int | Omit = omit, max_pages: int | Omit = omit, shorten_base64_images: bool | Omit = omit, @@ -760,6 +772,10 @@ async def web_crawl_md( include_links: Preserve hyperlinks in the Markdown output + max_age_ms: Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + max_depth: Maximum link depth from the starting URL (0 = only the starting page) max_pages: Maximum number of pages to crawl. Hard cap: 500. @@ -787,6 +803,7 @@ async def web_crawl_md( "follow_subdomains": follow_subdomains, "include_images": include_images, "include_links": include_links, + "max_age_ms": max_age_ms, "max_depth": max_depth, "max_pages": max_pages, "shorten_base64_images": shorten_base64_images, @@ -960,6 +977,7 @@ async def web_scrape_sitemap( *, domain: str, max_links: int | Omit = omit, + url_regex: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -976,6 +994,9 @@ async def web_scrape_sitemap( max_links: Maximum number of links to return from the sitemap crawl. Defaults to 10,000. Minimum is 1, maximum is 100,000. + url_regex: Optional RE2-compatible regex pattern. Only URLs matching this pattern are + returned and counted against maxLinks. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -995,6 +1016,7 @@ async def web_scrape_sitemap( { "domain": domain, "max_links": max_links, + "url_regex": url_regex, }, web_web_scrape_sitemap_params.WebWebScrapeSitemapParams, ), diff --git a/src/context/dev/types/web_extract_fonts_response.py b/src/context/dev/types/web_extract_fonts_response.py index 55fec61..d8cd2a1 100644 --- a/src/context/dev/types/web_extract_fonts_response.py +++ b/src/context/dev/types/web_extract_fonts_response.py @@ -1,10 +1,13 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List +from typing import Dict, List, Optional +from typing_extensions import Literal + +from pydantic import Field as FieldInfo from .._models import BaseModel -__all__ = ["WebExtractFontsResponse", "Font"] +__all__ = ["WebExtractFontsResponse", "Font", "FontLinks"] class Font(BaseModel): @@ -30,6 +33,30 @@ class Font(BaseModel): """Array of CSS selectors or element types where this font is used""" +class FontLinks(BaseModel): + files: Dict[str, str] + """Upright font files keyed by weight string (e.g. + + "400" for regular, "500", "700"). Values are absolute URLs. + """ + + type: Literal["google", "custom"] + + category: Optional[str] = None + """Google Fonts category when type is google (e.g. + + sans-serif, serif, monospace, display, handwriting). Omitted for custom fonts + when unknown. + """ + + display_name: Optional[str] = FieldInfo(alias="displayName", default=None) + """ + Present when type is custom: human-readable name derived from the fontLinks key + (strip build/hash suffixes, split camelCase / PascalCase, normalize separators). + Google entries omit this. + """ + + class WebExtractFontsResponse(BaseModel): code: int """HTTP status code, e.g., 200""" @@ -42,3 +69,10 @@ class WebExtractFontsResponse(BaseModel): status: str """Status of the response, e.g., 'ok'""" + + font_links: Optional[Dict[str, FontLinks]] = FieldInfo(alias="fontLinks", default=None) + """ + Font assets keyed by family name as it appears in the fonts array (non-generic + names only). Clients match entries in fonts to pick a file URL from files. + Omitted when no families resolve to Google or custom @font-face URLs. + """ diff --git a/src/context/dev/types/web_web_crawl_md_params.py b/src/context/dev/types/web_web_crawl_md_params.py index cbd849e..7cf4bb9 100644 --- a/src/context/dev/types/web_web_crawl_md_params.py +++ b/src/context/dev/types/web_web_crawl_md_params.py @@ -26,6 +26,13 @@ class WebWebCrawlMdParams(TypedDict, total=False): include_links: Annotated[bool, PropertyInfo(alias="includeLinks")] """Preserve hyperlinks in the Markdown output""" + max_age_ms: Annotated[int, PropertyInfo(alias="maxAgeMs")] + """ + Return a cached result if a prior scrape for the same parameters exists and is + younger than this many milliseconds. Defaults to 1 day (86400000 ms) when + omitted. Max is 30 days (2592000000 ms). Set to 0 to always scrape fresh. + """ + max_depth: Annotated[int, PropertyInfo(alias="maxDepth")] """Maximum link depth from the starting URL (0 = only the starting page)""" diff --git a/src/context/dev/types/web_web_scrape_sitemap_params.py b/src/context/dev/types/web_web_scrape_sitemap_params.py index 4a1c766..3ebe710 100644 --- a/src/context/dev/types/web_web_scrape_sitemap_params.py +++ b/src/context/dev/types/web_web_scrape_sitemap_params.py @@ -18,3 +18,9 @@ class WebWebScrapeSitemapParams(TypedDict, total=False): Defaults to 10,000. Minimum is 1, maximum is 100,000. """ + + url_regex: Annotated[str, PropertyInfo(alias="urlRegex")] + """Optional RE2-compatible regex pattern. + + Only URLs matching this pattern are returned and counted against maxLinks. + """ diff --git a/tests/api_resources/test_web.py b/tests/api_resources/test_web.py index 6917533..6474cb1 100644 --- a/tests/api_resources/test_web.py +++ b/tests/api_resources/test_web.py @@ -158,10 +158,11 @@ def test_method_web_crawl_md_with_all_params(self, client: ContextDev) -> None: follow_subdomains=True, include_images=True, include_links=True, + max_age_ms=0, max_depth=0, max_pages=1, shorten_base64_images=True, - url_regex="urlRegex", + url_regex="^https?://[^/]+/blog/", use_main_content_only=True, ) assert_matches_type(WebWebCrawlMdResponse, web, path=["response"]) @@ -330,6 +331,7 @@ def test_method_web_scrape_sitemap_with_all_params(self, client: ContextDev) -> web = client.web.web_scrape_sitemap( domain="domain", max_links=1, + url_regex="^https?://[^/]+/blog/", ) assert_matches_type(WebWebScrapeSitemapResponse, web, path=["response"]) @@ -497,10 +499,11 @@ async def test_method_web_crawl_md_with_all_params(self, async_client: AsyncCont follow_subdomains=True, include_images=True, include_links=True, + max_age_ms=0, max_depth=0, max_pages=1, shorten_base64_images=True, - url_regex="urlRegex", + url_regex="^https?://[^/]+/blog/", use_main_content_only=True, ) assert_matches_type(WebWebCrawlMdResponse, web, path=["response"]) @@ -669,6 +672,7 @@ async def test_method_web_scrape_sitemap_with_all_params(self, async_client: Asy web = await async_client.web.web_scrape_sitemap( domain="domain", max_links=1, + url_regex="^https?://[^/]+/blog/", ) assert_matches_type(WebWebScrapeSitemapResponse, web, path=["response"])