From a2b4daa3caed18e5159da0747f1f3a5ccaa0b645 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 18 Jul 2026 02:11:32 +0000 Subject: [PATCH 1/4] feat(stlc): configurable CI runner and private-production-repo support in workflow templates --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a363ef..56a96ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ github.repository == 'stainless-sdks/parallel-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -44,7 +44,7 @@ jobs: permissions: contents: read id-token: write - runs-on: ${{ github.repository == 'stainless-sdks/parallel-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -84,7 +84,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ github.repository == 'stainless-sdks/parallel-sdk-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From 15f1f47985c735a57e7985a01f1eb5abbd07f1d9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:30:35 +0000 Subject: [PATCH 2/4] feat(api): add memory support --- .github/workflows/ci.yml | 10 +- .stats.yml | 8 +- scripts/utils/upload-artifact.sh | 2 +- src/parallel/_client.py | 26 +- src/parallel/resources/beta/__init__.py | 14 + src/parallel/resources/beta/api.md | 23 + src/parallel/resources/beta/beta.py | 50 ++ src/parallel/resources/beta/findall.py | 16 +- src/parallel/resources/beta/memory.py | 437 ++++++++++++++++++ src/parallel/resources/monitor.py | 10 + src/parallel/resources/task_run.py | 10 + src/parallel/types/beta/__init__.py | 8 + .../types/beta/findall_create_params.py | 11 +- .../types/beta/findall_memory_result.py | 25 + .../types/beta/memory_clear_params.py | 16 + .../types/beta/memory_evict_params.py | 22 + .../types/beta/memory_retrieve_params.py | 37 ++ .../types/beta/memory_retrieve_response.py | 20 + .../types/beta/monitor_memory_event.py | 21 + .../types/beta/monitor_memory_result.py | 32 ++ src/parallel/types/beta/task_memory_result.py | 25 + src/parallel/types/client_search_params.py | 15 +- src/parallel/types/monitor_create_params.py | 6 + src/parallel/types/run_input.py | 6 + src/parallel/types/run_input_param.py | 6 + src/parallel/types/task_run_create_params.py | 6 + tests/api_resources/beta/test_findall.py | 2 + tests/api_resources/beta/test_memory.py | 247 ++++++++++ tests/api_resources/test_monitor.py | 2 + tests/api_resources/test_task_group.py | 2 + tests/api_resources/test_task_run.py | 2 + 31 files changed, 1085 insertions(+), 32 deletions(-) create mode 100644 src/parallel/resources/beta/memory.py create mode 100644 src/parallel/types/beta/findall_memory_result.py create mode 100644 src/parallel/types/beta/memory_clear_params.py create mode 100644 src/parallel/types/beta/memory_evict_params.py create mode 100644 src/parallel/types/beta/memory_retrieve_params.py create mode 100644 src/parallel/types/beta/memory_retrieve_response.py create mode 100644 src/parallel/types/beta/monitor_memory_event.py create mode 100644 src/parallel/types/beta/monitor_memory_result.py create mode 100644 src/parallel/types/beta/task_memory_result.py create mode 100644 tests/api_resources/beta/test_memory.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56a96ba..1a9d102 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: lint: timeout-minutes: 10 name: lint - runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: 'ubuntu-latest' if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -44,7 +44,7 @@ jobs: permissions: contents: read id-token: write - runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: 'ubuntu-latest' steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -64,7 +64,7 @@ jobs: - name: Get GitHub OIDC Token if: |- - github.repository == 'stainless-sdks/parallel-sdk-python' && + github.repository == 'parallel-web/parallel-sdk-python-staging' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 @@ -73,7 +73,7 @@ jobs: - name: Upload tarball if: |- - github.repository == 'stainless-sdks/parallel-sdk-python' && + github.repository == 'parallel-web/parallel-sdk-python-staging' && !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s @@ -84,7 +84,7 @@ jobs: test: timeout-minutes: 10 name: test - runs-on: ${{ startsWith(github.repository, 'stainless-sdks/') && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + runs-on: 'ubuntu-latest' if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/.stats.yml b/.stats.yml index 4b2af5b..20142f4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 30 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-3001a018c926803bb713f19d99c3d5d39ed44ce3fe670bebefc326fd252b8821.yml -openapi_spec_hash: 0883a98aa5b566818f5910d01c831c4a -config_hash: 8572a2d7a5ede9ade3be8ad4d8aafd7d +configured_endpoints: 33 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-dcb1605f4878ba899f427518b5f86d2bb79fc37820caa27392695fe8b7f5295c.yml +openapi_spec_hash: 6c7d3db50b53be72d8b35c260f771004 +config_hash: d4f69197dba970d05757624fe3f7b373 diff --git a/scripts/utils/upload-artifact.sh b/scripts/utils/upload-artifact.sh index f3f256b..72ae6c1 100755 --- a/scripts/utils/upload-artifact.sh +++ b/scripts/utils/upload-artifact.sh @@ -20,7 +20,7 @@ UPLOAD_RESPONSE=$(curl -v -X PUT \ if echo "$UPLOAD_RESPONSE" | grep -q "HTTP/[0-9.]* 200"; then echo -e "\033[32mUploaded build to Stainless storage.\033[0m" - echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/parallel-sdk-python/$SHA/$FILENAME'\033[0m" + echo -e "\033[32mInstallation: pip install 'https://pkg.stainless.com/s/parallel-sdk-python-staging/$SHA/$FILENAME'\033[0m" else echo -e "\033[31mFailed to upload artifact.\033[0m" exit 1 diff --git a/src/parallel/_client.py b/src/parallel/_client.py index 8ecaaaf..e35da7e 100644 --- a/src/parallel/_client.py +++ b/src/parallel/_client.py @@ -355,7 +355,7 @@ def search( advanced_settings: Optional[AdvancedSearchSettingsParam] | Omit = omit, client_model: Optional[str] | Omit = omit, max_chars_total: Optional[int] | Omit = omit, - mode: Optional[Literal["turbo", "basic", "advanced"]] | Omit = omit, + mode: Optional[Literal["turbo", "basic", "advanced", "fast"]] | Omit = omit, objective: Optional[str] | Omit = omit, session_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -388,11 +388,12 @@ def search( max_chars_total: Upper bound on total characters across excerpts from all results. - mode: Search mode preset: supported values are `turbo`, `basic`, and `advanced`. Turbo - mode is optimized for the fastest responses. Basic mode offers low latency and - works best with 2-3 high-quality search_queries. Advanced mode provides higher - quality with more advanced retrieval and compression. Defaults to `advanced` - when omitted. + mode: Search mode preset: supported values are `turbo`, `fast`, `basic`, and + `advanced`. Turbo mode is optimized for the fastest responses. Fast mode trades + some quality for low latency, and works best with concise, high-quality + objective and search_queries. Basic mode offers low latency and works best with + 2-3 high-quality search_queries. Advanced mode provides higher quality with more + advanced retrieval and compression. Defaults to `advanced` when omitted. objective: Natural-language description of the underlying question or goal driving the search. Used together with search_queries to focus results on the most relevant @@ -748,7 +749,7 @@ async def search( advanced_settings: Optional[AdvancedSearchSettingsParam] | Omit = omit, client_model: Optional[str] | Omit = omit, max_chars_total: Optional[int] | Omit = omit, - mode: Optional[Literal["turbo", "basic", "advanced"]] | Omit = omit, + mode: Optional[Literal["turbo", "basic", "advanced", "fast"]] | Omit = omit, objective: Optional[str] | Omit = omit, session_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -781,11 +782,12 @@ async def search( max_chars_total: Upper bound on total characters across excerpts from all results. - mode: Search mode preset: supported values are `turbo`, `basic`, and `advanced`. Turbo - mode is optimized for the fastest responses. Basic mode offers low latency and - works best with 2-3 high-quality search_queries. Advanced mode provides higher - quality with more advanced retrieval and compression. Defaults to `advanced` - when omitted. + mode: Search mode preset: supported values are `turbo`, `fast`, `basic`, and + `advanced`. Turbo mode is optimized for the fastest responses. Fast mode trades + some quality for low latency, and works best with concise, high-quality + objective and search_queries. Basic mode offers low latency and works best with + 2-3 high-quality search_queries. Advanced mode provides higher quality with more + advanced retrieval and compression. Defaults to `advanced` when omitted. objective: Natural-language description of the underlying question or goal driving the search. Used together with search_queries to focus results on the most relevant diff --git a/src/parallel/resources/beta/__init__.py b/src/parallel/resources/beta/__init__.py index 284e308..d821691 100644 --- a/src/parallel/resources/beta/__init__.py +++ b/src/parallel/resources/beta/__init__.py @@ -8,6 +8,14 @@ BetaResourceWithStreamingResponse, AsyncBetaResourceWithStreamingResponse, ) +from .memory import ( + MemoryResource, + AsyncMemoryResource, + MemoryResourceWithRawResponse, + AsyncMemoryResourceWithRawResponse, + MemoryResourceWithStreamingResponse, + AsyncMemoryResourceWithStreamingResponse, +) from .findall import ( FindAllResource, AsyncFindAllResource, @@ -24,6 +32,12 @@ "AsyncFindAllResourceWithRawResponse", "FindAllResourceWithStreamingResponse", "AsyncFindAllResourceWithStreamingResponse", + "MemoryResource", + "AsyncMemoryResource", + "MemoryResourceWithRawResponse", + "AsyncMemoryResourceWithRawResponse", + "MemoryResourceWithStreamingResponse", + "AsyncMemoryResourceWithStreamingResponse", "BetaResource", "AsyncBetaResource", "BetaResourceWithRawResponse", diff --git a/src/parallel/resources/beta/api.md b/src/parallel/resources/beta/api.md index d7a4588..1488340 100644 --- a/src/parallel/resources/beta/api.md +++ b/src/parallel/resources/beta/api.md @@ -39,3 +39,26 @@ Methods: - client.beta.findall.ingest(\*\*params) -> FindAllSchema - client.beta.findall.result(findall_id) -> FindAllRunResult - client.beta.findall.schema(findall_id) -> FindAllSchema + +## Memory + +Types: + +```python +from parallel.types.beta import ( + FindAllMemoryResult, + MemoryClearRequest, + MemoryEvictRequest, + MemoryRetrieveRequest, + MemoryRetrieveResponse, + MonitorMemoryEvent, + MonitorMemoryResult, + TaskMemoryResult, +) +``` + +Methods: + +- client.beta.memory.retrieve(\*\*params) -> MemoryRetrieveResponse +- client.beta.memory.clear(\*\*params) -> None +- client.beta.memory.evict(\*\*params) -> None diff --git a/src/parallel/resources/beta/beta.py b/src/parallel/resources/beta/beta.py index dd3de47..cd24b9f 100644 --- a/src/parallel/resources/beta/beta.py +++ b/src/parallel/resources/beta/beta.py @@ -2,6 +2,14 @@ from __future__ import annotations +from .memory import ( + MemoryResource, + AsyncMemoryResource, + MemoryResourceWithRawResponse, + AsyncMemoryResourceWithRawResponse, + MemoryResourceWithStreamingResponse, + AsyncMemoryResourceWithStreamingResponse, +) from .findall import ( FindAllResource, AsyncFindAllResource, @@ -24,6 +32,13 @@ def findall(self) -> FindAllResource: """ return FindAllResource(self._client) + @cached_property + def memory(self) -> MemoryResource: + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + return MemoryResource(self._client) + @cached_property def with_raw_response(self) -> BetaResourceWithRawResponse: """ @@ -52,6 +67,13 @@ def findall(self) -> AsyncFindAllResource: """ return AsyncFindAllResource(self._client) + @cached_property + def memory(self) -> AsyncMemoryResource: + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + return AsyncMemoryResource(self._client) + @cached_property def with_raw_response(self) -> AsyncBetaResourceWithRawResponse: """ @@ -83,6 +105,13 @@ def findall(self) -> FindAllResourceWithRawResponse: """ return FindAllResourceWithRawResponse(self._beta.findall) + @cached_property + def memory(self) -> MemoryResourceWithRawResponse: + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + return MemoryResourceWithRawResponse(self._beta.memory) + class AsyncBetaResourceWithRawResponse: def __init__(self, beta: AsyncBetaResource) -> None: @@ -95,6 +124,13 @@ def findall(self) -> AsyncFindAllResourceWithRawResponse: """ return AsyncFindAllResourceWithRawResponse(self._beta.findall) + @cached_property + def memory(self) -> AsyncMemoryResourceWithRawResponse: + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + return AsyncMemoryResourceWithRawResponse(self._beta.memory) + class BetaResourceWithStreamingResponse: def __init__(self, beta: BetaResource) -> None: @@ -107,6 +143,13 @@ def findall(self) -> FindAllResourceWithStreamingResponse: """ return FindAllResourceWithStreamingResponse(self._beta.findall) + @cached_property + def memory(self) -> MemoryResourceWithStreamingResponse: + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + return MemoryResourceWithStreamingResponse(self._beta.memory) + class AsyncBetaResourceWithStreamingResponse: def __init__(self, beta: AsyncBetaResource) -> None: @@ -118,3 +161,10 @@ def findall(self) -> AsyncFindAllResourceWithStreamingResponse: The FindAll API discovers and evaluates entities that match complex criteria from natural language objectives. Submit a high-level goal and the service automatically generates structured match conditions, discovers relevant candidates, and evaluates each against the criteria. Returns comprehensive results with detailed reasoning, citations, and confidence scores for each match decision. Streaming events and webhooks are supported. """ return AsyncFindAllResourceWithStreamingResponse(self._beta.findall) + + @cached_property + def memory(self) -> AsyncMemoryResourceWithStreamingResponse: + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + return AsyncMemoryResourceWithStreamingResponse(self._beta.memory) diff --git a/src/parallel/resources/beta/findall.py b/src/parallel/resources/beta/findall.py index cc4bccb..63dd30c 100644 --- a/src/parallel/resources/beta/findall.py +++ b/src/parallel/resources/beta/findall.py @@ -75,6 +75,7 @@ def create( match_limit: int, objective: str, exclude_list: Optional[Iterable[findall_create_params.ExcludeList]] | Omit = omit, + memory_scope_key: Optional[str] | Omit = omit, metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, webhook: Optional[WebhookParam] | Omit = omit, betas: List[ParallelBetaParam] | Omit = omit, @@ -111,7 +112,11 @@ def create( objective: Natural language objective of the FindAll run. - exclude_list: List of entity names/IDs to exclude from results. + exclude_list: List of entity names/IDs to exclude from results. At most 10,000 entries are + allowed. + + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. metadata: Metadata for the FindAll run. @@ -148,6 +153,7 @@ def create( "match_limit": match_limit, "objective": objective, "exclude_list": exclude_list, + "memory_scope_key": memory_scope_key, "metadata": metadata, "webhook": webhook, }, @@ -675,6 +681,7 @@ async def create( match_limit: int, objective: str, exclude_list: Optional[Iterable[findall_create_params.ExcludeList]] | Omit = omit, + memory_scope_key: Optional[str] | Omit = omit, metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, webhook: Optional[WebhookParam] | Omit = omit, betas: List[ParallelBetaParam] | Omit = omit, @@ -711,7 +718,11 @@ async def create( objective: Natural language objective of the FindAll run. - exclude_list: List of entity names/IDs to exclude from results. + exclude_list: List of entity names/IDs to exclude from results. At most 10,000 entries are + allowed. + + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. metadata: Metadata for the FindAll run. @@ -748,6 +759,7 @@ async def create( "match_limit": match_limit, "objective": objective, "exclude_list": exclude_list, + "memory_scope_key": memory_scope_key, "metadata": metadata, "webhook": webhook, }, diff --git a/src/parallel/resources/beta/memory.py b/src/parallel/resources/beta/memory.py new file mode 100644 index 0000000..6f3cc74 --- /dev/null +++ b/src/parallel/resources/beta/memory.py @@ -0,0 +1,437 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given +from ..._utils import maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...types.beta import memory_clear_params, memory_evict_params, memory_retrieve_params +from ..._base_client import make_request_options +from ...types.beta.memory_retrieve_response import MemoryRetrieveResponse + +__all__ = ["MemoryResource", "AsyncMemoryResource"] + + +class MemoryResource(SyncAPIResource): + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + + @cached_property + def with_raw_response(self) -> MemoryResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/parallel-web/parallel-sdk-python#accessing-raw-response-data-eg-headers + """ + return MemoryResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> MemoryResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/parallel-web/parallel-sdk-python#with_streaming_response + """ + return MemoryResourceWithStreamingResponse(self) + + def retrieve( + self, + *, + kind: Optional[Literal["task", "monitor", "findall"]] | Omit = omit, + limit: int | Omit = omit, + memory_scope_key: Optional[str] | Omit = omit, + query: Optional[str] | Omit = omit, + since: Union[str, datetime, None] | 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> MemoryRetrieveResponse: + """Retrieves relevant or recent runs from the selected memory. + + Provide a query to + rank results by relevance; leave it empty to return the most recent runs. + + Args: + kind: Filter memories by kind: `task`, `monitor`, or `findall`. + + limit: Maximum number of memories to return. + + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + + query: Concise query describing the memories to retrieve. Empty queries return the most + recent memories. + + since: Only return memories sourced from task, monitor, or FindAll runs completed at or + after this RFC 3339 timestamp. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"parallel-beta": "search-extract-2025-10-10", **(extra_headers or {})} + return self._post( + "/v1beta/memory/retrieve", + body=maybe_transform( + { + "kind": kind, + "limit": limit, + "memory_scope_key": memory_scope_key, + "query": query, + "since": since, + }, + memory_retrieve_params.MemoryRetrieveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MemoryRetrieveResponse, + ) + + def clear( + self, + *, + memory_scope_key: Optional[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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Clears all entries from the selected memory without deleting the underlying + tasks, monitors, or FindAll runs. + + Args: + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + extra_headers.update({"parallel-beta": "search-extract-2025-10-10"}) + return self._post( + "/v1beta/memory/clear", + body=maybe_transform({"memory_scope_key": memory_scope_key}, memory_clear_params.MemoryClearParams), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + def evict( + self, + *, + id: str, + kind: Literal["task", "monitor", "findall"], + memory_scope_key: Optional[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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Removes a task run, monitor, or FindAll run from the selected memory without + deleting the original resource. + + Args: + id: ID of the task run, monitor, or FindAll run to evict. + + kind: Kind of source to evict: `task`, `monitor`, or `findall`. + + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + extra_headers.update({"parallel-beta": "search-extract-2025-10-10"}) + return self._post( + "/v1beta/memory/evict", + body=maybe_transform( + { + "id": id, + "kind": kind, + "memory_scope_key": memory_scope_key, + }, + memory_evict_params.MemoryEvictParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class AsyncMemoryResource(AsyncAPIResource): + """ + The Memory API retrieves and manages memories created by Tasks, Monitors, and FindAll runs. Memories can be personal or isolated with a `memory_scope_key`. + """ + + @cached_property + def with_raw_response(self) -> AsyncMemoryResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/parallel-web/parallel-sdk-python#accessing-raw-response-data-eg-headers + """ + return AsyncMemoryResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncMemoryResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/parallel-web/parallel-sdk-python#with_streaming_response + """ + return AsyncMemoryResourceWithStreamingResponse(self) + + async def retrieve( + self, + *, + kind: Optional[Literal["task", "monitor", "findall"]] | Omit = omit, + limit: int | Omit = omit, + memory_scope_key: Optional[str] | Omit = omit, + query: Optional[str] | Omit = omit, + since: Union[str, datetime, None] | 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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> MemoryRetrieveResponse: + """Retrieves relevant or recent runs from the selected memory. + + Provide a query to + rank results by relevance; leave it empty to return the most recent runs. + + Args: + kind: Filter memories by kind: `task`, `monitor`, or `findall`. + + limit: Maximum number of memories to return. + + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + + query: Concise query describing the memories to retrieve. Empty queries return the most + recent memories. + + since: Only return memories sourced from task, monitor, or FindAll runs completed at or + after this RFC 3339 timestamp. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"parallel-beta": "search-extract-2025-10-10", **(extra_headers or {})} + return await self._post( + "/v1beta/memory/retrieve", + body=await async_maybe_transform( + { + "kind": kind, + "limit": limit, + "memory_scope_key": memory_scope_key, + "query": query, + "since": since, + }, + memory_retrieve_params.MemoryRetrieveParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=MemoryRetrieveResponse, + ) + + async def clear( + self, + *, + memory_scope_key: Optional[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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Clears all entries from the selected memory without deleting the underlying + tasks, monitors, or FindAll runs. + + Args: + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + extra_headers.update({"parallel-beta": "search-extract-2025-10-10"}) + return await self._post( + "/v1beta/memory/clear", + body=await async_maybe_transform( + {"memory_scope_key": memory_scope_key}, memory_clear_params.MemoryClearParams + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + async def evict( + self, + *, + id: str, + kind: Literal["task", "monitor", "findall"], + memory_scope_key: Optional[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, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> None: + """ + Removes a task run, monitor, or FindAll run from the selected memory without + deleting the original resource. + + Args: + id: ID of the task run, monitor, or FindAll run to evict. + + kind: Kind of source to evict: `task`, `monitor`, or `findall`. + + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {"Accept": "*/*", **(extra_headers or {})} + extra_headers.update({"parallel-beta": "search-extract-2025-10-10"}) + return await self._post( + "/v1beta/memory/evict", + body=await async_maybe_transform( + { + "id": id, + "kind": kind, + "memory_scope_key": memory_scope_key, + }, + memory_evict_params.MemoryEvictParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=NoneType, + ) + + +class MemoryResourceWithRawResponse: + def __init__(self, memory: MemoryResource) -> None: + self._memory = memory + + self.retrieve = to_raw_response_wrapper( + memory.retrieve, + ) + self.clear = to_raw_response_wrapper( + memory.clear, + ) + self.evict = to_raw_response_wrapper( + memory.evict, + ) + + +class AsyncMemoryResourceWithRawResponse: + def __init__(self, memory: AsyncMemoryResource) -> None: + self._memory = memory + + self.retrieve = async_to_raw_response_wrapper( + memory.retrieve, + ) + self.clear = async_to_raw_response_wrapper( + memory.clear, + ) + self.evict = async_to_raw_response_wrapper( + memory.evict, + ) + + +class MemoryResourceWithStreamingResponse: + def __init__(self, memory: MemoryResource) -> None: + self._memory = memory + + self.retrieve = to_streamed_response_wrapper( + memory.retrieve, + ) + self.clear = to_streamed_response_wrapper( + memory.clear, + ) + self.evict = to_streamed_response_wrapper( + memory.evict, + ) + + +class AsyncMemoryResourceWithStreamingResponse: + def __init__(self, memory: AsyncMemoryResource) -> None: + self._memory = memory + + self.retrieve = async_to_streamed_response_wrapper( + memory.retrieve, + ) + self.clear = async_to_streamed_response_wrapper( + memory.clear, + ) + self.evict = async_to_streamed_response_wrapper( + memory.evict, + ) diff --git a/src/parallel/resources/monitor.py b/src/parallel/resources/monitor.py index a51201f..ae33fcf 100644 --- a/src/parallel/resources/monitor.py +++ b/src/parallel/resources/monitor.py @@ -68,6 +68,7 @@ def create( frequency: str, settings: monitor_create_params.Settings, type: Literal["event_stream", "snapshot"], + memory_scope_key: Optional[str] | Omit = omit, metadata: Optional[Dict[str, str]] | Omit = omit, processor: Literal["lite", "base"] | Omit = omit, webhook: Optional[MonitorWebhookParam] | Omit = omit, @@ -98,6 +99,9 @@ def create( changes; `snapshot` monitors a specific task run's output. Determines the expected shape of `settings`. + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + metadata: User-provided metadata stored with the monitor and echoed back in webhook notifications and GET responses, so you can map events to objects in your application. Keys: max 16 chars; values: max 512 chars. @@ -122,6 +126,7 @@ def create( "frequency": frequency, "settings": settings, "type": type, + "memory_scope_key": memory_scope_key, "metadata": metadata, "processor": processor, "webhook": webhook, @@ -480,6 +485,7 @@ async def create( frequency: str, settings: monitor_create_params.Settings, type: Literal["event_stream", "snapshot"], + memory_scope_key: Optional[str] | Omit = omit, metadata: Optional[Dict[str, str]] | Omit = omit, processor: Literal["lite", "base"] | Omit = omit, webhook: Optional[MonitorWebhookParam] | Omit = omit, @@ -510,6 +516,9 @@ async def create( changes; `snapshot` monitors a specific task run's output. Determines the expected shape of `settings`. + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + metadata: User-provided metadata stored with the monitor and echoed back in webhook notifications and GET responses, so you can map events to objects in your application. Keys: max 16 chars; values: max 512 chars. @@ -534,6 +543,7 @@ async def create( "frequency": frequency, "settings": settings, "type": type, + "memory_scope_key": memory_scope_key, "metadata": metadata, "processor": processor, "webhook": webhook, diff --git a/src/parallel/resources/task_run.py b/src/parallel/resources/task_run.py index 2a73374..efe256f 100644 --- a/src/parallel/resources/task_run.py +++ b/src/parallel/resources/task_run.py @@ -84,6 +84,7 @@ def create( advanced_settings: Optional[TaskAdvancedSettingsParam] | Omit = omit, enable_events: Optional[bool] | Omit = omit, mcp_servers: Optional[Iterable[McpServerParam]] | Omit = omit, + memory_scope_key: Optional[str] | Omit = omit, metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, previous_interaction_id: Optional[str] | Omit = omit, source_policy: Optional[SourcePolicy] | Omit = omit, @@ -120,6 +121,9 @@ def create( mcp_servers: Optional list of MCP servers to use for the run. + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + metadata: User-provided metadata stored with the run. Keys and values must be strings with a maximum length of 16 and 512 characters respectively. @@ -161,6 +165,7 @@ def create( "advanced_settings": advanced_settings, "enable_events": enable_events, "mcp_servers": mcp_servers, + "memory_scope_key": memory_scope_key, "metadata": metadata, "previous_interaction_id": previous_interaction_id, "source_policy": source_policy, @@ -499,6 +504,7 @@ async def create( advanced_settings: Optional[TaskAdvancedSettingsParam] | Omit = omit, enable_events: Optional[bool] | Omit = omit, mcp_servers: Optional[Iterable[McpServerParam]] | Omit = omit, + memory_scope_key: Optional[str] | Omit = omit, metadata: Optional[Dict[str, Union[str, float, bool]]] | Omit = omit, previous_interaction_id: Optional[str] | Omit = omit, source_policy: Optional[SourcePolicy] | Omit = omit, @@ -535,6 +541,9 @@ async def create( mcp_servers: Optional list of MCP servers to use for the run. + memory_scope_key: User-provided key identifying the memory scope to use. Omit to use personal + memory, if available. + metadata: User-provided metadata stored with the run. Keys and values must be strings with a maximum length of 16 and 512 characters respectively. @@ -576,6 +585,7 @@ async def create( "advanced_settings": advanced_settings, "enable_events": enable_events, "mcp_servers": mcp_servers, + "memory_scope_key": memory_scope_key, "metadata": metadata, "previous_interaction_id": previous_interaction_id, "source_policy": source_policy, diff --git a/src/parallel/types/beta/__init__.py b/src/parallel/types/beta/__init__.py index 377d9f1..dbd95da 100644 --- a/src/parallel/types/beta/__init__.py +++ b/src/parallel/types/beta/__init__.py @@ -8,16 +8,24 @@ from .findall_candidate import FindAllCandidate as FindAllCandidate from .findall_run_result import FindAllRunResult as FindAllRunResult from .findall_run_status import FindAllRunStatus as FindAllRunStatus +from .task_memory_result import TaskMemoryResult as TaskMemoryResult +from .memory_clear_params import MemoryClearParams as MemoryClearParams +from .memory_evict_params import MemoryEvictParams as MemoryEvictParams from .parallel_beta_param import ParallelBetaParam as ParallelBetaParam from .findall_enrich_input import FindAllEnrichInput as FindAllEnrichInput +from .monitor_memory_event import MonitorMemoryEvent as MonitorMemoryEvent from .findall_create_params import FindAllCreateParams as FindAllCreateParams from .findall_enrich_params import FindAllEnrichParams as FindAllEnrichParams from .findall_events_params import FindAllEventsParams as FindAllEventsParams from .findall_extend_params import FindAllExtendParams as FindAllExtendParams from .findall_ingest_params import FindAllIngestParams as FindAllIngestParams +from .findall_memory_result import FindAllMemoryResult as FindAllMemoryResult from .match_condition_param import MatchConditionParam as MatchConditionParam +from .monitor_memory_result import MonitorMemoryResult as MonitorMemoryResult +from .memory_retrieve_params import MemoryRetrieveParams as MemoryRetrieveParams from .findall_events_response import FindAllEventsResponse as FindAllEventsResponse from .findall_run_status_event import FindAllRunStatusEvent as FindAllRunStatusEvent +from .memory_retrieve_response import MemoryRetrieveResponse as MemoryRetrieveResponse from .findall_candidate_metrics import FindAllCandidateMetrics as FindAllCandidateMetrics from .findall_entity_search_params import FindAllEntitySearchParams as FindAllEntitySearchParams from .findall_schema_updated_event import FindAllSchemaUpdatedEvent as FindAllSchemaUpdatedEvent diff --git a/src/parallel/types/beta/findall_create_params.py b/src/parallel/types/beta/findall_create_params.py index 5345c04..0005602 100644 --- a/src/parallel/types/beta/findall_create_params.py +++ b/src/parallel/types/beta/findall_create_params.py @@ -33,7 +33,16 @@ class FindAllCreateParams(TypedDict, total=False): """Natural language objective of the FindAll run.""" exclude_list: Optional[Iterable[ExcludeList]] - """List of entity names/IDs to exclude from results.""" + """List of entity names/IDs to exclude from results. + + At most 10,000 entries are allowed. + """ + + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ metadata: Optional[Dict[str, Union[str, float, bool]]] """Metadata for the FindAll run.""" diff --git a/src/parallel/types/beta/findall_memory_result.py b/src/parallel/types/beta/findall_memory_result.py new file mode 100644 index 0000000..3772f16 --- /dev/null +++ b/src/parallel/types/beta/findall_memory_result.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["FindAllMemoryResult"] + + +class FindAllMemoryResult(BaseModel): + id: str + """ID of the FindAll run.""" + + input_excerpt: str + """Preview of the run's objective. May be truncated.""" + + matched_count: int + """Current number of matched entities.""" + + updated_at: datetime + """When the FindAll result was last updated, as an RFC 3339 timestamp.""" + + kind: Optional[Literal["findall"]] = None diff --git a/src/parallel/types/beta/memory_clear_params.py b/src/parallel/types/beta/memory_clear_params.py new file mode 100644 index 0000000..9808018 --- /dev/null +++ b/src/parallel/types/beta/memory_clear_params.py @@ -0,0 +1,16 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import TypedDict + +__all__ = ["MemoryClearParams"] + + +class MemoryClearParams(TypedDict, total=False): + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ diff --git a/src/parallel/types/beta/memory_evict_params.py b/src/parallel/types/beta/memory_evict_params.py new file mode 100644 index 0000000..ca13b80 --- /dev/null +++ b/src/parallel/types/beta/memory_evict_params.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Optional +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["MemoryEvictParams"] + + +class MemoryEvictParams(TypedDict, total=False): + id: Required[str] + """ID of the task run, monitor, or FindAll run to evict.""" + + kind: Required[Literal["task", "monitor", "findall"]] + """Kind of source to evict: `task`, `monitor`, or `findall`.""" + + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ diff --git a/src/parallel/types/beta/memory_retrieve_params.py b/src/parallel/types/beta/memory_retrieve_params.py new file mode 100644 index 0000000..0986288 --- /dev/null +++ b/src/parallel/types/beta/memory_retrieve_params.py @@ -0,0 +1,37 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Union, Optional +from datetime import datetime +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["MemoryRetrieveParams"] + + +class MemoryRetrieveParams(TypedDict, total=False): + kind: Optional[Literal["task", "monitor", "findall"]] + """Filter memories by kind: `task`, `monitor`, or `findall`.""" + + limit: int + """Maximum number of memories to return.""" + + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ + + query: Optional[str] + """Concise query describing the memories to retrieve. + + Empty queries return the most recent memories. + """ + + since: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] + """ + Only return memories sourced from task, monitor, or FindAll runs completed at or + after this RFC 3339 timestamp. + """ diff --git a/src/parallel/types/beta/memory_retrieve_response.py b/src/parallel/types/beta/memory_retrieve_response.py new file mode 100644 index 0000000..9b55bec --- /dev/null +++ b/src/parallel/types/beta/memory_retrieve_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union +from typing_extensions import Annotated, TypeAlias + +from ..._utils import PropertyInfo +from ..._models import BaseModel +from .task_memory_result import TaskMemoryResult +from .findall_memory_result import FindAllMemoryResult +from .monitor_memory_result import MonitorMemoryResult + +__all__ = ["MemoryRetrieveResponse", "Result"] + +Result: TypeAlias = Annotated[ + Union[TaskMemoryResult, MonitorMemoryResult, FindAllMemoryResult], PropertyInfo(discriminator="kind") +] + + +class MemoryRetrieveResponse(BaseModel): + results: List[Result] diff --git a/src/parallel/types/beta/monitor_memory_event.py b/src/parallel/types/beta/monitor_memory_event.py new file mode 100644 index 0000000..70dc9d1 --- /dev/null +++ b/src/parallel/types/beta/monitor_memory_event.py @@ -0,0 +1,21 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from datetime import datetime + +from ..._models import BaseModel + +__all__ = ["MonitorMemoryEvent"] + + +class MonitorMemoryEvent(BaseModel): + detected_at: datetime + """When the event was detected, as an RFC 3339 timestamp.""" + + event_group_id: str + """ID of the execution that produced this event.""" + + event_id: str + """ID of the monitor event.""" + + excerpt: str + """Excerpt of the monitor event. May be truncated.""" diff --git a/src/parallel/types/beta/monitor_memory_result.py b/src/parallel/types/beta/monitor_memory_result.py new file mode 100644 index 0000000..8a78977 --- /dev/null +++ b/src/parallel/types/beta/monitor_memory_result.py @@ -0,0 +1,32 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel +from .monitor_memory_event import MonitorMemoryEvent + +__all__ = ["MonitorMemoryResult"] + + +class MonitorMemoryResult(BaseModel): + id: str + """ID of the monitor.""" + + input_excerpt: str + """Preview of the monitor's query. May be truncated.""" + + status: Literal["active", "cancelled"] + """Current status of the monitor.""" + + updated_at: datetime + """When the monitor last ran, as an RFC 3339 timestamp.""" + + kind: Optional[Literal["monitor"]] = None + + matched_events: Optional[List[MonitorMemoryEvent]] = None + """ + Detected events matching the retrieval query, ordered by relevance with more + recent events favored. For an empty query, events are ordered by recency. + """ diff --git a/src/parallel/types/beta/task_memory_result.py b/src/parallel/types/beta/task_memory_result.py new file mode 100644 index 0000000..c893790 --- /dev/null +++ b/src/parallel/types/beta/task_memory_result.py @@ -0,0 +1,25 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["TaskMemoryResult"] + + +class TaskMemoryResult(BaseModel): + id: str + """ID of the task run.""" + + input_excerpt: str + """Preview of the run's input. May be truncated.""" + + output_excerpt: str + """Preview of the run's output. May be truncated.""" + + updated_at: datetime + """When the run completed, as an RFC 3339 timestamp.""" + + kind: Optional[Literal["task"]] = None diff --git a/src/parallel/types/client_search_params.py b/src/parallel/types/client_search_params.py index b45988b..c1114cd 100644 --- a/src/parallel/types/client_search_params.py +++ b/src/parallel/types/client_search_params.py @@ -35,13 +35,14 @@ class ClientSearchParams(TypedDict, total=False): max_chars_total: Optional[int] """Upper bound on total characters across excerpts from all results.""" - mode: Optional[Literal["turbo", "basic", "advanced"]] - """Search mode preset: supported values are `turbo`, `basic`, and `advanced`. - - Turbo mode is optimized for the fastest responses. Basic mode offers low latency - and works best with 2-3 high-quality search_queries. Advanced mode provides - higher quality with more advanced retrieval and compression. Defaults to - `advanced` when omitted. + mode: Optional[Literal["turbo", "basic", "advanced", "fast"]] + """ + Search mode preset: supported values are `turbo`, `fast`, `basic`, and + `advanced`. Turbo mode is optimized for the fastest responses. Fast mode trades + some quality for low latency, and works best with concise, high-quality + objective and search_queries. Basic mode offers low latency and works best with + 2-3 high-quality search_queries. Advanced mode provides higher quality with more + advanced retrieval and compression. Defaults to `advanced` when omitted. """ objective: Optional[str] diff --git a/src/parallel/types/monitor_create_params.py b/src/parallel/types/monitor_create_params.py index 769d5e9..910ea59 100644 --- a/src/parallel/types/monitor_create_params.py +++ b/src/parallel/types/monitor_create_params.py @@ -35,6 +35,12 @@ class MonitorCreateParams(TypedDict, total=False): a specific task run's output. Determines the expected shape of `settings`. """ + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ + metadata: Optional[Dict[str, str]] """ User-provided metadata stored with the monitor and echoed back in webhook diff --git a/src/parallel/types/run_input.py b/src/parallel/types/run_input.py index 08cf0bd..f2b9711 100644 --- a/src/parallel/types/run_input.py +++ b/src/parallel/types/run_input.py @@ -37,6 +37,12 @@ class RunInput(BaseModel): mcp_servers: Optional[List[McpServer]] = None """Optional list of MCP servers to use for the run.""" + memory_scope_key: Optional[str] = None + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ + metadata: Optional[Dict[str, Union[str, float, bool]]] = None """User-provided metadata stored with the run. diff --git a/src/parallel/types/run_input_param.py b/src/parallel/types/run_input_param.py index a747103..cf1c39d 100644 --- a/src/parallel/types/run_input_param.py +++ b/src/parallel/types/run_input_param.py @@ -39,6 +39,12 @@ class RunInputParam(TypedDict, total=False): mcp_servers: Optional[Iterable[McpServerParam]] """Optional list of MCP servers to use for the run.""" + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ + metadata: Optional[Dict[str, Union[str, float, bool]]] """User-provided metadata stored with the run. diff --git a/src/parallel/types/task_run_create_params.py b/src/parallel/types/task_run_create_params.py index a15d920..295aaf5 100644 --- a/src/parallel/types/task_run_create_params.py +++ b/src/parallel/types/task_run_create_params.py @@ -39,6 +39,12 @@ class TaskRunCreateParams(TypedDict, total=False): mcp_servers: Optional[Iterable[McpServerParam]] """Optional list of MCP servers to use for the run.""" + memory_scope_key: Optional[str] + """User-provided key identifying the memory scope to use. + + Omit to use personal memory, if available. + """ + metadata: Optional[Dict[str, Union[str, float, bool]]] """User-provided metadata stored with the run. diff --git a/tests/api_resources/beta/test_findall.py b/tests/api_resources/beta/test_findall.py index 69cd0f3..ff0bb61 100644 --- a/tests/api_resources/beta/test_findall.py +++ b/tests/api_resources/beta/test_findall.py @@ -57,6 +57,7 @@ def test_method_create_with_all_params(self, client: Parallel) -> None: "url": "url", } ], + memory_scope_key="memory_scope_key", metadata={"foo": "string"}, webhook={ "url": "url", @@ -610,6 +611,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncParallel) "url": "url", } ], + memory_scope_key="memory_scope_key", metadata={"foo": "string"}, webhook={ "url": "url", diff --git a/tests/api_resources/beta/test_memory.py b/tests/api_resources/beta/test_memory.py new file mode 100644 index 0000000..80a3dea --- /dev/null +++ b/tests/api_resources/beta/test_memory.py @@ -0,0 +1,247 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from parallel import Parallel, AsyncParallel +from tests.utils import assert_matches_type +from parallel._utils import parse_datetime +from parallel.types.beta import MemoryRetrieveResponse + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestMemory: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @parametrize + def test_method_retrieve(self, client: Parallel) -> None: + memory = client.beta.memory.retrieve() + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + @parametrize + def test_method_retrieve_with_all_params(self, client: Parallel) -> None: + memory = client.beta.memory.retrieve( + kind="task", + limit=1, + memory_scope_key="memory_scope_key", + query="query", + since=parse_datetime("2026-07-15T17:30:00Z"), + ) + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + @parametrize + def test_raw_response_retrieve(self, client: Parallel) -> None: + response = client.beta.memory.with_raw_response.retrieve() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + memory = response.parse() + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + @parametrize + def test_streaming_response_retrieve(self, client: Parallel) -> None: + with client.beta.memory.with_streaming_response.retrieve() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + memory = response.parse() + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_clear(self, client: Parallel) -> None: + memory = client.beta.memory.clear() + assert memory is None + + @parametrize + def test_method_clear_with_all_params(self, client: Parallel) -> None: + memory = client.beta.memory.clear( + memory_scope_key="memory_scope_key", + ) + assert memory is None + + @parametrize + def test_raw_response_clear(self, client: Parallel) -> None: + response = client.beta.memory.with_raw_response.clear() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + memory = response.parse() + assert memory is None + + @parametrize + def test_streaming_response_clear(self, client: Parallel) -> None: + with client.beta.memory.with_streaming_response.clear() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + memory = response.parse() + assert memory is None + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_evict(self, client: Parallel) -> None: + memory = client.beta.memory.evict( + id="id", + kind="task", + ) + assert memory is None + + @parametrize + def test_method_evict_with_all_params(self, client: Parallel) -> None: + memory = client.beta.memory.evict( + id="id", + kind="task", + memory_scope_key="memory_scope_key", + ) + assert memory is None + + @parametrize + def test_raw_response_evict(self, client: Parallel) -> None: + response = client.beta.memory.with_raw_response.evict( + id="id", + kind="task", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + memory = response.parse() + assert memory is None + + @parametrize + def test_streaming_response_evict(self, client: Parallel) -> None: + with client.beta.memory.with_streaming_response.evict( + id="id", + kind="task", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + memory = response.parse() + assert memory is None + + assert cast(Any, response.is_closed) is True + + +class TestAsyncMemory: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @parametrize + async def test_method_retrieve(self, async_client: AsyncParallel) -> None: + memory = await async_client.beta.memory.retrieve() + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncParallel) -> None: + memory = await async_client.beta.memory.retrieve( + kind="task", + limit=1, + memory_scope_key="memory_scope_key", + query="query", + since=parse_datetime("2026-07-15T17:30:00Z"), + ) + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncParallel) -> None: + response = await async_client.beta.memory.with_raw_response.retrieve() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + memory = await response.parse() + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncParallel) -> None: + async with async_client.beta.memory.with_streaming_response.retrieve() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + memory = await response.parse() + assert_matches_type(MemoryRetrieveResponse, memory, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_clear(self, async_client: AsyncParallel) -> None: + memory = await async_client.beta.memory.clear() + assert memory is None + + @parametrize + async def test_method_clear_with_all_params(self, async_client: AsyncParallel) -> None: + memory = await async_client.beta.memory.clear( + memory_scope_key="memory_scope_key", + ) + assert memory is None + + @parametrize + async def test_raw_response_clear(self, async_client: AsyncParallel) -> None: + response = await async_client.beta.memory.with_raw_response.clear() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + memory = await response.parse() + assert memory is None + + @parametrize + async def test_streaming_response_clear(self, async_client: AsyncParallel) -> None: + async with async_client.beta.memory.with_streaming_response.clear() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + memory = await response.parse() + assert memory is None + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_evict(self, async_client: AsyncParallel) -> None: + memory = await async_client.beta.memory.evict( + id="id", + kind="task", + ) + assert memory is None + + @parametrize + async def test_method_evict_with_all_params(self, async_client: AsyncParallel) -> None: + memory = await async_client.beta.memory.evict( + id="id", + kind="task", + memory_scope_key="memory_scope_key", + ) + assert memory is None + + @parametrize + async def test_raw_response_evict(self, async_client: AsyncParallel) -> None: + response = await async_client.beta.memory.with_raw_response.evict( + id="id", + kind="task", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + memory = await response.parse() + assert memory is None + + @parametrize + async def test_streaming_response_evict(self, async_client: AsyncParallel) -> None: + async with async_client.beta.memory.with_streaming_response.evict( + id="id", + kind="task", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + memory = await response.parse() + assert memory is None + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_monitor.py b/tests/api_resources/test_monitor.py index 94b8682..06f1615 100644 --- a/tests/api_resources/test_monitor.py +++ b/tests/api_resources/test_monitor.py @@ -57,6 +57,7 @@ def test_method_create_with_all_params(self, client: Parallel) -> None: }, }, type="event_stream", + memory_scope_key="memory_scope_key", metadata={ "slack_thread_id": "1234567890.123456", "user_id": "U123ABC", @@ -402,6 +403,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncParallel) }, }, type="event_stream", + memory_scope_key="memory_scope_key", metadata={ "slack_thread_id": "1234567890.123456", "user_id": "U123ABC", diff --git a/tests/api_resources/test_task_group.py b/tests/api_resources/test_task_group.py index 29ae421..293b519 100644 --- a/tests/api_resources/test_task_group.py +++ b/tests/api_resources/test_task_group.py @@ -124,6 +124,7 @@ def test_method_add_runs_with_all_params(self, client: Parallel) -> None: "type": "url", } ], + "memory_scope_key": "memory_scope_key", "metadata": {"foo": "string"}, "previous_interaction_id": "previous_interaction_id", "source_policy": { @@ -465,6 +466,7 @@ async def test_method_add_runs_with_all_params(self, async_client: AsyncParallel "type": "url", } ], + "memory_scope_key": "memory_scope_key", "metadata": {"foo": "string"}, "previous_interaction_id": "previous_interaction_id", "source_policy": { diff --git a/tests/api_resources/test_task_run.py b/tests/api_resources/test_task_run.py index a41628a..5fa7f93 100644 --- a/tests/api_resources/test_task_run.py +++ b/tests/api_resources/test_task_run.py @@ -46,6 +46,7 @@ def test_method_create_with_all_params(self, client: Parallel) -> None: "type": "url", } ], + memory_scope_key="memory_scope_key", metadata={"foo": "string"}, previous_interaction_id="previous_interaction_id", source_policy={ @@ -289,6 +290,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncParallel) "type": "url", } ], + memory_scope_key="memory_scope_key", metadata={"foo": "string"}, previous_interaction_id="previous_interaction_id", source_policy={ From e726e105f6711ad49ce8f756f3d2bc07404c27ca Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:02:32 +0000 Subject: [PATCH 3/4] feat(api): manual updates --- .stats.yml | 4 ++-- src/parallel/_client.py | 26 ++++++++++------------ src/parallel/types/client_search_params.py | 15 ++++++------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/.stats.yml b/.stats.yml index 20142f4..00c360c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 33 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-dcb1605f4878ba899f427518b5f86d2bb79fc37820caa27392695fe8b7f5295c.yml -openapi_spec_hash: 6c7d3db50b53be72d8b35c260f771004 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/parallel-web/parallel-sdk-e72f6dcf18ffc713480444feef670bbbe754221e0a68336823642b474c20ec93.yml +openapi_spec_hash: ae8c3c62a78f2413f52c240c2a5d68a8 config_hash: d4f69197dba970d05757624fe3f7b373 diff --git a/src/parallel/_client.py b/src/parallel/_client.py index e35da7e..8ecaaaf 100644 --- a/src/parallel/_client.py +++ b/src/parallel/_client.py @@ -355,7 +355,7 @@ def search( advanced_settings: Optional[AdvancedSearchSettingsParam] | Omit = omit, client_model: Optional[str] | Omit = omit, max_chars_total: Optional[int] | Omit = omit, - mode: Optional[Literal["turbo", "basic", "advanced", "fast"]] | Omit = omit, + mode: Optional[Literal["turbo", "basic", "advanced"]] | Omit = omit, objective: Optional[str] | Omit = omit, session_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -388,12 +388,11 @@ def search( max_chars_total: Upper bound on total characters across excerpts from all results. - mode: Search mode preset: supported values are `turbo`, `fast`, `basic`, and - `advanced`. Turbo mode is optimized for the fastest responses. Fast mode trades - some quality for low latency, and works best with concise, high-quality - objective and search_queries. Basic mode offers low latency and works best with - 2-3 high-quality search_queries. Advanced mode provides higher quality with more - advanced retrieval and compression. Defaults to `advanced` when omitted. + mode: Search mode preset: supported values are `turbo`, `basic`, and `advanced`. Turbo + mode is optimized for the fastest responses. Basic mode offers low latency and + works best with 2-3 high-quality search_queries. Advanced mode provides higher + quality with more advanced retrieval and compression. Defaults to `advanced` + when omitted. objective: Natural-language description of the underlying question or goal driving the search. Used together with search_queries to focus results on the most relevant @@ -749,7 +748,7 @@ async def search( advanced_settings: Optional[AdvancedSearchSettingsParam] | Omit = omit, client_model: Optional[str] | Omit = omit, max_chars_total: Optional[int] | Omit = omit, - mode: Optional[Literal["turbo", "basic", "advanced", "fast"]] | Omit = omit, + mode: Optional[Literal["turbo", "basic", "advanced"]] | Omit = omit, objective: Optional[str] | Omit = omit, session_id: Optional[str] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -782,12 +781,11 @@ async def search( max_chars_total: Upper bound on total characters across excerpts from all results. - mode: Search mode preset: supported values are `turbo`, `fast`, `basic`, and - `advanced`. Turbo mode is optimized for the fastest responses. Fast mode trades - some quality for low latency, and works best with concise, high-quality - objective and search_queries. Basic mode offers low latency and works best with - 2-3 high-quality search_queries. Advanced mode provides higher quality with more - advanced retrieval and compression. Defaults to `advanced` when omitted. + mode: Search mode preset: supported values are `turbo`, `basic`, and `advanced`. Turbo + mode is optimized for the fastest responses. Basic mode offers low latency and + works best with 2-3 high-quality search_queries. Advanced mode provides higher + quality with more advanced retrieval and compression. Defaults to `advanced` + when omitted. objective: Natural-language description of the underlying question or goal driving the search. Used together with search_queries to focus results on the most relevant diff --git a/src/parallel/types/client_search_params.py b/src/parallel/types/client_search_params.py index c1114cd..b45988b 100644 --- a/src/parallel/types/client_search_params.py +++ b/src/parallel/types/client_search_params.py @@ -35,14 +35,13 @@ class ClientSearchParams(TypedDict, total=False): max_chars_total: Optional[int] """Upper bound on total characters across excerpts from all results.""" - mode: Optional[Literal["turbo", "basic", "advanced", "fast"]] - """ - Search mode preset: supported values are `turbo`, `fast`, `basic`, and - `advanced`. Turbo mode is optimized for the fastest responses. Fast mode trades - some quality for low latency, and works best with concise, high-quality - objective and search_queries. Basic mode offers low latency and works best with - 2-3 high-quality search_queries. Advanced mode provides higher quality with more - advanced retrieval and compression. Defaults to `advanced` when omitted. + mode: Optional[Literal["turbo", "basic", "advanced"]] + """Search mode preset: supported values are `turbo`, `basic`, and `advanced`. + + Turbo mode is optimized for the fastest responses. Basic mode offers low latency + and works best with 2-3 high-quality search_queries. Advanced mode provides + higher quality with more advanced retrieval and compression. Defaults to + `advanced` when omitted. """ objective: Optional[str] From b36e4a9269395e804b00a8bed94490263bad01f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:02:52 +0000 Subject: [PATCH 4/4] release: 1.2.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ pyproject.toml | 2 +- src/parallel/_version.py | 2 +- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2601677..d0ab664 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.1.0" + ".": "1.2.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a88f15..9ca2afd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 1.2.0 (2026-08-10) + +Full Changelog: [v1.1.0...v1.2.0](https://github.com/parallel-web/parallel-sdk-python/compare/v1.1.0...v1.2.0) + +### Features + +* **api:** add memory support ([15f1f47](https://github.com/parallel-web/parallel-sdk-python/commit/15f1f47985c735a57e7985a01f1eb5abbd07f1d9)) +* **api:** manual updates ([e726e10](https://github.com/parallel-web/parallel-sdk-python/commit/e726e105f6711ad49ce8f756f3d2bc07404c27ca)) +* **stlc:** configurable CI runner and private-production-repo support in workflow templates ([a2b4daa](https://github.com/parallel-web/parallel-sdk-python/commit/a2b4daa3caed18e5159da0747f1f3a5ccaa0b645)) + ## 1.1.0 (2026-06-08) Full Changelog: [v1.0.1...v1.1.0](https://github.com/parallel-web/parallel-sdk-python/compare/v1.0.1...v1.1.0) diff --git a/pyproject.toml b/pyproject.toml index 1b2efbf..e9ff6e6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "parallel-web" -version = "1.1.0" +version = "1.2.0" description = "The official Python library for the Parallel API" dynamic = ["readme"] license = "MIT" diff --git a/src/parallel/_version.py b/src/parallel/_version.py index 1f53f25..6013d9c 100644 --- a/src/parallel/_version.py +++ b/src/parallel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "parallel" -__version__ = "1.1.0" # x-release-please-version +__version__ = "1.2.0" # x-release-please-version