From 7f21a3f8bb08d705687637ac5138ebc602868ef9 Mon Sep 17 00:00:00 2001 From: Yegor Dolgopolov Date: Mon, 12 Oct 2026 17:05:02 -0700 Subject: [PATCH 1/3] Release 0.6.0: prospecting plan command, email_validated deprecation, work-in-progress limits Bump the SDK and CLI to 0.6.0 in _version.py, both pyproject.toml files, the discolike[cli] extra pin and uv.lock, and date the Unreleased changelog section. Adds one changelog entry for the API's new limits on queued email lookups and running async tasks: the transport already waits out their 429 with Retry-After: 60, so the entry only says how long a submit can block. --- CHANGELOG.md | 3 ++- packages/discolike-cli/pyproject.toml | 4 ++-- packages/discolike/pyproject.toml | 2 +- packages/discolike/src/discolike/_version.py | 2 +- packages/discolike/tests/test_package.py | 2 +- uv.lock | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1c0e9c..3579357 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog -## Unreleased +## 0.6.0 (2026-10-12) +- SDK/CLI: the API now limits how much work one account can have queued or running: email lookups (2,000 times the plan multiplier) and three DiscoGen, bulk match, contact bulk match and segment tasks. A submit over a limit is answered 429 with `Retry-After: 60`, which the SDK already waits out and retries, so with the default `max_retries=3` the call blocks for up to three minutes and then raises `RateLimitError` carrying the count and the limit in its message. Pass `max_retries=0` to get the error at once. No SDK change; older versions behave the same. - SDK: `DiscoverParams.offset` is limited to 0-10,000, matching the API, which now answers 422 above that instead of silently capping it. To go deeper, save the domains you already have as an exclusion list, pass it as `exclusion_query_id` and page again from 0. Edited in `discolike/_generated/requests.py` by hand ahead of the platform deploy; `scripts/gen_requests.py --check` reports the difference until the deployed spec carries it. - SDK: `country`, `person_country` and `filter_country` descriptions list the continent region codes the API now accepts (`EUROPE`, `ASIA`, `AFRICA`, `NORTH_AMERICA`, `SOUTH_AMERICA`, `OCEANIA`, `ANTARCTICA`). `EU` stays the 27 member states. The fields are plain strings, so older SDK versions can send these too. Edited in `discolike/_generated/requests.py` by hand ahead of the platform deploy; `scripts/gen_requests.py --check` reports the difference until the deployed spec carries it. - SDK: the `email_validated` contact filter on `contacts.search`, `contacts.count` and `contacts.discover` is deprecated. Treated as has_email: contact search no longer filters on email verification; verify emails instead. The flag behind it only recorded that a third-party verifier had run at some point, not what it found, so a large share of "validated" addresses were catch-all. It is dropped from `ContactsSearchParams`, `ContactsCountParams` and `ContactFilters`; passing it still works (it goes out as an extra field and the API applies it as `has_email`) but raises a `DeprecationWarning`. Contact results keep their `email_validated` field, which is now `None` until you run email verification on the contact, then `True` or `False`. diff --git a/packages/discolike-cli/pyproject.toml b/packages/discolike-cli/pyproject.toml index 9d06da3..5ec2b3e 100644 --- a/packages/discolike-cli/pyproject.toml +++ b/packages/discolike-cli/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "discolike-cli" -version = "0.5.0" +version = "0.6.0" description = "Official CLI for the DiscoLike API" readme = "README.md" license = "MIT" @@ -12,7 +12,7 @@ license-files = ["LICENSE"] requires-python = ">=3.11" authors = [{ name = "DiscoLike", email = "support@discolike.com" }] dependencies = [ - "discolike==0.5.0", + "discolike==0.6.0", "typer>=0.26.1,<0.28", "rich>=13.0", ] diff --git a/packages/discolike/pyproject.toml b/packages/discolike/pyproject.toml index ec3d9d3..9ad1bcd 100644 --- a/packages/discolike/pyproject.toml +++ b/packages/discolike/pyproject.toml @@ -33,7 +33,7 @@ classifiers = [ ] [project.optional-dependencies] -cli = ["discolike-cli==0.5.0"] +cli = ["discolike-cli==0.6.0"] [project.urls] Homepage = "https://www.discolike.com" diff --git a/packages/discolike/src/discolike/_version.py b/packages/discolike/src/discolike/_version.py index 3d18726..906d362 100644 --- a/packages/discolike/src/discolike/_version.py +++ b/packages/discolike/src/discolike/_version.py @@ -1 +1 @@ -__version__ = "0.5.0" +__version__ = "0.6.0" diff --git a/packages/discolike/tests/test_package.py b/packages/discolike/tests/test_package.py index b9f92c5..a6bf703 100644 --- a/packages/discolike/tests/test_package.py +++ b/packages/discolike/tests/test_package.py @@ -2,4 +2,4 @@ def test_version() -> None: - assert discolike.__version__ == "0.5.0" + assert discolike.__version__ == "0.6.0" diff --git a/uv.lock b/uv.lock index 486c218..429b470 100644 --- a/uv.lock +++ b/uv.lock @@ -343,7 +343,7 @@ dev = [ [[package]] name = "discolike-cli" -version = "0.5.0" +version = "0.6.0" source = { editable = "packages/discolike-cli" } dependencies = [ { name = "discolike" }, From 6c049b6be4008e91b68e3b7e3f599d81f450bfc6 Mon Sep 17 00:00:00 2001 From: Yegor Dolgopolov Date: Mon, 12 Oct 2026 17:07:27 -0700 Subject: [PATCH 2/3] Regenerate request models from the deployed production spec The platform release is live, so the offset cap, continent codes and the email_validated deprecation no longer need hand edits. gen_requests.py --check is clean; the changelog drops the notes that said it would not be. --- CHANGELOG.md | 6 +++--- .../src/discolike/_generated/requests.py | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3579357..e4b2144 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,11 @@ ## 0.6.0 (2026-10-12) - SDK/CLI: the API now limits how much work one account can have queued or running: email lookups (2,000 times the plan multiplier) and three DiscoGen, bulk match, contact bulk match and segment tasks. A submit over a limit is answered 429 with `Retry-After: 60`, which the SDK already waits out and retries, so with the default `max_retries=3` the call blocks for up to three minutes and then raises `RateLimitError` carrying the count and the limit in its message. Pass `max_retries=0` to get the error at once. No SDK change; older versions behave the same. -- SDK: `DiscoverParams.offset` is limited to 0-10,000, matching the API, which now answers 422 above that instead of silently capping it. To go deeper, save the domains you already have as an exclusion list, pass it as `exclusion_query_id` and page again from 0. Edited in `discolike/_generated/requests.py` by hand ahead of the platform deploy; `scripts/gen_requests.py --check` reports the difference until the deployed spec carries it. -- SDK: `country`, `person_country` and `filter_country` descriptions list the continent region codes the API now accepts (`EUROPE`, `ASIA`, `AFRICA`, `NORTH_AMERICA`, `SOUTH_AMERICA`, `OCEANIA`, `ANTARCTICA`). `EU` stays the 27 member states. The fields are plain strings, so older SDK versions can send these too. Edited in `discolike/_generated/requests.py` by hand ahead of the platform deploy; `scripts/gen_requests.py --check` reports the difference until the deployed spec carries it. +- SDK: `DiscoverParams.offset` is limited to 0-10,000, matching the API, which now answers 422 above that instead of silently capping it. To go deeper, save the domains you already have as an exclusion list, pass it as `exclusion_query_id` and page again from 0. +- SDK: `country`, `person_country` and `filter_country` descriptions list the continent region codes the API now accepts (`EUROPE`, `ASIA`, `AFRICA`, `NORTH_AMERICA`, `SOUTH_AMERICA`, `OCEANIA`, `ANTARCTICA`). `EU` stays the 27 member states. The fields are plain strings, so older SDK versions can send these too. - SDK: the `email_validated` contact filter on `contacts.search`, `contacts.count` and `contacts.discover` is deprecated. Treated as has_email: contact search no longer filters on email verification; verify emails instead. The flag behind it only recorded that a third-party verifier had run at some point, not what it found, so a large share of "validated" addresses were catch-all. It is dropped from `ContactsSearchParams`, `ContactsCountParams` and `ContactFilters`; passing it still works (it goes out as an extra field and the API applies it as `has_email`) but raises a `DeprecationWarning`. Contact results keep their `email_validated` field, which is now `None` until you run email verification on the contact, then `True` or `False`. - CLI: `contacts search`, `count` and `discover` keep `--email-validated/--no-email-validated` so existing scripts keep running. `--email-validated` is deprecated and treated as `--has-email` (an explicit `--has-email` or `--no-has-email` takes precedence) and prints a deprecation warning on stderr; `--no-email-validated` warns and has no effect. Neither sends `email_validated`. `bulk contacts` keeps its `email_validated` CSV column, empty unless the contact was verified. -- SDK (note for maintainers): `email_validated` was removed from `discolike/_generated/requests.py` by hand, ahead of the platform deploy that marks it deprecated in the OpenAPI spec (the generator drops deprecated fields). Until the deployed spec carries that flag, `scripts/gen_requests.py --check` reports the three fields as a diff and `scripts/check_contract.py` reports them as undeclared params; that is the pending release, not drift. +- SDK (note for maintainers): `discolike/_generated/requests.py` is regenerated from the production spec, which now marks `email_validated` deprecated and carries the offset cap and continent codes, so `scripts/gen_requests.py --check` is clean again. - SDK (note for maintainers): `scripts/check_contract.py` now skips a query parameter marked deprecated inside its `schema`, which is where FastAPI puts a deprecated model field. `scripts/gen_requests.py` already dropped those, so the two scripts disagreed on GET routes. - CLI: `prospecting plan RUN_ID --plan-version N` changes a proposed plan before approval, wrapping `update_plan()`: `--contact-integration-id`, `--validation-integration-id`, `--search-provider-id` (`none` skips web research), `--target-companies`, `--contacts-per-company`, `--deliverable`, `--goal`, `--max-spend-usd` and `--max-provider-spend-usd` (`0` removes a limit), sending only the flags passed. When an organization has several AI or search providers and none is the default, the plan leaves that engine at `selected: null` and `approve` returns 409 until one is picked; `plan` is how a CLI user picks it. The run comes back at a new `plan_version`, which is the one to approve. diff --git a/packages/discolike/src/discolike/_generated/requests.py b/packages/discolike/src/discolike/_generated/requests.py index 1f08057..11a159d 100644 --- a/packages/discolike/src/discolike/_generated/requests.py +++ b/packages/discolike/src/discolike/_generated/requests.py @@ -1380,7 +1380,7 @@ class ContactGenerateRequest(DiscolikeRequest): integration_id: Annotated[ str | None, Field( - description="LLM provider integration UUID, or 'native' for keyless extraction without title validation. Omit for the org default (falls back to native when none is set).", + description="LLM provider integration UUID, or 'native' for keyless extraction without title validation. Omit for native when it is available and a search provider resolves (the org default, or its only one), else the org default LLM.", title="Integration Id", ), ] = None @@ -1408,7 +1408,7 @@ class DiscoGenProcessRequest(DiscolikeRequest): integration_id: Annotated[ str | None, Field( - description="LLM provider integration UUID (omit for org default), or 'native-icp' to score an ICP validation prompt with the native model", + description="LLM provider integration UUID (omit for the org default, or its only integration), or 'native-icp' to score an ICP validation prompt with the native model", title="Integration Id", ), ] = None @@ -1425,7 +1425,7 @@ class DiscoGenProcessRequest(DiscolikeRequest): search_provider_id: Annotated[ str | None, Field( - description="Search provider integration UUID (omit for org default)", + description="Search provider integration UUID (omit for the org default, or its only provider)", title="Search Provider Id", ), ] = None @@ -1451,7 +1451,7 @@ class DiscoGenPersonaProcessRequest(DiscolikeRequest): integration_id: Annotated[ str | None, Field( - description="LLM provider integration UUID (omit for org default), or 'native-icp' to score an ICP validation prompt with the native model", + description="LLM provider integration UUID (omit for the org default, or its only integration), or 'native-icp' to score an ICP validation prompt with the native model", title="Integration Id", ), ] = None @@ -1468,7 +1468,7 @@ class DiscoGenPersonaProcessRequest(DiscolikeRequest): search_provider_id: Annotated[ str | None, Field( - description="Search provider integration UUID (omit for org default)", + description="Search provider integration UUID (omit for the org default, or its only provider)", title="Search Provider Id", ), ] = None @@ -1793,7 +1793,7 @@ class DiscoverParams(DiscolikeRequest): country: Annotated[ list[str] | None, Field( - description="Filter by ISO-3166-1 alpha-2 country codes (e.g., US, GB, DE). Also accepts region aliases: EU, LATAM, MENA, APAC, NORDICS, DACH, BENELUX, GCC, ASEAN, CEE, ANZ, EUROPE, ASIA, AFRICA, NORTH_AMERICA, SOUTH_AMERICA, OCEANIA, ANTARCTICA.", + description="ISO-3166-1 alpha-2 country codes (e.g., US, GB, DE) or region aliases: EU, LATAM, MENA, APAC, NORDICS, DACH, BENELUX, GCC, ASEAN, CEE, ANZ, EUROPE, ASIA, AFRICA, NORTH_AMERICA, SOUTH_AMERICA, OCEANIA, ANTARCTICA.", title="Country", ), ] = None @@ -2121,7 +2121,12 @@ class DiscoverParams(DiscolikeRequest): ] = "UNRESTRICTED" offset: Annotated[ int | None, - Field(description="Records to skip for pagination.", ge=0, le=10000, title="Offset"), + Field( + description="Records to skip for pagination.", + ge=0, + le=10000, + title="Offset", + ), ] = 0 exclusion_query_id: Annotated[ list[str] | None, @@ -2430,7 +2435,7 @@ class CountParams(DiscolikeRequest): country: Annotated[ list[str] | None, Field( - description="Filter by ISO-3166-1 alpha-2 country codes (e.g., US, GB, DE). Also accepts region aliases: EU, LATAM, MENA, APAC, NORDICS, DACH, BENELUX, GCC, ASEAN, CEE, ANZ, EUROPE, ASIA, AFRICA, NORTH_AMERICA, SOUTH_AMERICA, OCEANIA, ANTARCTICA.", + description="ISO-3166-1 alpha-2 country codes (e.g., US, GB, DE) or region aliases: EU, LATAM, MENA, APAC, NORDICS, DACH, BENELUX, GCC, ASEAN, CEE, ANZ, EUROPE, ASIA, AFRICA, NORTH_AMERICA, SOUTH_AMERICA, OCEANIA, ANTARCTICA.", title="Country", ), ] = None From 30ba009153a5c030bef9491dfe41d27a74ecafcd Mon Sep 17 00:00:00 2001 From: Yegor Dolgopolov Date: Mon, 12 Oct 2026 17:19:59 -0700 Subject: [PATCH 3/3] Say the max_retries advice is SDK-only in the 0.6.0 changelog The CLI builds its client with no retry option, so a CLI command over a work-in-progress limit waits out the retries and exits 4. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b2144..c63d9fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 0.6.0 (2026-10-12) -- SDK/CLI: the API now limits how much work one account can have queued or running: email lookups (2,000 times the plan multiplier) and three DiscoGen, bulk match, contact bulk match and segment tasks. A submit over a limit is answered 429 with `Retry-After: 60`, which the SDK already waits out and retries, so with the default `max_retries=3` the call blocks for up to three minutes and then raises `RateLimitError` carrying the count and the limit in its message. Pass `max_retries=0` to get the error at once. No SDK change; older versions behave the same. +- SDK/CLI: the API now limits how much work one account can have queued or running: email lookups (2,000 times the plan multiplier) and three DiscoGen, bulk match, contact bulk match and segment tasks. A submit over a limit is answered 429 with `Retry-After: 60`, which the SDK already waits out and retries, so with the default `max_retries=3` the call blocks for up to three minutes and then raises `RateLimitError` carrying the count and the limit in its message. In the SDK, `Discolike(max_retries=0)` gets the error at once; the CLI has no retry option, so its commands wait and then exit 4. No SDK change; older versions behave the same. - SDK: `DiscoverParams.offset` is limited to 0-10,000, matching the API, which now answers 422 above that instead of silently capping it. To go deeper, save the domains you already have as an exclusion list, pass it as `exclusion_query_id` and page again from 0. - SDK: `country`, `person_country` and `filter_country` descriptions list the continent region codes the API now accepts (`EUROPE`, `ASIA`, `AFRICA`, `NORTH_AMERICA`, `SOUTH_AMERICA`, `OCEANIA`, `ANTARCTICA`). `EU` stays the 27 member states. The fields are plain strings, so older SDK versions can send these too. - SDK: the `email_validated` contact filter on `contacts.search`, `contacts.count` and `contacts.discover` is deprecated. Treated as has_email: contact search no longer filters on email verification; verify emails instead. The flag behind it only recorded that a third-party verifier had run at some point, not what it found, so a large share of "validated" addresses were catch-all. It is dropped from `ContactsSearchParams`, `ContactsCountParams` and `ContactFilters`; passing it still works (it goes out as an extra field and the API applies it as `has_email`) but raises a `DeprecationWarning`. Contact results keep their `email_validated` field, which is now `None` until you run email verification on the contact, then `True` or `False`.