From 4c65bf113a5aeada0e0fa77d46c5cacf50632e7a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 11 Feb 2026 22:21:35 +0000
Subject: [PATCH 001/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/connector_search_tables_response.py | 8 ++++++++
src/structify/types/llm_information_store.py | 2 ++
src/structify/types/update_table_response.py | 2 ++
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index fa94e3025..30c2e349c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-1e6c4fd0edc3495bc88e8e124a41a7598a682123854f9e9daabc54192f8f976c.yml
-openapi_spec_hash: 8ded4b078445c04fa30d205bcbadc1e5
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9c17f744ae43c8e9ba9b72fbbd9d37756ea00fa116d9895ae52af54425edfee7.yml
+openapi_spec_hash: bd69e13ca4cc72d7fb335973dbeaa343
config_hash: 165b687c958e22430204bd5ef9094d9a
diff --git a/src/structify/types/connector_search_tables_response.py b/src/structify/types/connector_search_tables_response.py
index bbf3314a5..ef591a4ac 100644
--- a/src/structify/types/connector_search_tables_response.py
+++ b/src/structify/types/connector_search_tables_response.py
@@ -21,6 +21,8 @@
class RankedResultColumn(BaseModel):
"""Represents a column in a table or API resource"""
+ id: str
+
name: str
"""Name of the column"""
@@ -34,6 +36,8 @@ class RankedResultColumn(BaseModel):
class RankedResultTableColumn(BaseModel):
"""Represents a column in a table or API resource"""
+ id: str
+
name: str
"""Name of the column"""
@@ -84,6 +88,8 @@ class RankedResult(BaseModel):
class RawResultColumn(BaseModel):
"""Represents a column in a table or API resource"""
+ id: str
+
name: str
"""Name of the column"""
@@ -97,6 +103,8 @@ class RawResultColumn(BaseModel):
class RawResultTableColumn(BaseModel):
"""Represents a column in a table or API resource"""
+ id: str
+
name: str
"""Name of the column"""
diff --git a/src/structify/types/llm_information_store.py b/src/structify/types/llm_information_store.py
index b1a81a3d5..a8dde6fee 100644
--- a/src/structify/types/llm_information_store.py
+++ b/src/structify/types/llm_information_store.py
@@ -10,6 +10,8 @@
class DatabaseSchemaTableColumn(BaseModel):
"""Represents a column in a table or API resource"""
+ id: str
+
name: str
"""Name of the column"""
diff --git a/src/structify/types/update_table_response.py b/src/structify/types/update_table_response.py
index a913c8a38..4ae117ce9 100644
--- a/src/structify/types/update_table_response.py
+++ b/src/structify/types/update_table_response.py
@@ -10,6 +10,8 @@
class TableColumn(BaseModel):
"""Represents a column in a table or API resource"""
+ id: str
+
name: str
"""Name of the column"""
From 3a7173f56434bada6297dc0b2b25cd77fa0053cb Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 08:24:10 +0000
Subject: [PATCH 002/105] chore(internal): fix lint error on Python 3.14
---
src/structify/_utils/_compat.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/structify/_utils/_compat.py b/src/structify/_utils/_compat.py
index dd703233c..2c70b299c 100644
--- a/src/structify/_utils/_compat.py
+++ b/src/structify/_utils/_compat.py
@@ -26,7 +26,7 @@ def is_union(tp: Optional[Type[Any]]) -> bool:
else:
import types
- return tp is Union or tp is types.UnionType
+ return tp is Union or tp is types.UnionType # type: ignore[comparison-overlap]
def is_typeddict(tp: Type[Any]) -> bool:
From dade59552964ae2200022f60dc64f17543d225d3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 18:03:18 +0000
Subject: [PATCH 003/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/teams.py | 8 ++++++++
src/structify/types/sandbox.py | 2 ++
src/structify/types/team_update_params.py | 20 ++++++++++++++++++--
tests/api_resources/test_teams.py | 16 ++++++++++++++++
5 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 30c2e349c..c0fb57eff 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9c17f744ae43c8e9ba9b72fbbd9d37756ea00fa116d9895ae52af54425edfee7.yml
-openapi_spec_hash: bd69e13ca4cc72d7fb335973dbeaa343
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-40ac71e21bee6a060911db5a284c5c26af5c377743cb97ee08953c8ff3e2fa9b.yml
+openapi_spec_hash: 27bd0599c243adfb76dcbd30a0b218ac
config_hash: 165b687c958e22430204bd5ef9094d9a
diff --git a/src/structify/resources/teams.py b/src/structify/resources/teams.py
index 6513fc06f..d23aa3fd6 100644
--- a/src/structify/resources/teams.py
+++ b/src/structify/resources/teams.py
@@ -111,6 +111,7 @@ def update(
self,
team_id: str,
*,
+ daytona_credentials: Optional[team_update_params.DaytonaCredentials] | Omit = omit,
description: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
pipedream_project_id: Optional[str] | Omit = omit,
@@ -121,6 +122,7 @@ def update(
teams_app_id: Optional[str] | Omit = omit,
teams_app_password: Optional[str] | Omit = omit,
teams_tenant_id: Optional[str] | Omit = omit,
+ workflow_bucket: Optional[team_update_params.WorkflowBucket] | 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,
@@ -144,6 +146,7 @@ def update(
f"/team/{team_id}",
body=maybe_transform(
{
+ "daytona_credentials": daytona_credentials,
"description": description,
"name": name,
"pipedream_project_id": pipedream_project_id,
@@ -154,6 +157,7 @@ def update(
"teams_app_id": teams_app_id,
"teams_app_password": teams_app_password,
"teams_tenant_id": teams_tenant_id,
+ "workflow_bucket": workflow_bucket,
},
team_update_params.TeamUpdateParams,
),
@@ -670,6 +674,7 @@ async def update(
self,
team_id: str,
*,
+ daytona_credentials: Optional[team_update_params.DaytonaCredentials] | Omit = omit,
description: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
pipedream_project_id: Optional[str] | Omit = omit,
@@ -680,6 +685,7 @@ async def update(
teams_app_id: Optional[str] | Omit = omit,
teams_app_password: Optional[str] | Omit = omit,
teams_tenant_id: Optional[str] | Omit = omit,
+ workflow_bucket: Optional[team_update_params.WorkflowBucket] | 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,
@@ -703,6 +709,7 @@ async def update(
f"/team/{team_id}",
body=await async_maybe_transform(
{
+ "daytona_credentials": daytona_credentials,
"description": description,
"name": name,
"pipedream_project_id": pipedream_project_id,
@@ -713,6 +720,7 @@ async def update(
"teams_app_id": teams_app_id,
"teams_app_password": teams_app_password,
"teams_tenant_id": teams_tenant_id,
+ "workflow_bucket": workflow_bucket,
},
team_update_params.TeamUpdateParams,
),
diff --git a/src/structify/types/sandbox.py b/src/structify/types/sandbox.py
index 37e213da1..47925e3a1 100644
--- a/src/structify/types/sandbox.py
+++ b/src/structify/types/sandbox.py
@@ -20,6 +20,8 @@ class Sandbox(BaseModel):
status: Literal["alive", "terminated"]
+ team_id: str
+
updated_at: datetime
api_url: Optional[str] = None
diff --git a/src/structify/types/team_update_params.py b/src/structify/types/team_update_params.py
index e671cbb8b..3189391b3 100644
--- a/src/structify/types/team_update_params.py
+++ b/src/structify/types/team_update_params.py
@@ -3,12 +3,14 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Required, TypedDict
-__all__ = ["TeamUpdateParams"]
+__all__ = ["TeamUpdateParams", "DaytonaCredentials", "WorkflowBucket"]
class TeamUpdateParams(TypedDict, total=False):
+ daytona_credentials: Optional[DaytonaCredentials]
+
description: Optional[str]
name: Optional[str]
@@ -28,3 +30,17 @@ class TeamUpdateParams(TypedDict, total=False):
teams_app_password: Optional[str]
teams_tenant_id: Optional[str]
+
+ workflow_bucket: Optional[WorkflowBucket]
+
+
+class DaytonaCredentials(TypedDict, total=False):
+ api_key: Optional[str]
+
+ api_url: Optional[str]
+
+
+class WorkflowBucket(TypedDict, total=False):
+ bucket_url: Required[str]
+
+ gcp_credentials_json: Optional[str]
diff --git a/tests/api_resources/test_teams.py b/tests/api_resources/test_teams.py
index af5d5dca3..07b5762b7 100644
--- a/tests/api_resources/test_teams.py
+++ b/tests/api_resources/test_teams.py
@@ -83,6 +83,10 @@ def test_method_update(self, client: Structify) -> None:
def test_method_update_with_all_params(self, client: Structify) -> None:
team = client.teams.update(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ daytona_credentials={
+ "api_key": "api_key",
+ "api_url": "api_url",
+ },
description="description",
name="name",
pipedream_project_id="pipedream_project_id",
@@ -93,6 +97,10 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
teams_app_id="teams_app_id",
teams_app_password="teams_app_password",
teams_tenant_id="teams_tenant_id",
+ workflow_bucket={
+ "bucket_url": "bucket_url",
+ "gcp_credentials_json": "gcp_credentials_json",
+ },
)
assert_matches_type(UpdateTeamResponse, team, path=["response"])
@@ -730,6 +738,10 @@ async def test_method_update(self, async_client: AsyncStructify) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncStructify) -> None:
team = await async_client.teams.update(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ daytona_credentials={
+ "api_key": "api_key",
+ "api_url": "api_url",
+ },
description="description",
name="name",
pipedream_project_id="pipedream_project_id",
@@ -740,6 +752,10 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
teams_app_id="teams_app_id",
teams_app_password="teams_app_password",
teams_tenant_id="teams_tenant_id",
+ workflow_bucket={
+ "bucket_url": "bucket_url",
+ "gcp_credentials_json": "gcp_credentials_json",
+ },
)
assert_matches_type(UpdateTeamResponse, team, path=["response"])
From 248cbcb0cb64809d62173317c07498ad37cd83d2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 21:05:47 +0000
Subject: [PATCH 004/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connectors/connectors.py | 16 ----------------
src/structify/resources/teams.py | 4 ----
src/structify/types/connector.py | 4 ----
src/structify/types/connector_create_params.py | 7 -------
src/structify/types/team.py | 2 --
src/structify/types/team_update_params.py | 2 --
tests/api_resources/test_connectors.py | 6 ------
tests/api_resources/test_teams.py | 2 --
9 files changed, 2 insertions(+), 45 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c0fb57eff..ac3c9ed81 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-40ac71e21bee6a060911db5a284c5c26af5c377743cb97ee08953c8ff3e2fa9b.yml
-openapi_spec_hash: 27bd0599c243adfb76dcbd30a0b218ac
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-779ac9d3e3b624002e9371ec082c0382efbfcbfef3f4886686de3c78ed5f1aa6.yml
+openapi_spec_hash: d0c72e45260c840e533831c73c3c46d8
config_hash: 165b687c958e22430204bd5ef9094d9a
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 4b967eaf7..23f1f1870 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -94,9 +94,6 @@ def create(
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
- pipedream_account_id: Optional[str] | Omit = omit,
- pipedream_external_id: Optional[str] | Omit = omit,
- pipedream_project_id: Optional[str] | Omit = omit,
refresh_script: Optional[str] | Omit = omit,
secrets: Dict[str, str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -112,8 +109,6 @@ def create(
nango_integration_id: Nango integration ID (e.g., "linear", "slack")
- pipedream_external_id: Unique external ID for Pipedream routing (required for Pipedream connectors)
-
secrets: Optional secrets/environment variables for the connector
extra_headers: Send extra headers
@@ -134,9 +129,6 @@ def create(
"description": description,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
- "pipedream_account_id": pipedream_account_id,
- "pipedream_external_id": pipedream_external_id,
- "pipedream_project_id": pipedream_project_id,
"refresh_script": refresh_script,
"secrets": secrets,
},
@@ -1202,9 +1194,6 @@ async def create(
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
- pipedream_account_id: Optional[str] | Omit = omit,
- pipedream_external_id: Optional[str] | Omit = omit,
- pipedream_project_id: Optional[str] | Omit = omit,
refresh_script: Optional[str] | Omit = omit,
secrets: Dict[str, str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -1220,8 +1209,6 @@ async def create(
nango_integration_id: Nango integration ID (e.g., "linear", "slack")
- pipedream_external_id: Unique external ID for Pipedream routing (required for Pipedream connectors)
-
secrets: Optional secrets/environment variables for the connector
extra_headers: Send extra headers
@@ -1242,9 +1229,6 @@ async def create(
"description": description,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
- "pipedream_account_id": pipedream_account_id,
- "pipedream_external_id": pipedream_external_id,
- "pipedream_project_id": pipedream_project_id,
"refresh_script": refresh_script,
"secrets": secrets,
},
diff --git a/src/structify/resources/teams.py b/src/structify/resources/teams.py
index d23aa3fd6..0d8fbe051 100644
--- a/src/structify/resources/teams.py
+++ b/src/structify/resources/teams.py
@@ -114,7 +114,6 @@ def update(
daytona_credentials: Optional[team_update_params.DaytonaCredentials] | Omit = omit,
description: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
- pipedream_project_id: Optional[str] | Omit = omit,
slack_bot_token: Optional[str] | Omit = omit,
slack_team_icon: Optional[str] | Omit = omit,
slack_team_id: Optional[str] | Omit = omit,
@@ -149,7 +148,6 @@ def update(
"daytona_credentials": daytona_credentials,
"description": description,
"name": name,
- "pipedream_project_id": pipedream_project_id,
"slack_bot_token": slack_bot_token,
"slack_team_icon": slack_team_icon,
"slack_team_id": slack_team_id,
@@ -677,7 +675,6 @@ async def update(
daytona_credentials: Optional[team_update_params.DaytonaCredentials] | Omit = omit,
description: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
- pipedream_project_id: Optional[str] | Omit = omit,
slack_bot_token: Optional[str] | Omit = omit,
slack_team_icon: Optional[str] | Omit = omit,
slack_team_id: Optional[str] | Omit = omit,
@@ -712,7 +709,6 @@ async def update(
"daytona_credentials": daytona_credentials,
"description": description,
"name": name,
- "pipedream_project_id": pipedream_project_id,
"slack_bot_token": slack_bot_token,
"slack_team_icon": slack_team_icon,
"slack_team_id": slack_team_id,
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index d40f64e70..8eafb0636 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -41,10 +41,6 @@ class Connector(BaseModel):
nango_integration_id: Optional[str] = None
- pipedream_account_id: Optional[str] = None
-
- pipedream_external_id: Optional[str] = None
-
refresh_script: Optional[str] = None
usage_snippet_override: Optional[str] = None
diff --git a/src/structify/types/connector_create_params.py b/src/structify/types/connector_create_params.py
index 1f5534267..9aa5950fd 100644
--- a/src/structify/types/connector_create_params.py
+++ b/src/structify/types/connector_create_params.py
@@ -23,13 +23,6 @@ class ConnectorCreateParams(TypedDict, total=False):
nango_integration_id: Optional[str]
"""Nango integration ID (e.g., "linear", "slack")"""
- pipedream_account_id: Optional[str]
-
- pipedream_external_id: Optional[str]
- """Unique external ID for Pipedream routing (required for Pipedream connectors)"""
-
- pipedream_project_id: Optional[str]
-
refresh_script: Optional[str]
secrets: Dict[str, str]
diff --git a/src/structify/types/team.py b/src/structify/types/team.py
index cc1a46ccc..725790464 100644
--- a/src/structify/types/team.py
+++ b/src/structify/types/team.py
@@ -19,8 +19,6 @@ class Team(BaseModel):
description: Optional[str] = None
- pipedream_project_id: Optional[str] = None
-
sandbox_provider: Optional[str] = None
seats_override: Optional[int] = None
diff --git a/src/structify/types/team_update_params.py b/src/structify/types/team_update_params.py
index 3189391b3..cddb4155a 100644
--- a/src/structify/types/team_update_params.py
+++ b/src/structify/types/team_update_params.py
@@ -15,8 +15,6 @@ class TeamUpdateParams(TypedDict, total=False):
name: Optional[str]
- pipedream_project_id: Optional[str]
-
slack_bot_token: Optional[str]
slack_team_icon: Optional[str]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index c1cd9fe39..6557138cc 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -52,9 +52,6 @@ def test_method_create_with_all_params(self, client: Structify) -> None:
description="description",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
- pipedream_account_id="pipedream_account_id",
- pipedream_external_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- pipedream_project_id="pipedream_project_id",
refresh_script="refresh_script",
secrets={"foo": "string"},
)
@@ -1315,9 +1312,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncStructify)
description="description",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
- pipedream_account_id="pipedream_account_id",
- pipedream_external_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- pipedream_project_id="pipedream_project_id",
refresh_script="refresh_script",
secrets={"foo": "string"},
)
diff --git a/tests/api_resources/test_teams.py b/tests/api_resources/test_teams.py
index 07b5762b7..cc0ac93eb 100644
--- a/tests/api_resources/test_teams.py
+++ b/tests/api_resources/test_teams.py
@@ -89,7 +89,6 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
},
description="description",
name="name",
- pipedream_project_id="pipedream_project_id",
slack_bot_token="slack_bot_token",
slack_team_icon="slack_team_icon",
slack_team_id="slack_team_id",
@@ -744,7 +743,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
},
description="description",
name="name",
- pipedream_project_id="pipedream_project_id",
slack_bot_token="slack_bot_token",
slack_team_icon="slack_team_icon",
slack_team_id="slack_team_id",
From 04eadec50e082e5ce788917a4d7a7e916c4a6765 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Feb 2026 21:19:03 +0000
Subject: [PATCH 005/105] feat: Update from Structify backend changes
---
.stats.yml | 6 +-
api.md | 12 +-
src/structify/resources/admin/jobs.py | 162 ++++----
src/structify/resources/jobs.py | 141 ++-----
src/structify/types/__init__.py | 3 +-
src/structify/types/admin/__init__.py | 4 +-
.../types/admin/job_kill_by_user_params.py | 11 +
.../types/admin/job_kill_by_user_response.py | 9 +
src/structify/types/admin/job_list_params.py | 31 +-
..._jobs_response.py => job_list_response.py} | 17 +-
src/structify/types/job_get_response.py | 354 ++++++++++++++++++
.../types/job_get_scrapers_response.py | 34 --
.../types/job_get_source_entities_response.py | 170 ---------
tests/api_resources/admin/test_jobs.py | 133 ++++---
tests/api_resources/test_jobs.py | 167 +++------
15 files changed, 662 insertions(+), 592 deletions(-)
create mode 100644 src/structify/types/admin/job_kill_by_user_params.py
create mode 100644 src/structify/types/admin/job_kill_by_user_response.py
rename src/structify/types/admin/{admin_list_jobs_response.py => job_list_response.py} (93%)
create mode 100644 src/structify/types/job_get_response.py
delete mode 100644 src/structify/types/job_get_scrapers_response.py
delete mode 100644 src/structify/types/job_get_source_entities_response.py
diff --git a/.stats.yml b/.stats.yml
index ac3c9ed81..834a045e2 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-779ac9d3e3b624002e9371ec082c0382efbfcbfef3f4886686de3c78ed5f1aa6.yml
-openapi_spec_hash: d0c72e45260c840e533831c73c3c46d8
-config_hash: 165b687c958e22430204bd5ef9094d9a
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0b71726c36b64babf01c7f86080a45d2a17672098fa2f44401d9d1c9312de4f7.yml
+openapi_spec_hash: 79732aa3e2581721052dd6c1abd90d36
+config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/api.md b/api.md
index b4715b28a..7ccb63e42 100644
--- a/api.md
+++ b/api.md
@@ -319,14 +319,16 @@ from structify.types.admin import (
AdminDeleteJobsRequest,
AdminDeleteJobsResponse,
AdminListJobsRequestParams,
- AdminListJobsResponse,
+ JobListResponse,
+ JobKillByUserResponse,
)
```
Methods:
-- client.admin.jobs.list(\*\*params) -> SyncJobsList[AdminListJobsResponse]
+- client.admin.jobs.list(\*\*params) -> SyncJobsList[JobListResponse]
- client.admin.jobs.delete(\*\*params) -> AdminDeleteJobsResponse
+- client.admin.jobs.kill_by_user(\*\*params) -> JobKillByUserResponse
## Sandbox
@@ -503,8 +505,7 @@ from structify.types import (
GetJobEventsResponse,
JobListResponse,
JobCancelResponse,
- JobGetScrapersResponse,
- JobGetSourceEntitiesResponse,
+ JobGetResponse,
JobStatusResponse,
)
```
@@ -513,9 +514,8 @@ Methods:
- client.jobs.list(\*\*params) -> SyncJobsList[JobListResponse]
- client.jobs.cancel(uuid) -> JobCancelResponse
+- client.jobs.get(job_id) -> JobGetResponse
- client.jobs.get_events(job_id) -> GetJobEventsResponse
-- client.jobs.get_scrapers(job_id) -> JobGetScrapersResponse
-- client.jobs.get_source_entities(job_id) -> JobGetSourceEntitiesResponse
- client.jobs.schedule() -> None
- client.jobs.status(\*\*params) -> JobStatusResponse
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index 63173942d..91370faf3 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -2,8 +2,7 @@
from __future__ import annotations
-from typing import Union, Optional
-from datetime import datetime
+from typing import Optional
from typing_extensions import Literal
import httpx
@@ -19,9 +18,10 @@
async_to_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
-from ...types.admin import job_list_params, job_delete_params
+from ...types.admin import job_list_params, job_delete_params, job_kill_by_user_params
from ..._base_client import AsyncPaginator, make_request_options
-from ...types.admin.admin_list_jobs_response import AdminListJobsResponse
+from ...types.admin.job_list_response import JobListResponse
+from ...types.admin.job_kill_by_user_response import JobKillByUserResponse
from ...types.admin.admin_delete_jobs_response import AdminDeleteJobsResponse
__all__ = ["JobsResource", "AsyncJobsResource"]
@@ -50,41 +50,20 @@ def with_streaming_response(self) -> JobsResourceWithStreamingResponse:
def list(
self,
*,
- filter_test_users: bool,
- limit: int,
- offset: int,
- dataset_id: Optional[str] | Omit = omit,
- seeded_kg_search_term: Optional[str] | Omit = omit,
- since: Union[str, datetime, None] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ limit: int | Omit = omit,
+ offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
+ user_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.
# 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,
- ) -> SyncJobsList[AdminListJobsResponse]:
+ ) -> SyncJobsList[JobListResponse]:
"""
- This endpoint allows admins to list jobs from all users without user ownership
- restrictions. Optionally filter out test users (users with functional_test
- feature flag or debug permission).
-
Args:
- filter_test_users: Filter out jobs from test users (users with functional_test feature flag or
- debug permission)
-
- limit: Number of results to return
-
- offset: Pagination offset
-
- dataset_id: Dataset ID to optionally filter jobs by
-
- seeded_kg_search_term: Seeded kg search term
-
- since: List since a specific timestamp
-
- status: Status to optionally filter jobs by
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -95,7 +74,7 @@ def list(
"""
return self._get_api_list(
"/admin/jobs/list",
- page=SyncJobsList[AdminListJobsResponse],
+ page=SyncJobsList[JobListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -103,18 +82,16 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "filter_test_users": filter_test_users,
+ "job_type": job_type,
"limit": limit,
"offset": offset,
- "dataset_id": dataset_id,
- "seeded_kg_search_term": seeded_kg_search_term,
- "since": since,
"status": status,
+ "user_id": user_id,
},
job_list_params.JobListParams,
),
),
- model=AdminListJobsResponse,
+ model=JobListResponse,
)
def delete(
@@ -147,6 +124,36 @@ def delete(
cast_to=AdminDeleteJobsResponse,
)
+ def kill_by_user(
+ self,
+ *,
+ user_id: str,
+ # 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,
+ ) -> JobKillByUserResponse:
+ """
+ Args:
+ 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
+ """
+ return self._post(
+ "/admin/jobs/kill_by_user",
+ body=maybe_transform({"user_id": user_id}, job_kill_by_user_params.JobKillByUserParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobKillByUserResponse,
+ )
+
class AsyncJobsResource(AsyncAPIResource):
@cached_property
@@ -171,41 +178,20 @@ def with_streaming_response(self) -> AsyncJobsResourceWithStreamingResponse:
def list(
self,
*,
- filter_test_users: bool,
- limit: int,
- offset: int,
- dataset_id: Optional[str] | Omit = omit,
- seeded_kg_search_term: Optional[str] | Omit = omit,
- since: Union[str, datetime, None] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ limit: int | Omit = omit,
+ offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
+ user_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.
# 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,
- ) -> AsyncPaginator[AdminListJobsResponse, AsyncJobsList[AdminListJobsResponse]]:
+ ) -> AsyncPaginator[JobListResponse, AsyncJobsList[JobListResponse]]:
"""
- This endpoint allows admins to list jobs from all users without user ownership
- restrictions. Optionally filter out test users (users with functional_test
- feature flag or debug permission).
-
Args:
- filter_test_users: Filter out jobs from test users (users with functional_test feature flag or
- debug permission)
-
- limit: Number of results to return
-
- offset: Pagination offset
-
- dataset_id: Dataset ID to optionally filter jobs by
-
- seeded_kg_search_term: Seeded kg search term
-
- since: List since a specific timestamp
-
- status: Status to optionally filter jobs by
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -216,7 +202,7 @@ def list(
"""
return self._get_api_list(
"/admin/jobs/list",
- page=AsyncJobsList[AdminListJobsResponse],
+ page=AsyncJobsList[JobListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -224,18 +210,16 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "filter_test_users": filter_test_users,
+ "job_type": job_type,
"limit": limit,
"offset": offset,
- "dataset_id": dataset_id,
- "seeded_kg_search_term": seeded_kg_search_term,
- "since": since,
"status": status,
+ "user_id": user_id,
},
job_list_params.JobListParams,
),
),
- model=AdminListJobsResponse,
+ model=JobListResponse,
)
async def delete(
@@ -268,6 +252,36 @@ async def delete(
cast_to=AdminDeleteJobsResponse,
)
+ async def kill_by_user(
+ self,
+ *,
+ user_id: str,
+ # 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,
+ ) -> JobKillByUserResponse:
+ """
+ Args:
+ 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
+ """
+ return await self._post(
+ "/admin/jobs/kill_by_user",
+ body=await async_maybe_transform({"user_id": user_id}, job_kill_by_user_params.JobKillByUserParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobKillByUserResponse,
+ )
+
class JobsResourceWithRawResponse:
def __init__(self, jobs: JobsResource) -> None:
@@ -279,6 +293,9 @@ def __init__(self, jobs: JobsResource) -> None:
self.delete = to_raw_response_wrapper(
jobs.delete,
)
+ self.kill_by_user = to_raw_response_wrapper(
+ jobs.kill_by_user,
+ )
class AsyncJobsResourceWithRawResponse:
@@ -291,6 +308,9 @@ def __init__(self, jobs: AsyncJobsResource) -> None:
self.delete = async_to_raw_response_wrapper(
jobs.delete,
)
+ self.kill_by_user = async_to_raw_response_wrapper(
+ jobs.kill_by_user,
+ )
class JobsResourceWithStreamingResponse:
@@ -303,6 +323,9 @@ def __init__(self, jobs: JobsResource) -> None:
self.delete = to_streamed_response_wrapper(
jobs.delete,
)
+ self.kill_by_user = to_streamed_response_wrapper(
+ jobs.kill_by_user,
+ )
class AsyncJobsResourceWithStreamingResponse:
@@ -315,3 +338,6 @@ def __init__(self, jobs: AsyncJobsResource) -> None:
self.delete = async_to_streamed_response_wrapper(
jobs.delete,
)
+ self.kill_by_user = async_to_streamed_response_wrapper(
+ jobs.kill_by_user,
+ )
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index 974ece2ed..377bd22a2 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -23,12 +23,11 @@
)
from ..pagination import SyncJobsList, AsyncJobsList
from .._base_client import AsyncPaginator, make_request_options
+from ..types.job_get_response import JobGetResponse
from ..types.job_list_response import JobListResponse
from ..types.job_cancel_response import JobCancelResponse
from ..types.job_status_response import JobStatusResponse
from ..types.get_job_events_response import GetJobEventsResponse
-from ..types.job_get_scrapers_response import JobGetScrapersResponse
-from ..types.job_get_source_entities_response import JobGetSourceEntitiesResponse
__all__ = ["JobsResource", "AsyncJobsResource"]
@@ -153,7 +152,7 @@ def cancel(
cast_to=JobCancelResponse,
)
- def get_events(
+ def get(
self,
job_id: str,
*,
@@ -163,7 +162,7 @@ def get_events(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> GetJobEventsResponse:
+ ) -> JobGetResponse:
"""
Args:
extra_headers: Send extra headers
@@ -177,47 +176,14 @@ def get_events(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return self._get(
- f"/jobs/{job_id}/events",
+ f"/jobs/get/{job_id}",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=GetJobEventsResponse,
+ cast_to=JobGetResponse,
)
- def get_scrapers(
- self,
- job_id: str,
- *,
- # 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,
- ) -> JobGetScrapersResponse:
- """
- Retrieve scrapers associated with a job from structify.
-
- Args:
- 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
- """
- if not job_id:
- raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
- return self._get(
- f"/jobs/get_scrapers/{job_id}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=JobGetScrapersResponse,
- )
-
- def get_source_entities(
+ def get_events(
self,
job_id: str,
*,
@@ -227,10 +193,8 @@ def get_source_entities(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> JobGetSourceEntitiesResponse:
+ ) -> GetJobEventsResponse:
"""
- Get all source entities and their associated sources for a specific job
-
Args:
extra_headers: Send extra headers
@@ -243,11 +207,11 @@ def get_source_entities(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return self._get(
- f"/jobs/get_source_entities/{job_id}",
+ f"/jobs/{job_id}/events",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=JobGetSourceEntitiesResponse,
+ cast_to=GetJobEventsResponse,
)
def schedule(
@@ -506,38 +470,7 @@ async def cancel(
cast_to=JobCancelResponse,
)
- async def get_events(
- self,
- job_id: str,
- *,
- # 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,
- ) -> GetJobEventsResponse:
- """
- Args:
- 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
- """
- if not job_id:
- raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
- return await self._get(
- f"/jobs/{job_id}/events",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=GetJobEventsResponse,
- )
-
- async def get_scrapers(
+ async def get(
self,
job_id: str,
*,
@@ -547,10 +480,8 @@ async def get_scrapers(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> JobGetScrapersResponse:
+ ) -> JobGetResponse:
"""
- Retrieve scrapers associated with a job from structify.
-
Args:
extra_headers: Send extra headers
@@ -563,14 +494,14 @@ async def get_scrapers(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return await self._get(
- f"/jobs/get_scrapers/{job_id}",
+ f"/jobs/get/{job_id}",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=JobGetScrapersResponse,
+ cast_to=JobGetResponse,
)
- async def get_source_entities(
+ async def get_events(
self,
job_id: str,
*,
@@ -580,10 +511,8 @@ async def get_source_entities(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> JobGetSourceEntitiesResponse:
+ ) -> GetJobEventsResponse:
"""
- Get all source entities and their associated sources for a specific job
-
Args:
extra_headers: Send extra headers
@@ -596,11 +525,11 @@ async def get_source_entities(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return await self._get(
- f"/jobs/get_source_entities/{job_id}",
+ f"/jobs/{job_id}/events",
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=JobGetSourceEntitiesResponse,
+ cast_to=GetJobEventsResponse,
)
async def schedule(
@@ -682,15 +611,12 @@ def __init__(self, jobs: JobsResource) -> None:
self.cancel = to_raw_response_wrapper(
jobs.cancel,
)
+ self.get = to_raw_response_wrapper(
+ jobs.get,
+ )
self.get_events = to_raw_response_wrapper(
jobs.get_events,
)
- self.get_scrapers = to_raw_response_wrapper(
- jobs.get_scrapers,
- )
- self.get_source_entities = to_raw_response_wrapper(
- jobs.get_source_entities,
- )
self.schedule = to_raw_response_wrapper(
jobs.schedule,
)
@@ -712,15 +638,12 @@ def __init__(self, jobs: AsyncJobsResource) -> None:
self.cancel = async_to_raw_response_wrapper(
jobs.cancel,
)
+ self.get = async_to_raw_response_wrapper(
+ jobs.get,
+ )
self.get_events = async_to_raw_response_wrapper(
jobs.get_events,
)
- self.get_scrapers = async_to_raw_response_wrapper(
- jobs.get_scrapers,
- )
- self.get_source_entities = async_to_raw_response_wrapper(
- jobs.get_source_entities,
- )
self.schedule = async_to_raw_response_wrapper(
jobs.schedule,
)
@@ -739,15 +662,12 @@ def __init__(self, jobs: JobsResource) -> None:
self.cancel = to_streamed_response_wrapper(
jobs.cancel,
)
+ self.get = to_streamed_response_wrapper(
+ jobs.get,
+ )
self.get_events = to_streamed_response_wrapper(
jobs.get_events,
)
- self.get_scrapers = to_streamed_response_wrapper(
- jobs.get_scrapers,
- )
- self.get_source_entities = to_streamed_response_wrapper(
- jobs.get_source_entities,
- )
self.schedule = to_streamed_response_wrapper(
jobs.schedule,
)
@@ -769,15 +689,12 @@ def __init__(self, jobs: AsyncJobsResource) -> None:
self.cancel = async_to_streamed_response_wrapper(
jobs.cancel,
)
+ self.get = async_to_streamed_response_wrapper(
+ jobs.get,
+ )
self.get_events = async_to_streamed_response_wrapper(
jobs.get_events,
)
- self.get_scrapers = async_to_streamed_response_wrapper(
- jobs.get_scrapers,
- )
- self.get_source_entities = async_to_streamed_response_wrapper(
- jobs.get_source_entities,
- )
self.schedule = async_to_streamed_response_wrapper(
jobs.schedule,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 31412756e..34f1f8e84 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -50,6 +50,7 @@
from .tool_invocation import ToolInvocation as ToolInvocation
from .usage_group_key import UsageGroupKey as UsageGroupKey
from .chat_copy_params import ChatCopyParams as ChatCopyParams
+from .job_get_response import JobGetResponse as JobGetResponse
from .save_requirement import SaveRequirement as SaveRequirement
from .workflow_session import WorkflowSession as WorkflowSession
from .chat_session_role import ChatSessionRole as ChatSessionRole
@@ -188,7 +189,6 @@
from .exploration_runs_response import ExplorationRunsResponse as ExplorationRunsResponse
from .get_chat_session_response import GetChatSessionResponse as GetChatSessionResponse
from .get_dependencies_response import GetDependenciesResponse as GetDependenciesResponse
-from .job_get_scrapers_response import JobGetScrapersResponse as JobGetScrapersResponse
from .match_list_results_params import MatchListResultsParams as MatchListResultsParams
from .session_get_events_params import SessionGetEventsParams as SessionGetEventsParams
from .slack_event_payload_param import SlackEventPayloadParam as SlackEventPayloadParam
@@ -282,7 +282,6 @@
from .connector_search_tables_response import ConnectorSearchTablesResponse as ConnectorSearchTablesResponse
from .entity_add_relationship_response import EntityAddRelationshipResponse as EntityAddRelationshipResponse
from .entity_get_local_subgraph_params import EntityGetLocalSubgraphParams as EntityGetLocalSubgraphParams
-from .job_get_source_entities_response import JobGetSourceEntitiesResponse as JobGetSourceEntitiesResponse
from .nango_list_integrations_response import NangoListIntegrationsResponse as NangoListIntegrationsResponse
from .project_collaborator_input_param import ProjectCollaboratorInputParam as ProjectCollaboratorInputParam
from .connector_auth_method_with_fields import ConnectorAuthMethodWithFields as ConnectorAuthMethodWithFields
diff --git a/src/structify/types/admin/__init__.py b/src/structify/types/admin/__init__.py
index 5fa1433e9..6745f1848 100644
--- a/src/structify/types/admin/__init__.py
+++ b/src/structify/types/admin/__init__.py
@@ -7,6 +7,7 @@
from .job_list_params import JobListParams as JobListParams
from .team_list_params import TeamListParams as TeamListParams
from .job_delete_params import JobDeleteParams as JobDeleteParams
+from .job_list_response import JobListResponse as JobListResponse
from .user_create_params import UserCreateParams as UserCreateParams
from .user_list_response import UserListResponse as UserListResponse
from .sandbox_list_params import SandboxListParams as SandboxListParams
@@ -18,15 +19,16 @@
from .expire_grants_response import ExpireGrantsResponse as ExpireGrantsResponse
from .grant_credits_response import GrantCreditsResponse as GrantCreditsResponse
from .team_add_member_params import TeamAddMemberParams as TeamAddMemberParams
+from .job_kill_by_user_params import JobKillByUserParams as JobKillByUserParams
from .user_get_stats_response import UserGetStatsResponse as UserGetStatsResponse
from .user_impersonate_params import UserImpersonateParams as UserImpersonateParams
-from .admin_list_jobs_response import AdminListJobsResponse as AdminListJobsResponse
from .dataset_get_by_id_params import DatasetGetByIDParams as DatasetGetByIDParams
from .team_extend_trial_params import TeamExtendTrialParams as TeamExtendTrialParams
from .admin_add_member_response import AdminAddMemberResponse as AdminAddMemberResponse
from .admin_teams_list_response import AdminTeamsListResponse as AdminTeamsListResponse
from .chat_template_list_params import ChatTemplateListParams as ChatTemplateListParams
from .clone_connectors_response import CloneConnectorsResponse as CloneConnectorsResponse
+from .job_kill_by_user_response import JobKillByUserResponse as JobKillByUserResponse
from .team_expire_grants_params import TeamExpireGrantsParams as TeamExpireGrantsParams
from .team_grant_credits_params import TeamGrantCreditsParams as TeamGrantCreditsParams
from .team_remove_member_params import TeamRemoveMemberParams as TeamRemoveMemberParams
diff --git a/src/structify/types/admin/job_kill_by_user_params.py b/src/structify/types/admin/job_kill_by_user_params.py
new file mode 100644
index 000000000..26dc2f804
--- /dev/null
+++ b/src/structify/types/admin/job_kill_by_user_params.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["JobKillByUserParams"]
+
+
+class JobKillByUserParams(TypedDict, total=False):
+ user_id: Required[str]
diff --git a/src/structify/types/admin/job_kill_by_user_response.py b/src/structify/types/admin/job_kill_by_user_response.py
new file mode 100644
index 000000000..3754fe457
--- /dev/null
+++ b/src/structify/types/admin/job_kill_by_user_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from ..._models import BaseModel
+
+__all__ = ["JobKillByUserResponse"]
+
+
+class JobKillByUserResponse(BaseModel):
+ killed_jobs: int
diff --git a/src/structify/types/admin/job_list_params.py b/src/structify/types/admin/job_list_params.py
index 150217f76..cb290ca95 100644
--- a/src/structify/types/admin/job_list_params.py
+++ b/src/structify/types/admin/job_list_params.py
@@ -2,36 +2,19 @@
from __future__ import annotations
-from typing import Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, Required, Annotated, TypedDict
-
-from ..._utils import PropertyInfo
+from typing import Optional
+from typing_extensions import Literal, TypedDict
__all__ = ["JobListParams"]
class JobListParams(TypedDict, total=False):
- filter_test_users: Required[bool]
- """
- Filter out jobs from test users (users with functional_test feature flag or
- debug permission)
- """
-
- limit: Required[int]
- """Number of results to return"""
-
- offset: Required[int]
- """Pagination offset"""
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
- dataset_id: Optional[str]
- """Dataset ID to optionally filter jobs by"""
+ limit: int
- seeded_kg_search_term: Optional[str]
- """Seeded kg search term"""
-
- since: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
- """List since a specific timestamp"""
+ offset: int
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]]
- """Status to optionally filter jobs by"""
+
+ user_id: Optional[str]
diff --git a/src/structify/types/admin/admin_list_jobs_response.py b/src/structify/types/admin/job_list_response.py
similarity index 93%
rename from src/structify/types/admin/admin_list_jobs_response.py
rename to src/structify/types/admin/job_list_response.py
index eb52fa0f0..f7cad37fe 100644
--- a/src/structify/types/admin/admin_list_jobs_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -1,6 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import List, Union, Optional
+from datetime import datetime
from typing_extensions import Literal, TypeAlias
from pydantic import Field as FieldInfo
@@ -11,7 +12,7 @@
from ..exploration_phase_id import ExplorationPhaseID
__all__ = [
- "AdminListJobsResponse",
+ "JobListResponse",
"Parameters",
"ParametersStructuringInput",
"ParametersStructuringInputAgent",
@@ -144,9 +145,11 @@ class Parameters(BaseModel):
model: Optional[str] = None
-class AdminListJobsResponse(BaseModel):
+class JobListResponse(BaseModel):
id: str
+ created_at: datetime
+
dataset_id: str
job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
@@ -155,4 +158,14 @@ class AdminListJobsResponse(BaseModel):
user_id: str
+ message: Optional[str] = None
+
parameters: Optional[Parameters] = None
+
+ reason: Optional[str] = None
+
+ run_started_time: Optional[datetime] = None
+
+ run_time_milliseconds: Optional[int] = None
+
+ special_job_type: Optional[Literal["HumanLLM"]] = None
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
new file mode 100644
index 000000000..80b9978ce
--- /dev/null
+++ b/src/structify/types/job_get_response.py
@@ -0,0 +1,354 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List, Union, Optional
+from datetime import datetime
+from typing_extensions import Literal, TypeAlias
+
+from pydantic import Field as FieldInfo
+
+from .image import Image
+from .source import Source
+from .._models import BaseModel
+from .chat_event import ChatEvent
+from .chat_prompt import ChatPrompt
+from .knowledge_graph import KnowledgeGraph
+from .save_requirement import SaveRequirement
+from .exploration_phase_id import ExplorationPhaseID
+
+__all__ = [
+ "JobGetResponse",
+ "Agent",
+ "Info",
+ "InfoParameters",
+ "InfoParametersStructuringInput",
+ "InfoParametersStructuringInputAgent",
+ "InfoParametersStructuringInputAgentAgent",
+ "InfoParametersStructuringInputAgentAgentPdf",
+ "InfoParametersStructuringInputAgentAgentPdfPdf",
+ "InfoParametersStructuringInputAgentAgentWeb",
+ "InfoParametersStructuringInputAgentAgentWebWeb",
+ "InfoParametersStructuringInputTransformationPrompt",
+ "InfoParametersStructuringInputScrapeFromURLProperty",
+ "InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
+ "InfoParametersStructuringInputScrapeURL",
+ "InfoParametersStructuringInputScrapeURLScrapeURL",
+ "InfoParametersStructuringInputConnectorExploration",
+ "InfoParametersStructuringInputConnectorExplorationConnectorExploration",
+ "Saved",
+ "SavedProperties",
+ "SavedPropertiesPartialDateObject",
+ "SavedPropertiesURLObject",
+ "SavedPropertiesMoneyObject",
+ "SavedPropertiesPersonName",
+ "SavedPropertiesAddressObject",
+ "SavedLocation",
+ "SavedLocationText",
+ "SavedLocationTextText",
+ "SavedLocationVisual",
+ "SavedLocationVisualVisual",
+ "SavedLocationPage",
+ "SavedLocationPagePage",
+]
+
+
+class Agent(BaseModel):
+ base_url: str
+
+ is_newly_created: bool
+
+ scraper_created_at: datetime
+
+ scraper_id: str
+
+ scraper_updated_at: datetime
+
+ chat: Optional[ChatPrompt] = None
+
+ code: Optional[str] = None
+
+ events: Optional[List[ChatEvent]] = None
+
+ next_page_code: Optional[str] = None
+
+
+class InfoParametersStructuringInputAgentAgentPdfPdf(BaseModel):
+ """Ingest all pages of a PDF and process them independently."""
+
+ path: str
+
+ page: Optional[int] = None
+
+
+class InfoParametersStructuringInputAgentAgentPdf(BaseModel):
+ pdf: InfoParametersStructuringInputAgentAgentPdfPdf = FieldInfo(alias="PDF")
+ """Ingest all pages of a PDF and process them independently."""
+
+
+class InfoParametersStructuringInputAgentAgentWebWeb(BaseModel):
+ banned_domains: Optional[List[str]] = None
+
+ starting_searches: Optional[List[str]] = None
+
+ starting_urls: Optional[List[str]] = None
+
+
+class InfoParametersStructuringInputAgentAgentWeb(BaseModel):
+ web: InfoParametersStructuringInputAgentAgentWebWeb = FieldInfo(alias="Web")
+
+
+InfoParametersStructuringInputAgentAgent: TypeAlias = Union[
+ InfoParametersStructuringInputAgentAgentPdf, InfoParametersStructuringInputAgentAgentWeb
+]
+
+
+class InfoParametersStructuringInputAgent(BaseModel):
+ agent: InfoParametersStructuringInputAgentAgent = FieldInfo(alias="Agent")
+
+
+class InfoParametersStructuringInputTransformationPrompt(BaseModel):
+ transformation_prompt: str = FieldInfo(alias="TransformationPrompt")
+
+
+class InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty(BaseModel):
+ batch_scrape: bool
+
+ url_property_name: str
+
+ use_markdown: bool
+
+
+class InfoParametersStructuringInputScrapeFromURLProperty(BaseModel):
+ scrape_from_url_property: InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty = FieldInfo(
+ alias="ScrapeFromUrlProperty"
+ )
+
+
+class InfoParametersStructuringInputScrapeURLScrapeURL(BaseModel):
+ batch_scrape: bool
+
+ url: str
+
+ use_markdown: bool
+
+
+class InfoParametersStructuringInputScrapeURL(BaseModel):
+ scrape_url: InfoParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+
+
+class InfoParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
+ connector_id: str
+
+ exploration_phase_id: ExplorationPhaseID
+ """Identifies the phase of connector exploration
+
+ This enum is used to track which phase of exploration a chat session belongs to.
+ It's stored as JSONB in the database to allow for flexible phase identification.
+ """
+
+ exploration_run_id: str
+
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
+
+
+class InfoParametersStructuringInputConnectorExploration(BaseModel):
+ connector_exploration: InfoParametersStructuringInputConnectorExplorationConnectorExploration = FieldInfo(
+ alias="ConnectorExploration"
+ )
+
+
+InfoParametersStructuringInput: TypeAlias = Union[
+ InfoParametersStructuringInputAgent,
+ InfoParametersStructuringInputTransformationPrompt,
+ InfoParametersStructuringInputScrapeFromURLProperty,
+ InfoParametersStructuringInputScrapeURL,
+ InfoParametersStructuringInputConnectorExploration,
+]
+
+
+class InfoParameters(BaseModel):
+ allow_extra_entities: bool
+
+ extraction_criteria: List[SaveRequirement]
+
+ seeded_kg: KnowledgeGraph
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
+ structuring_input: InfoParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
+
+class Info(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+
+ status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ user_id: str
+
+ message: Optional[str] = None
+
+ parameters: Optional[InfoParameters] = None
+
+ reason: Optional[str] = None
+
+ run_started_time: Optional[datetime] = None
+
+ run_time_milliseconds: Optional[int] = None
+
+ special_job_type: Optional[Literal["HumanLLM"]] = None
+
+
+class SavedPropertiesPartialDateObject(BaseModel):
+ original_string: str
+
+ year: int
+
+ day: Optional[int] = None
+
+ month: Optional[int] = None
+
+
+class SavedPropertiesURLObject(BaseModel):
+ original_string: str
+
+ url: str
+
+
+class SavedPropertiesMoneyObject(BaseModel):
+ amount: float
+
+ currency_code: Literal[
+ "USD",
+ "EUR",
+ "GBP",
+ "JPY",
+ "CNY",
+ "INR",
+ "RUB",
+ "CAD",
+ "AUD",
+ "CHF",
+ "ILS",
+ "NZD",
+ "SGD",
+ "HKD",
+ "NOK",
+ "SEK",
+ "PLN",
+ "TRY",
+ "DKK",
+ "MXN",
+ "ZAR",
+ "PHP",
+ "VND",
+ "THB",
+ "BRL",
+ "KRW",
+ ]
+
+ original_string: str
+
+
+class SavedPropertiesPersonName(BaseModel):
+ name: str
+
+
+class SavedPropertiesAddressObject(BaseModel):
+ components: Dict[str, str]
+
+ original_address: str
+
+
+SavedProperties: TypeAlias = Union[
+ str,
+ bool,
+ float,
+ SavedPropertiesPartialDateObject,
+ str,
+ str,
+ SavedPropertiesURLObject,
+ str,
+ SavedPropertiesMoneyObject,
+ Image,
+ SavedPropertiesPersonName,
+ SavedPropertiesAddressObject,
+ str,
+]
+
+
+class SavedLocationTextText(BaseModel):
+ byte_offset: int
+
+
+class SavedLocationText(BaseModel):
+ text: SavedLocationTextText = FieldInfo(alias="Text")
+
+
+class SavedLocationVisualVisual(BaseModel):
+ x: int
+
+ y: int
+
+
+class SavedLocationVisual(BaseModel):
+ visual: SavedLocationVisualVisual = FieldInfo(alias="Visual")
+
+
+class SavedLocationPagePage(BaseModel):
+ page_number: int
+
+
+class SavedLocationPage(BaseModel):
+ page: SavedLocationPagePage = FieldInfo(alias="Page")
+
+
+SavedLocation: TypeAlias = Union[SavedLocationText, SavedLocationVisual, SavedLocationPage, None]
+
+
+class Saved(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ is_summary: bool
+
+ label: str
+
+ llm_id: int
+
+ properties: Dict[str, SavedProperties]
+
+ source_id: str
+
+ user_specified: bool
+
+ job_id: Optional[str] = None
+
+ kg_entity_id: Optional[str] = None
+
+ link: Optional[Source] = None
+
+ location: Optional[SavedLocation] = None
+
+ scraper_id: Optional[str] = None
+
+
+class JobGetResponse(BaseModel):
+ agents: List[Agent]
+
+ info: Info
+
+ saved: List[List[Saved]]
diff --git a/src/structify/types/job_get_scrapers_response.py b/src/structify/types/job_get_scrapers_response.py
deleted file mode 100644
index d22f6a616..000000000
--- a/src/structify/types/job_get_scrapers_response.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# 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 TypeAlias
-
-from .._models import BaseModel
-from .chat_event import ChatEvent
-from .chat_prompt import ChatPrompt
-
-__all__ = ["JobGetScrapersResponse", "JobGetScrapersResponseItem"]
-
-
-class JobGetScrapersResponseItem(BaseModel):
- base_url: str
-
- is_newly_created: bool
-
- scraper_created_at: datetime
-
- scraper_id: str
-
- scraper_updated_at: datetime
-
- chat: Optional[ChatPrompt] = None
-
- code: Optional[str] = None
-
- events: Optional[List[ChatEvent]] = None
-
- next_page_code: Optional[str] = None
-
-
-JobGetScrapersResponse: TypeAlias = List[JobGetScrapersResponseItem]
diff --git a/src/structify/types/job_get_source_entities_response.py b/src/structify/types/job_get_source_entities_response.py
deleted file mode 100644
index a43f7932b..000000000
--- a/src/structify/types/job_get_source_entities_response.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Dict, List, Union, Optional
-from datetime import datetime
-from typing_extensions import Literal, TypeAlias
-
-from pydantic import Field as FieldInfo
-
-from .image import Image
-from .source import Source
-from .._models import BaseModel
-
-__all__ = [
- "JobGetSourceEntitiesResponse",
- "SourceEntity",
- "SourceEntityProperties",
- "SourceEntityPropertiesPartialDateObject",
- "SourceEntityPropertiesURLObject",
- "SourceEntityPropertiesMoneyObject",
- "SourceEntityPropertiesPersonName",
- "SourceEntityPropertiesAddressObject",
- "SourceEntityLocation",
- "SourceEntityLocationText",
- "SourceEntityLocationTextText",
- "SourceEntityLocationVisual",
- "SourceEntityLocationVisualVisual",
- "SourceEntityLocationPage",
- "SourceEntityLocationPagePage",
-]
-
-
-class SourceEntityPropertiesPartialDateObject(BaseModel):
- original_string: str
-
- year: int
-
- day: Optional[int] = None
-
- month: Optional[int] = None
-
-
-class SourceEntityPropertiesURLObject(BaseModel):
- original_string: str
-
- url: str
-
-
-class SourceEntityPropertiesMoneyObject(BaseModel):
- amount: float
-
- currency_code: Literal[
- "USD",
- "EUR",
- "GBP",
- "JPY",
- "CNY",
- "INR",
- "RUB",
- "CAD",
- "AUD",
- "CHF",
- "ILS",
- "NZD",
- "SGD",
- "HKD",
- "NOK",
- "SEK",
- "PLN",
- "TRY",
- "DKK",
- "MXN",
- "ZAR",
- "PHP",
- "VND",
- "THB",
- "BRL",
- "KRW",
- ]
-
- original_string: str
-
-
-class SourceEntityPropertiesPersonName(BaseModel):
- name: str
-
-
-class SourceEntityPropertiesAddressObject(BaseModel):
- components: Dict[str, str]
-
- original_address: str
-
-
-SourceEntityProperties: TypeAlias = Union[
- str,
- bool,
- float,
- SourceEntityPropertiesPartialDateObject,
- str,
- str,
- SourceEntityPropertiesURLObject,
- str,
- SourceEntityPropertiesMoneyObject,
- Image,
- SourceEntityPropertiesPersonName,
- SourceEntityPropertiesAddressObject,
- str,
-]
-
-
-class SourceEntityLocationTextText(BaseModel):
- byte_offset: int
-
-
-class SourceEntityLocationText(BaseModel):
- text: SourceEntityLocationTextText = FieldInfo(alias="Text")
-
-
-class SourceEntityLocationVisualVisual(BaseModel):
- x: int
-
- y: int
-
-
-class SourceEntityLocationVisual(BaseModel):
- visual: SourceEntityLocationVisualVisual = FieldInfo(alias="Visual")
-
-
-class SourceEntityLocationPagePage(BaseModel):
- page_number: int
-
-
-class SourceEntityLocationPage(BaseModel):
- page: SourceEntityLocationPagePage = FieldInfo(alias="Page")
-
-
-SourceEntityLocation: TypeAlias = Union[
- SourceEntityLocationText, SourceEntityLocationVisual, SourceEntityLocationPage, None
-]
-
-
-class SourceEntity(BaseModel):
- id: str
-
- created_at: datetime
-
- is_summary: bool
-
- label: str
-
- llm_id: int
-
- properties: Dict[str, SourceEntityProperties]
-
- source_id: str
-
- user_specified: bool
-
- job_id: Optional[str] = None
-
- kg_entity_id: Optional[str] = None
-
- link: Optional[Source] = None
-
- location: Optional[SourceEntityLocation] = None
-
- scraper_id: Optional[str] = None
-
-
-class JobGetSourceEntitiesResponse(BaseModel):
- source_entities: List[List[SourceEntity]]
diff --git a/tests/api_resources/admin/test_jobs.py b/tests/api_resources/admin/test_jobs.py
index bfc2d0cea..ac3210575 100644
--- a/tests/api_resources/admin/test_jobs.py
+++ b/tests/api_resources/admin/test_jobs.py
@@ -9,9 +9,12 @@
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
-from structify._utils import parse_datetime
from structify.pagination import SyncJobsList, AsyncJobsList
-from structify.types.admin import AdminListJobsResponse, AdminDeleteJobsResponse
+from structify.types.admin import (
+ JobListResponse,
+ JobKillByUserResponse,
+ AdminDeleteJobsResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -21,51 +24,37 @@ class TestJobs:
@parametrize
def test_method_list(self, client: Structify) -> None:
- job = client.admin.jobs.list(
- filter_test_users=True,
- limit=0,
- offset=0,
- )
- assert_matches_type(SyncJobsList[AdminListJobsResponse], job, path=["response"])
+ job = client.admin.jobs.list()
+ assert_matches_type(SyncJobsList[JobListResponse], job, path=["response"])
@parametrize
def test_method_list_with_all_params(self, client: Structify) -> None:
job = client.admin.jobs.list(
- filter_test_users=True,
+ job_type="Web",
limit=0,
offset=0,
- dataset_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- seeded_kg_search_term="seeded_kg_search_term",
- since=parse_datetime("2019-12-27T18:11:19.117Z"),
status="Queued",
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(SyncJobsList[AdminListJobsResponse], job, path=["response"])
+ assert_matches_type(SyncJobsList[JobListResponse], job, path=["response"])
@parametrize
def test_raw_response_list(self, client: Structify) -> None:
- response = client.admin.jobs.with_raw_response.list(
- filter_test_users=True,
- limit=0,
- offset=0,
- )
+ response = client.admin.jobs.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = response.parse()
- assert_matches_type(SyncJobsList[AdminListJobsResponse], job, path=["response"])
+ assert_matches_type(SyncJobsList[JobListResponse], job, path=["response"])
@parametrize
def test_streaming_response_list(self, client: Structify) -> None:
- with client.admin.jobs.with_streaming_response.list(
- filter_test_users=True,
- limit=0,
- offset=0,
- ) as response:
+ with client.admin.jobs.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = response.parse()
- assert_matches_type(SyncJobsList[AdminListJobsResponse], job, path=["response"])
+ assert_matches_type(SyncJobsList[JobListResponse], job, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -100,6 +89,37 @@ def test_streaming_response_delete(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_kill_by_user(self, client: Structify) -> None:
+ job = client.admin.jobs.kill_by_user(
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(JobKillByUserResponse, job, path=["response"])
+
+ @parametrize
+ def test_raw_response_kill_by_user(self, client: Structify) -> None:
+ response = client.admin.jobs.with_raw_response.kill_by_user(
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = response.parse()
+ assert_matches_type(JobKillByUserResponse, job, path=["response"])
+
+ @parametrize
+ def test_streaming_response_kill_by_user(self, client: Structify) -> None:
+ with client.admin.jobs.with_streaming_response.kill_by_user(
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = response.parse()
+ assert_matches_type(JobKillByUserResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncJobs:
parametrize = pytest.mark.parametrize(
@@ -108,51 +128,37 @@ class TestAsyncJobs:
@parametrize
async def test_method_list(self, async_client: AsyncStructify) -> None:
- job = await async_client.admin.jobs.list(
- filter_test_users=True,
- limit=0,
- offset=0,
- )
- assert_matches_type(AsyncJobsList[AdminListJobsResponse], job, path=["response"])
+ job = await async_client.admin.jobs.list()
+ assert_matches_type(AsyncJobsList[JobListResponse], job, path=["response"])
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncStructify) -> None:
job = await async_client.admin.jobs.list(
- filter_test_users=True,
+ job_type="Web",
limit=0,
offset=0,
- dataset_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- seeded_kg_search_term="seeded_kg_search_term",
- since=parse_datetime("2019-12-27T18:11:19.117Z"),
status="Queued",
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(AsyncJobsList[AdminListJobsResponse], job, path=["response"])
+ assert_matches_type(AsyncJobsList[JobListResponse], job, path=["response"])
@parametrize
async def test_raw_response_list(self, async_client: AsyncStructify) -> None:
- response = await async_client.admin.jobs.with_raw_response.list(
- filter_test_users=True,
- limit=0,
- offset=0,
- )
+ response = await async_client.admin.jobs.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = await response.parse()
- assert_matches_type(AsyncJobsList[AdminListJobsResponse], job, path=["response"])
+ assert_matches_type(AsyncJobsList[JobListResponse], job, path=["response"])
@parametrize
async def test_streaming_response_list(self, async_client: AsyncStructify) -> None:
- async with async_client.admin.jobs.with_streaming_response.list(
- filter_test_users=True,
- limit=0,
- offset=0,
- ) as response:
+ async with async_client.admin.jobs.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = await response.parse()
- assert_matches_type(AsyncJobsList[AdminListJobsResponse], job, path=["response"])
+ assert_matches_type(AsyncJobsList[JobListResponse], job, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -186,3 +192,34 @@ async def test_streaming_response_delete(self, async_client: AsyncStructify) ->
assert_matches_type(AdminDeleteJobsResponse, job, path=["response"])
assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_kill_by_user(self, async_client: AsyncStructify) -> None:
+ job = await async_client.admin.jobs.kill_by_user(
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(JobKillByUserResponse, job, path=["response"])
+
+ @parametrize
+ async def test_raw_response_kill_by_user(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.jobs.with_raw_response.kill_by_user(
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = await response.parse()
+ assert_matches_type(JobKillByUserResponse, job, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_kill_by_user(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.jobs.with_streaming_response.kill_by_user(
+ user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = await response.parse()
+ assert_matches_type(JobKillByUserResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_jobs.py b/tests/api_resources/test_jobs.py
index 5db5dbf6f..e3119fd98 100644
--- a/tests/api_resources/test_jobs.py
+++ b/tests/api_resources/test_jobs.py
@@ -10,12 +10,11 @@
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
from structify.types import (
+ JobGetResponse,
JobListResponse,
JobCancelResponse,
JobStatusResponse,
GetJobEventsResponse,
- JobGetScrapersResponse,
- JobGetSourceEntitiesResponse,
)
from structify._utils import parse_datetime
from structify.pagination import SyncJobsList, AsyncJobsList
@@ -104,116 +103,78 @@ def test_path_params_cancel(self, client: Structify) -> None:
)
@parametrize
- def test_method_get_events(self, client: Structify) -> None:
- job = client.jobs.get_events(
+ def test_method_get(self, client: Structify) -> None:
+ job = client.jobs.get(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(GetJobEventsResponse, job, path=["response"])
+ assert_matches_type(JobGetResponse, job, path=["response"])
@parametrize
- def test_raw_response_get_events(self, client: Structify) -> None:
- response = client.jobs.with_raw_response.get_events(
+ def test_raw_response_get(self, client: Structify) -> None:
+ response = client.jobs.with_raw_response.get(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = response.parse()
- assert_matches_type(GetJobEventsResponse, job, path=["response"])
+ assert_matches_type(JobGetResponse, job, path=["response"])
@parametrize
- def test_streaming_response_get_events(self, client: Structify) -> None:
- with client.jobs.with_streaming_response.get_events(
+ def test_streaming_response_get(self, client: Structify) -> None:
+ with client.jobs.with_streaming_response.get(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = response.parse()
- assert_matches_type(GetJobEventsResponse, job, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_get_events(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"):
- client.jobs.with_raw_response.get_events(
- "",
- )
-
- @parametrize
- def test_method_get_scrapers(self, client: Structify) -> None:
- job = client.jobs.get_scrapers(
- "job_id",
- )
- assert_matches_type(JobGetScrapersResponse, job, path=["response"])
-
- @parametrize
- def test_raw_response_get_scrapers(self, client: Structify) -> None:
- response = client.jobs.with_raw_response.get_scrapers(
- "job_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- job = response.parse()
- assert_matches_type(JobGetScrapersResponse, job, path=["response"])
-
- @parametrize
- def test_streaming_response_get_scrapers(self, client: Structify) -> None:
- with client.jobs.with_streaming_response.get_scrapers(
- "job_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- job = response.parse()
- assert_matches_type(JobGetScrapersResponse, job, path=["response"])
+ assert_matches_type(JobGetResponse, job, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_get_scrapers(self, client: Structify) -> None:
+ def test_path_params_get(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"):
- client.jobs.with_raw_response.get_scrapers(
+ client.jobs.with_raw_response.get(
"",
)
@parametrize
- def test_method_get_source_entities(self, client: Structify) -> None:
- job = client.jobs.get_source_entities(
+ def test_method_get_events(self, client: Structify) -> None:
+ job = client.jobs.get_events(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(JobGetSourceEntitiesResponse, job, path=["response"])
+ assert_matches_type(GetJobEventsResponse, job, path=["response"])
@parametrize
- def test_raw_response_get_source_entities(self, client: Structify) -> None:
- response = client.jobs.with_raw_response.get_source_entities(
+ def test_raw_response_get_events(self, client: Structify) -> None:
+ response = client.jobs.with_raw_response.get_events(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = response.parse()
- assert_matches_type(JobGetSourceEntitiesResponse, job, path=["response"])
+ assert_matches_type(GetJobEventsResponse, job, path=["response"])
@parametrize
- def test_streaming_response_get_source_entities(self, client: Structify) -> None:
- with client.jobs.with_streaming_response.get_source_entities(
+ def test_streaming_response_get_events(self, client: Structify) -> None:
+ with client.jobs.with_streaming_response.get_events(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = response.parse()
- assert_matches_type(JobGetSourceEntitiesResponse, job, path=["response"])
+ assert_matches_type(GetJobEventsResponse, job, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_get_source_entities(self, client: Structify) -> None:
+ def test_path_params_get_events(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"):
- client.jobs.with_raw_response.get_source_entities(
+ client.jobs.with_raw_response.get_events(
"",
)
@@ -360,116 +321,78 @@ async def test_path_params_cancel(self, async_client: AsyncStructify) -> None:
)
@parametrize
- async def test_method_get_events(self, async_client: AsyncStructify) -> None:
- job = await async_client.jobs.get_events(
+ async def test_method_get(self, async_client: AsyncStructify) -> None:
+ job = await async_client.jobs.get(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(GetJobEventsResponse, job, path=["response"])
+ assert_matches_type(JobGetResponse, job, path=["response"])
@parametrize
- async def test_raw_response_get_events(self, async_client: AsyncStructify) -> None:
- response = await async_client.jobs.with_raw_response.get_events(
+ async def test_raw_response_get(self, async_client: AsyncStructify) -> None:
+ response = await async_client.jobs.with_raw_response.get(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = await response.parse()
- assert_matches_type(GetJobEventsResponse, job, path=["response"])
+ assert_matches_type(JobGetResponse, job, path=["response"])
@parametrize
- async def test_streaming_response_get_events(self, async_client: AsyncStructify) -> None:
- async with async_client.jobs.with_streaming_response.get_events(
+ async def test_streaming_response_get(self, async_client: AsyncStructify) -> None:
+ async with async_client.jobs.with_streaming_response.get(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = await response.parse()
- assert_matches_type(GetJobEventsResponse, job, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_get_events(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"):
- await async_client.jobs.with_raw_response.get_events(
- "",
- )
-
- @parametrize
- async def test_method_get_scrapers(self, async_client: AsyncStructify) -> None:
- job = await async_client.jobs.get_scrapers(
- "job_id",
- )
- assert_matches_type(JobGetScrapersResponse, job, path=["response"])
-
- @parametrize
- async def test_raw_response_get_scrapers(self, async_client: AsyncStructify) -> None:
- response = await async_client.jobs.with_raw_response.get_scrapers(
- "job_id",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- job = await response.parse()
- assert_matches_type(JobGetScrapersResponse, job, path=["response"])
-
- @parametrize
- async def test_streaming_response_get_scrapers(self, async_client: AsyncStructify) -> None:
- async with async_client.jobs.with_streaming_response.get_scrapers(
- "job_id",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- job = await response.parse()
- assert_matches_type(JobGetScrapersResponse, job, path=["response"])
+ assert_matches_type(JobGetResponse, job, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_get_scrapers(self, async_client: AsyncStructify) -> None:
+ async def test_path_params_get(self, async_client: AsyncStructify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"):
- await async_client.jobs.with_raw_response.get_scrapers(
+ await async_client.jobs.with_raw_response.get(
"",
)
@parametrize
- async def test_method_get_source_entities(self, async_client: AsyncStructify) -> None:
- job = await async_client.jobs.get_source_entities(
+ async def test_method_get_events(self, async_client: AsyncStructify) -> None:
+ job = await async_client.jobs.get_events(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(JobGetSourceEntitiesResponse, job, path=["response"])
+ assert_matches_type(GetJobEventsResponse, job, path=["response"])
@parametrize
- async def test_raw_response_get_source_entities(self, async_client: AsyncStructify) -> None:
- response = await async_client.jobs.with_raw_response.get_source_entities(
+ async def test_raw_response_get_events(self, async_client: AsyncStructify) -> None:
+ response = await async_client.jobs.with_raw_response.get_events(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = await response.parse()
- assert_matches_type(JobGetSourceEntitiesResponse, job, path=["response"])
+ assert_matches_type(GetJobEventsResponse, job, path=["response"])
@parametrize
- async def test_streaming_response_get_source_entities(self, async_client: AsyncStructify) -> None:
- async with async_client.jobs.with_streaming_response.get_source_entities(
+ async def test_streaming_response_get_events(self, async_client: AsyncStructify) -> None:
+ async with async_client.jobs.with_streaming_response.get_events(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
job = await response.parse()
- assert_matches_type(JobGetSourceEntitiesResponse, job, path=["response"])
+ assert_matches_type(GetJobEventsResponse, job, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_get_source_entities(self, async_client: AsyncStructify) -> None:
+ async def test_path_params_get_events(self, async_client: AsyncStructify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `job_id` but received ''"):
- await async_client.jobs.with_raw_response.get_source_entities(
+ await async_client.jobs.with_raw_response.get_events(
"",
)
From 454d1ddd7f12b025bb552850da43d381f702fb55 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 00:31:19 +0000
Subject: [PATCH 006/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connectors/connectors.py | 8 --------
src/structify/types/connector.py | 2 --
src/structify/types/connector_create_params.py | 2 --
src/structify/types/connector_update_params.py | 2 --
tests/api_resources/test_connectors.py | 4 ----
6 files changed, 2 insertions(+), 20 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 834a045e2..cb8dcf8ab 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0b71726c36b64babf01c7f86080a45d2a17672098fa2f44401d9d1c9312de4f7.yml
-openapi_spec_hash: 79732aa3e2581721052dd6c1abd90d36
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9ac930b25364583b2db87571ec154283722d305a063bb7903b072d992a2ab5a1.yml
+openapi_spec_hash: 28ed6dcfc4c41d4e4293a5f5cda6065c
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 23f1f1870..afe4aca65 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -94,7 +94,6 @@ def create(
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
- refresh_script: Optional[str] | Omit = omit,
secrets: Dict[str, 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.
@@ -129,7 +128,6 @@ def create(
"description": description,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
- "refresh_script": refresh_script,
"secrets": secrets,
},
connector_create_params.ConnectorCreateParams,
@@ -147,7 +145,6 @@ def update(
description: Optional[str] | Omit = omit,
known_connector_type: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
- refresh_script: Optional[str] | Omit = omit,
usage_snippet_override: 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.
@@ -176,7 +173,6 @@ def update(
"description": description,
"known_connector_type": known_connector_type,
"name": name,
- "refresh_script": refresh_script,
"usage_snippet_override": usage_snippet_override,
},
connector_update_params.ConnectorUpdateParams,
@@ -1194,7 +1190,6 @@ async def create(
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
- refresh_script: Optional[str] | Omit = omit,
secrets: Dict[str, 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.
@@ -1229,7 +1224,6 @@ async def create(
"description": description,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
- "refresh_script": refresh_script,
"secrets": secrets,
},
connector_create_params.ConnectorCreateParams,
@@ -1247,7 +1241,6 @@ async def update(
description: Optional[str] | Omit = omit,
known_connector_type: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
- refresh_script: Optional[str] | Omit = omit,
usage_snippet_override: 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.
@@ -1276,7 +1269,6 @@ async def update(
"description": description,
"known_connector_type": known_connector_type,
"name": name,
- "refresh_script": refresh_script,
"usage_snippet_override": usage_snippet_override,
},
connector_update_params.ConnectorUpdateParams,
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 8eafb0636..6df49f909 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -41,6 +41,4 @@ class Connector(BaseModel):
nango_integration_id: Optional[str] = None
- refresh_script: Optional[str] = None
-
usage_snippet_override: Optional[str] = None
diff --git a/src/structify/types/connector_create_params.py b/src/structify/types/connector_create_params.py
index 9aa5950fd..2f9bbec48 100644
--- a/src/structify/types/connector_create_params.py
+++ b/src/structify/types/connector_create_params.py
@@ -23,7 +23,5 @@ class ConnectorCreateParams(TypedDict, total=False):
nango_integration_id: Optional[str]
"""Nango integration ID (e.g., "linear", "slack")"""
- refresh_script: Optional[str]
-
secrets: Dict[str, str]
"""Optional secrets/environment variables for the connector"""
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index 51ffbed78..2d0fc0eb0 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -15,6 +15,4 @@ class ConnectorUpdateParams(TypedDict, total=False):
name: Optional[str]
- refresh_script: Optional[str]
-
usage_snippet_override: Optional[str]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index 6557138cc..c0d44fd46 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -52,7 +52,6 @@ def test_method_create_with_all_params(self, client: Structify) -> None:
description="description",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
- refresh_script="refresh_script",
secrets={"foo": "string"},
)
assert_matches_type(Connector, connector, path=["response"])
@@ -99,7 +98,6 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
description="description",
known_connector_type="known_connector_type",
name="name",
- refresh_script="refresh_script",
usage_snippet_override="usage_snippet_override",
)
assert connector is None
@@ -1312,7 +1310,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncStructify)
description="description",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
- refresh_script="refresh_script",
secrets={"foo": "string"},
)
assert_matches_type(Connector, connector, path=["response"])
@@ -1359,7 +1356,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
description="description",
known_connector_type="known_connector_type",
name="name",
- refresh_script="refresh_script",
usage_snippet_override="usage_snippet_override",
)
assert connector is None
From fc8a112722cb379d824920e3fde59345fdb4df85 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 05:24:26 +0000
Subject: [PATCH 007/105] chore: format all `api.md` files
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index e1c617e27..78554b597 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -72,7 +72,7 @@ format = { chain = [
# run formatting again to fix any inconsistencies when imports are stripped
"format:ruff",
]}
-"format:docs" = "python scripts/utils/ruffen-docs.py README.md api.md"
+"format:docs" = "bash -c 'python scripts/utils/ruffen-docs.py README.md $(find . -type f -name api.md)'"
"format:ruff" = "ruff format"
"lint" = { chain = [
From 6c64d5c8b902b82ef046fafbef03dfbe27fbd05c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 18:37:27 +0000
Subject: [PATCH 008/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/admin/job_list_response.py | 2 --
src/structify/types/job_get_response.py | 2 --
src/structify/types/job_list_response.py | 2 --
4 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index cb8dcf8ab..23c80ab49 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9ac930b25364583b2db87571ec154283722d305a063bb7903b072d992a2ab5a1.yml
-openapi_spec_hash: 28ed6dcfc4c41d4e4293a5f5cda6065c
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-bb0c9a0219101d7bed3f03d3565880c661d9366f67790defda43ba1b090d6561.yml
+openapi_spec_hash: c9d139865a64059620379dfa94cc3602
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/types/admin/job_list_response.py b/src/structify/types/admin/job_list_response.py
index f7cad37fe..d494541eb 100644
--- a/src/structify/types/admin/job_list_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -167,5 +167,3 @@ class JobListResponse(BaseModel):
run_started_time: Optional[datetime] = None
run_time_milliseconds: Optional[int] = None
-
- special_job_type: Optional[Literal["HumanLLM"]] = None
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
index 80b9978ce..c51109bea 100644
--- a/src/structify/types/job_get_response.py
+++ b/src/structify/types/job_get_response.py
@@ -208,8 +208,6 @@ class Info(BaseModel):
run_time_milliseconds: Optional[int] = None
- special_job_type: Optional[Literal["HumanLLM"]] = None
-
class SavedPropertiesPartialDateObject(BaseModel):
original_string: str
diff --git a/src/structify/types/job_list_response.py b/src/structify/types/job_list_response.py
index 4ed6da86a..d6567a058 100644
--- a/src/structify/types/job_list_response.py
+++ b/src/structify/types/job_list_response.py
@@ -167,5 +167,3 @@ class JobListResponse(BaseModel):
run_started_time: Optional[datetime] = None
run_time_milliseconds: Optional[int] = None
-
- special_job_type: Optional[Literal["HumanLLM"]] = None
From f733d2aad89b62c283d279a02d341d2b05a6357e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 22:56:32 +0000
Subject: [PATCH 009/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +-
pyproject.toml | 1 +
src/structify/resources/polars.py | 56 +++++++++++++++------
src/structify/resources/structure.py | 9 ++--
src/structify/types/structure_pdf_params.py | 8 +--
tests/api_resources/test_structure.py | 4 +-
6 files changed, 54 insertions(+), 28 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 23c80ab49..b1a899565 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-bb0c9a0219101d7bed3f03d3565880c661d9366f67790defda43ba1b090d6561.yml
-openapi_spec_hash: c9d139865a64059620379dfa94cc3602
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-910978cf2408b30290eb4d05d2efec09e8dcd53db71c9316670b3b46c3c50218.yml
+openapi_spec_hash: ecb3e8076932341277b429da091cdc8d
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/pyproject.toml b/pyproject.toml
index 78554b597..985ed4b25 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,6 +16,7 @@ dependencies = [
"distro>=1.7.0, <2",
"sniffio",
"polars==1.31.0",
+ "pypdf>=4.0.0,<5.0.0",
"tqdm>=4.66.2,<4.67.0",
]
diff --git a/src/structify/resources/polars.py b/src/structify/resources/polars.py
index 6ae6d9d38..0d0246816 100644
--- a/src/structify/resources/polars.py
+++ b/src/structify/resources/polars.py
@@ -8,6 +8,7 @@
from typing import Any, Dict, List, Tuple, Literal, Optional, cast
from concurrent.futures import Future, ThreadPoolExecutor, as_completed
+import pypdf
import polars as pl
from tqdm import tqdm # type: ignore
from polars import LazyFrame
@@ -845,6 +846,24 @@ def structure_pdfs(
table_param = as_table_param(table_name, schema)
+ paths_df = document_paths.collect()
+
+ page_count_map: dict[str, int] = {}
+ if mode == "all_pages":
+ for pdf_path in paths_df[path_column].to_list():
+ if pdf_path is not None:
+ with open(pdf_path, "rb") as f:
+ pdf = pypdf.PdfReader(f)
+ page_count_map[pdf_path] = len(pdf.pages)
+ else:
+ for pdf_path in paths_df[path_column].to_list():
+ # TODO: this is a hack to note that we cost twice as much for single page mode
+ page_count_map[pdf_path] = 2
+
+ total_pages = sum(page_count_map.values())
+ if not request_cost_confirmation_if_needed(self._client, total_pages, "pdf"):
+ raise Exception(f"User cancelled PDF extraction for {table_name}")
+
# Create dataset for this PDF
dataset_name = f"structure_pdfs_{table_name}_{uuid.uuid4().hex}"
self._client.datasets.create(
@@ -865,7 +884,6 @@ def structure_pdfs(
"model must be in format 'provider.model_name' (e.g. 'bedrock.claude-sonnet-4-bedrock')"
)
- paths_df = document_paths.collect()
instructions_list: list[str | None] = []
if instructions is not None and not isinstance(instructions, str):
@@ -874,42 +892,50 @@ def structure_pdfs(
raise ValueError(f"instructions shape {instr_df.shape} != document_paths shape {paths_df.shape}")
instructions_list = cast(List[Optional[str]], instr_df[instr_df.columns[0]].to_list())
- # Request cost confirmation before dispatching costly PDF extraction jobs
- if not request_cost_confirmation_if_needed(self._client, paths_df.shape[0], "pdf"):
- raise Exception(f"User cancelled PDF extraction for {table_name}")
-
job_to_pdf_path: dict[str, str] = {}
# Process each PDF document
- def process_pdf(pdf_path: str, instructions: str | None) -> Tuple[List[str], str]:
+ def upload_pdf(pdf_path: str) -> None:
# Upload the PDF document
- unique_pdf_name = f"{uuid.uuid4().hex}.pdf"
with open(pdf_path, "rb") as pdf_file:
try:
self._client.documents.upload(
content=pdf_file,
file_type="PDF",
dataset=dataset_name,
- path=unique_pdf_name.encode(),
+ path=pdf_path.encode(),
)
except Exception as e:
if "Document already exists" not in str(e):
raise e
+ with ThreadPoolExecutor(max_workers=MAX_PARALLEL_REQUESTS) as executor:
+ upload_futures: List[Future[None]] = []
+ for pdf_path in paths_df[path_column].to_list():
+ if isinstance(pdf_path, str):
+ upload_futures.append(executor.submit(upload_pdf, pdf_path))
+ for future in tqdm(as_completed(upload_futures), total=len(upload_futures), desc="Uploading PDFs"):
+ future.result()
+
+ def structure_pdf(pdf_path: str, instructions: str | None) -> Tuple[List[str], str]:
+ pages: List[int] | None = None
+ if mode == "all_pages":
+ pages = list(range(page_count_map[pdf_path]))
+
job_ids = self._client.structure.pdf(
dataset=dataset_name,
- path=unique_pdf_name,
+ path=pdf_path,
node_id=node_id,
instructions=instructions,
- mode="Single" if mode == "single" else "Batch",
model=model,
+ pages=pages,
).job_ids
return job_ids, pdf_path
with ThreadPoolExecutor(max_workers=MAX_PARALLEL_REQUESTS) as executor:
futures: List[Future[Tuple[List[str], str]]] = []
for i in range(paths_df.shape[0]):
- path: str | None = paths_df[path_column][i]
+ path = paths_df[path_column][i]
pdf_instructions: str | None = None
if isinstance(instructions, str):
pdf_instructions = instructions
@@ -917,15 +943,15 @@ def process_pdf(pdf_path: str, instructions: str | None) -> Tuple[List[str], str
pdf_instructions = instructions_list[i]
if pdf_instructions is None and conditioning:
pdf_instructions = conditioning
- if path is not None:
- futures.append(executor.submit(process_pdf, path, pdf_instructions))
- for future in tqdm(as_completed(futures), total=len(futures), desc="Preparing PDFs"):
+ if isinstance(path, str):
+ futures.append(executor.submit(structure_pdf, path, pdf_instructions))
+ for future in tqdm(as_completed(futures), total=len(futures), desc="Submitting PDFs for parsing"):
job_ids, pdf_path = future.result()
for job_id in job_ids:
job_to_pdf_path[job_id] = pdf_path
# Wait for all PDF processing jobs to complete
- self._client.jobs.wait_for_jobs(dataset_name=dataset_name, title=f"Parsing PDFs", node_id=node_id)
+ self._client.jobs.wait_for_jobs(dataset_name=dataset_name, title=f"Parsing PDF pages", node_id=node_id)
# Get all of the entities with their job_ids
entities = self._client.datasets.view_table(dataset=dataset_name, name=table_name)
diff --git a/src/structify/resources/structure.py b/src/structify/resources/structure.py
index 2581b5794..e004296d8 100644
--- a/src/structify/resources/structure.py
+++ b/src/structify/resources/structure.py
@@ -3,7 +3,6 @@
from __future__ import annotations
from typing import Iterable, Optional
-from typing_extensions import Literal
import httpx
@@ -276,9 +275,9 @@ def pdf(
dataset: str,
path: str,
instructions: Optional[str] | Omit = omit,
- mode: Literal["Single", "Batch"] | Omit = omit,
model: Optional[str] | Omit = omit,
node_id: Optional[str] | Omit = omit,
+ pages: Optional[Iterable[int]] | 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,
@@ -307,9 +306,9 @@ def pdf(
"dataset": dataset,
"path": path,
"instructions": instructions,
- "mode": mode,
"model": model,
"node_id": node_id,
+ "pages": pages,
},
structure_pdf_params.StructurePdfParams,
),
@@ -616,9 +615,9 @@ async def pdf(
dataset: str,
path: str,
instructions: Optional[str] | Omit = omit,
- mode: Literal["Single", "Batch"] | Omit = omit,
model: Optional[str] | Omit = omit,
node_id: Optional[str] | Omit = omit,
+ pages: Optional[Iterable[int]] | 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,
@@ -647,9 +646,9 @@ async def pdf(
"dataset": dataset,
"path": path,
"instructions": instructions,
- "mode": mode,
"model": model,
"node_id": node_id,
+ "pages": pages,
},
structure_pdf_params.StructurePdfParams,
),
diff --git a/src/structify/types/structure_pdf_params.py b/src/structify/types/structure_pdf_params.py
index e4c577e8b..48b2db292 100644
--- a/src/structify/types/structure_pdf_params.py
+++ b/src/structify/types/structure_pdf_params.py
@@ -2,8 +2,8 @@
from __future__ import annotations
-from typing import Optional
-from typing_extensions import Literal, Required, TypedDict
+from typing import Iterable, Optional
+from typing_extensions import Required, TypedDict
__all__ = ["StructurePdfParams"]
@@ -15,8 +15,8 @@ class StructurePdfParams(TypedDict, total=False):
instructions: Optional[str]
- mode: Literal["Single", "Batch"]
-
model: Optional[str]
node_id: Optional[str]
+
+ pages: Optional[Iterable[int]]
diff --git a/tests/api_resources/test_structure.py b/tests/api_resources/test_structure.py
index a87649bcc..1d33cc3e6 100644
--- a/tests/api_resources/test_structure.py
+++ b/tests/api_resources/test_structure.py
@@ -250,9 +250,9 @@ def test_method_pdf_with_all_params(self, client: Structify) -> None:
dataset="dataset",
path="path",
instructions="instructions",
- mode="Single",
model="model",
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ pages=[0],
)
assert_matches_type(StructurePdfResponse, structure, path=["response"])
@@ -586,9 +586,9 @@ async def test_method_pdf_with_all_params(self, async_client: AsyncStructify) ->
dataset="dataset",
path="path",
instructions="instructions",
- mode="Single",
model="model",
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ pages=[0],
)
assert_matches_type(StructurePdfResponse, structure, path=["response"])
From 6cbcd7d9e1c0374a9d6780e44f107ba37bea8d4f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 13 Feb 2026 23:17:06 +0000
Subject: [PATCH 010/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/list_chat_sessions_response.py | 6 ++++++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index b1a899565..3bb1608be 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-910978cf2408b30290eb4d05d2efec09e8dcd53db71c9316670b3b46c3c50218.yml
-openapi_spec_hash: ecb3e8076932341277b429da091cdc8d
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-6c1ab90a4f74e6b8a467fe4ee0c02675a5a426151d7ce02e0687922153bb6ae8.yml
+openapi_spec_hash: 56cae0e7eb10cb8862770340851b7c80
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/types/list_chat_sessions_response.py b/src/structify/types/list_chat_sessions_response.py
index cdfc2307e..a62d7c050 100644
--- a/src/structify/types/list_chat_sessions_response.py
+++ b/src/structify/types/list_chat_sessions_response.py
@@ -33,6 +33,12 @@ class Session(BaseModel):
project_id: Optional[str] = None
+ slack_channel_id: Optional[str] = None
+
+ teams_channel_id: Optional[str] = None
+
+ teams_conversation_id: Optional[str] = None
+
class ListChatSessionsResponse(BaseModel):
"""Response for listing chat sessions"""
From 464f6aa23698b3cec87ff2c7462e86d71aea48f6 Mon Sep 17 00:00:00 2001
From: Alex Goldstein
Date: Sat, 14 Feb 2026 00:12:10 +0000
Subject: [PATCH 011/105] Don't parallelize the agent now
---
src/structify/resources/polars.py | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/structify/resources/polars.py b/src/structify/resources/polars.py
index 0d0246816..d82a550fd 100644
--- a/src/structify/resources/polars.py
+++ b/src/structify/resources/polars.py
@@ -240,14 +240,10 @@ def enhance_entity_property(
else:
property_names = f"{', '.join(property_list[:-1])}, and {property_list[-1]}"
with ThreadPoolExecutor(max_workers=MAX_PARALLEL_REQUESTS) as executor:
- futures: List[Future[None]] = []
- # Iterate through property name at the outer level for queueing so with large requests
- # we can skip later jobs if the earlier ones get extra properties.
- for property_name in property_list:
- futures += [
- executor.submit(enhance_entity_property, entity_id, entity_param, [property_name])
- for entity_id, entity_param in entity_id_to_entity.items()
- ]
+ futures: List[Future[None]] = [
+ executor.submit(enhance_entity_property, entity_id, entity_param, property_list)
+ for entity_id, entity_param in entity_id_to_entity.items()
+ ]
for future in tqdm(
as_completed(futures), total=len(futures), desc=f"Preparing enrichments for {property_names}"
):
From 5c40f7b6977787dee2e1d96b1b13a4379229f38a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 14 Feb 2026 05:38:51 +0000
Subject: [PATCH 012/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +--
src/structify/resources/polars.py | 28 ++++++++-----------
.../types/dataset_view_table_response.py | 6 ++--
...view_tables_with_relationships_response.py | 8 +++---
.../entity_get_local_subgraph_response.py | 2 ++
src/structify/types/entity_get_response.py | 2 ++
src/structify/types/entity_search_response.py | 2 ++
.../types/entity_summarize_response.py | 2 ++
.../types/entity_update_property_response.py | 2 ++
src/structify/types/entity_view_response.py | 6 ++++
tests/api_resources/test_dataframe.py | 6 ++--
11 files changed, 39 insertions(+), 29 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 3bb1608be..4a506c71f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-6c1ab90a4f74e6b8a467fe4ee0c02675a5a426151d7ce02e0687922153bb6ae8.yml
-openapi_spec_hash: 56cae0e7eb10cb8862770340851b7c80
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-58be3f9aa58813af4da10c5ccc4a8279ed1a018f7046d8eb6b40843d9e078e4e.yml
+openapi_spec_hash: cf34b541d99840dd6bfbee42dc8d13bb
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/resources/polars.py b/src/structify/resources/polars.py
index d82a550fd..3b6dd3c58 100644
--- a/src/structify/resources/polars.py
+++ b/src/structify/resources/polars.py
@@ -13,6 +13,7 @@
from tqdm import tqdm # type: ignore
from polars import LazyFrame
+from structify import Structify
from structify.types.entity_param import EntityParam
from structify.types.property_type_param import PropertyTypeParam
from structify.types.dataset_create_params import Relationship as CreateRelationshipParam
@@ -37,12 +38,13 @@
STRUCTIFY_JOB_ID_COLUMN = "structify_job_id"
-def _collect_entities_with_job_ids(entities: Any) -> List[Dict[str, Any]]:
- """Collect entity properties with their first job_id."""
+def _collect_entities_with_job_ids(client: Structify, dataset_name: str, table_name: str) -> List[Dict[str, Any]]:
+ """Collect entity properties with their job_id."""
+ entities = client.datasets.view_table(dataset=dataset_name, name=table_name)
results: List[Dict[str, Any]] = []
for entity in entities:
row: Dict[str, Any] = dict(entity.properties)
- row[STRUCTIFY_JOB_ID_COLUMN] = entity.job_ids[0] if entity.job_ids else None
+ row[STRUCTIFY_JOB_ID_COLUMN] = entity.job_id
results.append(row)
return results
@@ -252,9 +254,7 @@ def enhance_entity_property(
title = f"Enriching {property_names} for {dataframe_name}"
self._client.jobs.wait_for_jobs(dataset_name=dataset_name, title=title, node_id=node_id)
# 4. Collect the results with job_ids
- results = _collect_entities_with_job_ids(
- self._client.datasets.view_table(dataset=dataset_name, name=dataframe_name)
- )
+ results = _collect_entities_with_job_ids(self._client, dataset_name, dataframe_name)
# 5. Return the results
return pl.DataFrame(results, schema=expected_schema)
@@ -414,7 +414,7 @@ def enhance_relationship(entity_id: str) -> None:
prop_name if prop_name not in input_schema else f"{prop_name}_{target_table_name}"
) # If the column already exists in the input schema, we need to suffix it with the target table name
result_row[eff] = target_entity.properties.get(prop_name)
- result_row[STRUCTIFY_JOB_ID_COLUMN] = target_entity.job_ids[0] if target_entity.job_ids else None
+ result_row[STRUCTIFY_JOB_ID_COLUMN] = target_entity.job_id
result_rows.append(result_row)
# Handle source rows without relationships
@@ -587,9 +587,7 @@ def scrape_entity_property(entity_id: str) -> None:
self._client.jobs.wait_for_jobs(dataset_name=dataset_name, title=title, node_id=node_id)
# 4. Collect the results with job_id
- results = _collect_entities_with_job_ids(
- self._client.datasets.view_table(dataset=dataset_name, name=dataframe_name)
- )
+ results = _collect_entities_with_job_ids(self._client, dataset_name, dataframe_name)
# 5. Return the results
return pl.DataFrame(results, schema=expected_schema)
@@ -746,9 +744,7 @@ def scrape_entity(entity: Dict[str, Any]) -> None:
result_row: dict[str, Any] = {
**scraped_entity.properties,
url_column: related_entity.properties[url_column],
- STRUCTIFY_JOB_ID_COLUMN: scraped_entity.job_ids[0]
- if scraped_entity.job_ids
- else None,
+ STRUCTIFY_JOB_ID_COLUMN: scraped_entity.job_id,
}
result_rows.append(result_row)
offset += LIMIT
@@ -953,7 +949,7 @@ def structure_pdf(pdf_path: str, instructions: str | None) -> Tuple[List[str], s
entities = self._client.datasets.view_table(dataset=dataset_name, name=table_name)
structured_results: List[Dict[str, Any]] = []
for entity in entities:
- job_id = entity.job_ids[0] if entity.job_ids else None
+ job_id = entity.job_id
result_row: Dict[str, Any] = {
**entity.properties,
path_column: job_to_pdf_path.get(job_id) if job_id else None,
@@ -1054,9 +1050,7 @@ def tag(
# 3. Collect the results with job_ids
title = f"Tagging {new_property_name} for {dataframe_name}"
self._client.jobs.wait_for_jobs(dataset_name=dataset_name, title=title, node_id=node_id)
- results = _collect_entities_with_job_ids(
- self._client.datasets.view_table(dataset=dataset_name, name=dataframe_name)
- )
+ results = _collect_entities_with_job_ids(self._client, dataset_name, dataframe_name)
# 4. Return the results
return pl.DataFrame(results, schema=expected_schema).lazy()
diff --git a/src/structify/types/dataset_view_table_response.py b/src/structify/types/dataset_view_table_response.py
index 2080355a2..18e546830 100644
--- a/src/structify/types/dataset_view_table_response.py
+++ b/src/structify/types/dataset_view_table_response.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Dict, List, Union, Optional
+from typing import Dict, Union, Optional
from datetime import datetime
from typing_extensions import Literal, TypeAlias
@@ -103,10 +103,10 @@ class DatasetViewTableResponse(BaseModel):
dataset_id: str
- job_ids: List[str]
-
label: str
properties: Dict[str, Properties]
updated_at: datetime
+
+ job_id: Optional[str] = None
diff --git a/src/structify/types/dataset_view_tables_with_relationships_response.py b/src/structify/types/dataset_view_tables_with_relationships_response.py
index 2dbf55099..72ecfb24f 100644
--- a/src/structify/types/dataset_view_tables_with_relationships_response.py
+++ b/src/structify/types/dataset_view_tables_with_relationships_response.py
@@ -118,14 +118,14 @@ class ConnectedEntity(BaseModel):
dataset_id: str
- job_ids: List[str]
-
label: str
properties: Dict[str, ConnectedEntityProperties]
updated_at: datetime
+ job_id: Optional[str] = None
+
class EntityPropertiesPartialDateObject(BaseModel):
original_string: str
@@ -212,14 +212,14 @@ class Entity(BaseModel):
dataset_id: str
- job_ids: List[str]
-
label: str
properties: Dict[str, EntityProperties]
updated_at: datetime
+ job_id: Optional[str] = None
+
class RelationshipPropertiesPartialDateObject(BaseModel):
original_string: str
diff --git a/src/structify/types/entity_get_local_subgraph_response.py b/src/structify/types/entity_get_local_subgraph_response.py
index e3ed1bcb7..eeb9e4348 100644
--- a/src/structify/types/entity_get_local_subgraph_response.py
+++ b/src/structify/types/entity_get_local_subgraph_response.py
@@ -117,6 +117,8 @@ class Neighbor(BaseModel):
updated_at: datetime
+ job_id: Optional[str] = None
+
class RelationshipPropertiesPartialDateObject(BaseModel):
original_string: str
diff --git a/src/structify/types/entity_get_response.py b/src/structify/types/entity_get_response.py
index fb913d686..43e98a9a2 100644
--- a/src/structify/types/entity_get_response.py
+++ b/src/structify/types/entity_get_response.py
@@ -108,3 +108,5 @@ class EntityGetResponse(BaseModel):
properties: Dict[str, Properties]
updated_at: datetime
+
+ job_id: Optional[str] = None
diff --git a/src/structify/types/entity_search_response.py b/src/structify/types/entity_search_response.py
index 5edf5eca8..ef9e15d45 100644
--- a/src/structify/types/entity_search_response.py
+++ b/src/structify/types/entity_search_response.py
@@ -110,5 +110,7 @@ class EntitySearchResponseItem(BaseModel):
updated_at: datetime
+ job_id: Optional[str] = None
+
EntitySearchResponse: TypeAlias = List[EntitySearchResponseItem]
diff --git a/src/structify/types/entity_summarize_response.py b/src/structify/types/entity_summarize_response.py
index c1eecbfde..7ce3c6dde 100644
--- a/src/structify/types/entity_summarize_response.py
+++ b/src/structify/types/entity_summarize_response.py
@@ -110,5 +110,7 @@ class EntitySummarizeResponseItem(BaseModel):
updated_at: datetime
+ job_id: Optional[str] = None
+
EntitySummarizeResponse: TypeAlias = List[EntitySummarizeResponseItem]
diff --git a/src/structify/types/entity_update_property_response.py b/src/structify/types/entity_update_property_response.py
index 9d0e10065..015a19568 100644
--- a/src/structify/types/entity_update_property_response.py
+++ b/src/structify/types/entity_update_property_response.py
@@ -108,3 +108,5 @@ class EntityUpdatePropertyResponse(BaseModel):
properties: Dict[str, Properties]
updated_at: datetime
+
+ job_id: Optional[str] = None
diff --git a/src/structify/types/entity_view_response.py b/src/structify/types/entity_view_response.py
index d66212f6f..7bba540f1 100644
--- a/src/structify/types/entity_view_response.py
+++ b/src/structify/types/entity_view_response.py
@@ -142,6 +142,8 @@ class ConnectedEntity(BaseModel):
updated_at: datetime
+ job_id: Optional[str] = None
+
class EntityPropertiesPartialDateObject(BaseModel):
original_string: str
@@ -234,6 +236,8 @@ class Entity(BaseModel):
updated_at: datetime
+ job_id: Optional[str] = None
+
class RelationshipPropertiesPartialDateObject(BaseModel):
original_string: str
@@ -422,6 +426,8 @@ class SimilarEntity(BaseModel):
updated_at: datetime
+ job_id: Optional[str] = None
+
class SourceLocationTextText(BaseModel):
byte_offset: int
diff --git a/tests/api_resources/test_dataframe.py b/tests/api_resources/test_dataframe.py
index 89b13a0f3..2b90d2fb4 100644
--- a/tests/api_resources/test_dataframe.py
+++ b/tests/api_resources/test_dataframe.py
@@ -115,9 +115,9 @@ def test_method_enhance_relationships(self, client: Structify) -> None:
mock_source_3 = Mock(id="entity-3", properties={"company_name": "Microsoft"})
# Target/connected entities
- mock_target_1 = Mock(id="target-1", properties={"employee_name": "Alex", "position": "CEO"}, job_ids=["job-1"])
- mock_target_2 = Mock(id="target-2", properties={"employee_name": "Alex", "position": "SWE"}, job_ids=["job-2"])
- mock_target_3 = Mock(id="target-3", properties={"employee_name": "Alex", "position": "PM"}, job_ids=["job-3"])
+ mock_target_1 = Mock(id="target-1", properties={"employee_name": "Alex", "position": "CEO"}, job_id="job-1")
+ mock_target_2 = Mock(id="target-2", properties={"employee_name": "Alex", "position": "SWE"}, job_id="job-2")
+ mock_target_3 = Mock(id="target-3", properties={"employee_name": "Alex", "position": "PM"}, job_id="job-3")
# Relationships connecting sources to targets
rel1 = Mock(from_id="entity-1", to_id="target-1")
From 782281890bbcb0117c542df7072e167a4b978a1d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 16 Feb 2026 02:28:53 +0000
Subject: [PATCH 013/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/teams.py | 5 +++++
src/structify/types/team_update_params.py | 4 +++-
tests/api_resources/test_teams.py | 2 ++
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 4a506c71f..e28126d2d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-58be3f9aa58813af4da10c5ccc4a8279ed1a018f7046d8eb6b40843d9e078e4e.yml
-openapi_spec_hash: cf34b541d99840dd6bfbee42dc8d13bb
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-d9f4b0ff786936f9db2b7bc5acd00f29ad9476d7fdb71bd2421f174a47e9ae62.yml
+openapi_spec_hash: 26ee581bb65a26f746406dbc497be768
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/resources/teams.py b/src/structify/resources/teams.py
index 0d8fbe051..8bddb0091 100644
--- a/src/structify/resources/teams.py
+++ b/src/structify/resources/teams.py
@@ -4,6 +4,7 @@
from typing import Union, Optional
from datetime import datetime
+from typing_extensions import Literal
import httpx
@@ -114,6 +115,7 @@ def update(
daytona_credentials: Optional[team_update_params.DaytonaCredentials] | Omit = omit,
description: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
+ sandbox_provider: Optional[Literal["modal", "daytona"]] | Omit = omit,
slack_bot_token: Optional[str] | Omit = omit,
slack_team_icon: Optional[str] | Omit = omit,
slack_team_id: Optional[str] | Omit = omit,
@@ -148,6 +150,7 @@ def update(
"daytona_credentials": daytona_credentials,
"description": description,
"name": name,
+ "sandbox_provider": sandbox_provider,
"slack_bot_token": slack_bot_token,
"slack_team_icon": slack_team_icon,
"slack_team_id": slack_team_id,
@@ -675,6 +678,7 @@ async def update(
daytona_credentials: Optional[team_update_params.DaytonaCredentials] | Omit = omit,
description: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
+ sandbox_provider: Optional[Literal["modal", "daytona"]] | Omit = omit,
slack_bot_token: Optional[str] | Omit = omit,
slack_team_icon: Optional[str] | Omit = omit,
slack_team_id: Optional[str] | Omit = omit,
@@ -709,6 +713,7 @@ async def update(
"daytona_credentials": daytona_credentials,
"description": description,
"name": name,
+ "sandbox_provider": sandbox_provider,
"slack_bot_token": slack_bot_token,
"slack_team_icon": slack_team_icon,
"slack_team_id": slack_team_id,
diff --git a/src/structify/types/team_update_params.py b/src/structify/types/team_update_params.py
index cddb4155a..6beaeed9f 100644
--- a/src/structify/types/team_update_params.py
+++ b/src/structify/types/team_update_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
__all__ = ["TeamUpdateParams", "DaytonaCredentials", "WorkflowBucket"]
@@ -15,6 +15,8 @@ class TeamUpdateParams(TypedDict, total=False):
name: Optional[str]
+ sandbox_provider: Optional[Literal["modal", "daytona"]]
+
slack_bot_token: Optional[str]
slack_team_icon: Optional[str]
diff --git a/tests/api_resources/test_teams.py b/tests/api_resources/test_teams.py
index cc0ac93eb..38bc0ce81 100644
--- a/tests/api_resources/test_teams.py
+++ b/tests/api_resources/test_teams.py
@@ -89,6 +89,7 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
},
description="description",
name="name",
+ sandbox_provider="modal",
slack_bot_token="slack_bot_token",
slack_team_icon="slack_team_icon",
slack_team_id="slack_team_id",
@@ -743,6 +744,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
},
description="description",
name="name",
+ sandbox_provider="modal",
slack_bot_token="slack_bot_token",
slack_team_icon="slack_team_icon",
slack_team_id="slack_team_id",
From 68e0e5a43037252590cf8a697d4b78760c4a7260 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 16 Feb 2026 22:15:49 +0000
Subject: [PATCH 014/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/team.py | 18 +++++++++++++++++-
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index e28126d2d..d55d75ea3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-d9f4b0ff786936f9db2b7bc5acd00f29ad9476d7fdb71bd2421f174a47e9ae62.yml
-openapi_spec_hash: 26ee581bb65a26f746406dbc497be768
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-078eb16aa89b64047bce6dc05d1ad62d79785489fb4b4d6eb17b9350ef5f9086.yml
+openapi_spec_hash: fb04d528d0059474f077f6d1460f7c50
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/types/team.py b/src/structify/types/team.py
index 725790464..3d4a67f59 100644
--- a/src/structify/types/team.py
+++ b/src/structify/types/team.py
@@ -5,7 +5,19 @@
from .._models import BaseModel
-__all__ = ["Team"]
+__all__ = ["Team", "DaytonaCredentials", "WorkflowBucket"]
+
+
+class DaytonaCredentials(BaseModel):
+ api_key: Optional[str] = None
+
+ api_url: Optional[str] = None
+
+
+class WorkflowBucket(BaseModel):
+ bucket_url: str
+
+ gcp_credentials_json: Optional[str] = None
class Team(BaseModel):
@@ -17,6 +29,8 @@ class Team(BaseModel):
updated_at: datetime
+ daytona_credentials: Optional[DaytonaCredentials] = None
+
description: Optional[str] = None
sandbox_provider: Optional[str] = None
@@ -34,3 +48,5 @@ class Team(BaseModel):
teams_service_url: Optional[str] = None
teams_tenant_id: Optional[str] = None
+
+ workflow_bucket: Optional[WorkflowBucket] = None
From fdc379a0fbc2ecc263f473553bded63e671a5640 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Feb 2026 17:11:01 +0000
Subject: [PATCH 015/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +--
README.md | 26 +++++++-------
api.md | 3 +-
src/structify/resources/admin/teams.py | 35 ++++++++++---------
src/structify/types/admin/__init__.py | 1 +
src/structify/types/admin/team_list_params.py | 2 ++
.../types/admin/team_list_response.py | 14 ++++++++
tests/api_resources/admin/test_teams.py | 21 +++++------
8 files changed, 63 insertions(+), 43 deletions(-)
create mode 100644 src/structify/types/admin/team_list_response.py
diff --git a/.stats.yml b/.stats.yml
index d55d75ea3..07eaf7178 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-078eb16aa89b64047bce6dc05d1ad62d79785489fb4b4d6eb17b9350ef5f9086.yml
-openapi_spec_hash: fb04d528d0059474f077f6d1460f7c50
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-a6b075395bd0772d888f5ade0b71f02159a6eead0f4b614e4b34748d25c8797d.yml
+openapi_spec_hash: a49a0bfcc8274bf8d5fb7950c4bfb3dd
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/README.md b/README.md
index 7c3467649..aceab7a36 100644
--- a/README.md
+++ b/README.md
@@ -120,12 +120,12 @@ from structify import Structify
client = Structify()
-all_teams = []
+all_jobs = []
# Automatically fetches more pages as needed.
-for team in client.admin.teams.list():
- # Do something with team here
- all_teams.append(team)
-print(all_teams)
+for job in client.admin.jobs.list():
+ # Do something with job here
+ all_jobs.append(job)
+print(all_jobs)
```
Or, asynchronously:
@@ -138,11 +138,11 @@ client = AsyncStructify()
async def main() -> None:
- all_teams = []
+ all_jobs = []
# Iterate through items across all pages, issuing requests as needed.
- async for team in client.admin.teams.list():
- all_teams.append(team)
- print(all_teams)
+ async for job in client.admin.jobs.list():
+ all_jobs.append(job)
+ print(all_jobs)
asyncio.run(main())
@@ -151,7 +151,7 @@ asyncio.run(main())
Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:
```python
-first_page = await client.admin.teams.list()
+first_page = await client.admin.jobs.list()
if first_page.has_next_page():
print(f"will fetch next page using these details: {first_page.next_page_info()}")
next_page = await first_page.get_next_page()
@@ -163,9 +163,9 @@ if first_page.has_next_page():
Or just work directly with the returned data:
```python
-first_page = await client.admin.teams.list()
-for team in first_page.items:
- print(team)
+first_page = await client.admin.jobs.list()
+for job in first_page.items:
+ print(job.id)
# Remove `await` for non-async usage.
```
diff --git a/api.md b/api.md
index 7ccb63e42..3cf77e481 100644
--- a/api.md
+++ b/api.md
@@ -282,12 +282,13 @@ from structify.types.admin import (
GrantCreditsResponse,
UpdateSeatsOverrideRequest,
UpdateSeatsOverrideResponse,
+ TeamListResponse,
)
```
Methods:
-- client.admin.teams.list(\*\*params) -> SyncJobsList[AdminTeamsListResponse]
+- client.admin.teams.list(\*\*params) -> TeamListResponse
- client.admin.teams.add_member(\*\*params) -> AdminAddMemberResponse
- client.admin.teams.cancel_subscription(\*\*params) -> CancelSubscriptionResponse
- client.admin.teams.create_subscription(\*\*params) -> CreateSubscriptionResponse
diff --git a/src/structify/resources/admin/teams.py b/src/structify/resources/admin/teams.py
index dc9e4e015..c9c6989fc 100644
--- a/src/structify/resources/admin/teams.py
+++ b/src/structify/resources/admin/teams.py
@@ -19,7 +19,6 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ...pagination import SyncJobsList, AsyncJobsList
from ...types.admin import (
team_list_params,
team_add_member_params,
@@ -31,13 +30,13 @@
team_create_subscription_params,
team_update_seats_override_params,
)
-from ..._base_client import AsyncPaginator, make_request_options
+from ..._base_client import make_request_options
from ...types.team_role import TeamRole
+from ...types.admin.team_list_response import TeamListResponse
from ...types.admin.extend_trial_response import ExtendTrialResponse
from ...types.admin.expire_grants_response import ExpireGrantsResponse
from ...types.admin.grant_credits_response import GrantCreditsResponse
from ...types.admin.admin_add_member_response import AdminAddMemberResponse
-from ...types.admin.admin_teams_list_response import AdminTeamsListResponse
from ...types.admin.admin_list_members_response import AdminListMembersResponse
from ...types.admin.admin_remove_member_response import AdminRemoveMemberResponse
from ...types.admin.cancel_subscription_response import CancelSubscriptionResponse
@@ -72,17 +71,18 @@ def list(
*,
limit: Optional[int] | Omit = omit,
offset: Optional[int] | Omit = omit,
+ search: 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,
- ) -> SyncJobsList[AdminTeamsListResponse]:
+ ) -> TeamListResponse:
"""
Lists teams in the system along with their subscription information, credit
- grants, and member counts. Supports optional pagination via limit and offset
- query parameters.
+ grants, and member counts. Supports optional pagination via limit, offset, and
+ search query parameters.
Args:
extra_headers: Send extra headers
@@ -93,9 +93,8 @@ def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._get_api_list(
+ return self._get(
"/admin/team/list",
- page=SyncJobsList[AdminTeamsListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -105,11 +104,12 @@ def list(
{
"limit": limit,
"offset": offset,
+ "search": search,
},
team_list_params.TeamListParams,
),
),
- model=AdminTeamsListResponse,
+ cast_to=TeamListResponse,
)
def add_member(
@@ -475,22 +475,23 @@ def with_streaming_response(self) -> AsyncTeamsResourceWithStreamingResponse:
"""
return AsyncTeamsResourceWithStreamingResponse(self)
- def list(
+ async def list(
self,
*,
limit: Optional[int] | Omit = omit,
offset: Optional[int] | Omit = omit,
+ search: 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,
- ) -> AsyncPaginator[AdminTeamsListResponse, AsyncJobsList[AdminTeamsListResponse]]:
+ ) -> TeamListResponse:
"""
Lists teams in the system along with their subscription information, credit
- grants, and member counts. Supports optional pagination via limit and offset
- query parameters.
+ grants, and member counts. Supports optional pagination via limit, offset, and
+ search query parameters.
Args:
extra_headers: Send extra headers
@@ -501,23 +502,23 @@ def list(
timeout: Override the client-level default timeout for this request, in seconds
"""
- return self._get_api_list(
+ return await self._get(
"/admin/team/list",
- page=AsyncJobsList[AdminTeamsListResponse],
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=maybe_transform(
+ query=await async_maybe_transform(
{
"limit": limit,
"offset": offset,
+ "search": search,
},
team_list_params.TeamListParams,
),
),
- model=AdminTeamsListResponse,
+ cast_to=TeamListResponse,
)
async def add_member(
diff --git a/src/structify/types/admin/__init__.py b/src/structify/types/admin/__init__.py
index 6745f1848..9c79effd6 100644
--- a/src/structify/types/admin/__init__.py
+++ b/src/structify/types/admin/__init__.py
@@ -8,6 +8,7 @@
from .team_list_params import TeamListParams as TeamListParams
from .job_delete_params import JobDeleteParams as JobDeleteParams
from .job_list_response import JobListResponse as JobListResponse
+from .team_list_response import TeamListResponse as TeamListResponse
from .user_create_params import UserCreateParams as UserCreateParams
from .user_list_response import UserListResponse as UserListResponse
from .sandbox_list_params import SandboxListParams as SandboxListParams
diff --git a/src/structify/types/admin/team_list_params.py b/src/structify/types/admin/team_list_params.py
index e5cec336c..065bf3749 100644
--- a/src/structify/types/admin/team_list_params.py
+++ b/src/structify/types/admin/team_list_params.py
@@ -12,3 +12,5 @@ class TeamListParams(TypedDict, total=False):
limit: Optional[int]
offset: Optional[int]
+
+ search: Optional[str]
diff --git a/src/structify/types/admin/team_list_response.py b/src/structify/types/admin/team_list_response.py
new file mode 100644
index 000000000..0c06da6ba
--- /dev/null
+++ b/src/structify/types/admin/team_list_response.py
@@ -0,0 +1,14 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from .admin_teams_list_response import AdminTeamsListResponse
+
+__all__ = ["TeamListResponse"]
+
+
+class TeamListResponse(BaseModel):
+ items: List[AdminTeamsListResponse]
+
+ total_count: int
diff --git a/tests/api_resources/admin/test_teams.py b/tests/api_resources/admin/test_teams.py
index 57ba074c1..f1ba06f3b 100644
--- a/tests/api_resources/admin/test_teams.py
+++ b/tests/api_resources/admin/test_teams.py
@@ -10,13 +10,12 @@
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
from structify._utils import parse_datetime
-from structify.pagination import SyncJobsList, AsyncJobsList
from structify.types.admin import (
+ TeamListResponse,
ExtendTrialResponse,
ExpireGrantsResponse,
GrantCreditsResponse,
AdminAddMemberResponse,
- AdminTeamsListResponse,
AdminListMembersResponse,
AdminRemoveMemberResponse,
CancelSubscriptionResponse,
@@ -33,15 +32,16 @@ class TestTeams:
@parametrize
def test_method_list(self, client: Structify) -> None:
team = client.admin.teams.list()
- assert_matches_type(SyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
@parametrize
def test_method_list_with_all_params(self, client: Structify) -> None:
team = client.admin.teams.list(
limit=0,
offset=0,
+ search="search",
)
- assert_matches_type(SyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
@parametrize
def test_raw_response_list(self, client: Structify) -> None:
@@ -50,7 +50,7 @@ def test_raw_response_list(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
team = response.parse()
- assert_matches_type(SyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
@parametrize
def test_streaming_response_list(self, client: Structify) -> None:
@@ -59,7 +59,7 @@ def test_streaming_response_list(self, client: Structify) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
team = response.parse()
- assert_matches_type(SyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -421,15 +421,16 @@ class TestAsyncTeams:
@parametrize
async def test_method_list(self, async_client: AsyncStructify) -> None:
team = await async_client.admin.teams.list()
- assert_matches_type(AsyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncStructify) -> None:
team = await async_client.admin.teams.list(
limit=0,
offset=0,
+ search="search",
)
- assert_matches_type(AsyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
@parametrize
async def test_raw_response_list(self, async_client: AsyncStructify) -> None:
@@ -438,7 +439,7 @@ async def test_raw_response_list(self, async_client: AsyncStructify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
team = await response.parse()
- assert_matches_type(AsyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
@parametrize
async def test_streaming_response_list(self, async_client: AsyncStructify) -> None:
@@ -447,7 +448,7 @@ async def test_streaming_response_list(self, async_client: AsyncStructify) -> No
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
team = await response.parse()
- assert_matches_type(AsyncJobsList[AdminTeamsListResponse], team, path=["response"])
+ assert_matches_type(TeamListResponse, team, path=["response"])
assert cast(Any, response.is_closed) is True
From 9091cce1f24daa6ec1079c5b313a8c212173f835 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Feb 2026 23:20:46 +0000
Subject: [PATCH 016/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/connector.py | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 07eaf7178..2ba7b5a1d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-a6b075395bd0772d888f5ade0b71f02159a6eead0f4b614e4b34748d25c8797d.yml
-openapi_spec_hash: a49a0bfcc8274bf8d5fb7950c4bfb3dd
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9513d397aafc9866fdd283cec730b61f413dac134ea433e9424c45a944618326.yml
+openapi_spec_hash: 5690659944d718d450de71a0f12db0f5
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 6df49f909..1a0441d0a 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -2,6 +2,7 @@
from typing import Optional
from datetime import datetime
+from typing_extensions import Literal
from .._models import BaseModel
from .connector_category import ConnectorCategory
@@ -23,6 +24,8 @@ class Connector(BaseModel):
team_id: str
+ team_visibility: Literal["Team", "Private"]
+
updated_at: datetime
connector_category: Optional[ConnectorCategory] = None
From ab6c580596d6cb790650173533f43d647651e25a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Feb 2026 23:38:27 +0000
Subject: [PATCH 017/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/chat.py | 4 ++++
src/structify/resources/sessions.py | 4 ++++
src/structify/types/chat_session.py | 2 ++
src/structify/types/chat_session_with_messages.py | 2 ++
src/structify/types/chat_update_session_params.py | 2 ++
src/structify/types/get_chat_session_response.py | 7 +++++++
src/structify/types/session_create_session_params.py | 2 ++
src/structify/types/workflow_session.py | 2 ++
tests/api_resources/test_chat.py | 2 ++
tests/api_resources/test_sessions.py | 2 ++
11 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 2ba7b5a1d..460e170d0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9513d397aafc9866fdd283cec730b61f413dac134ea433e9424c45a944618326.yml
-openapi_spec_hash: 5690659944d718d450de71a0f12db0f5
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0b1b4a5942efd52970d7e864ec0b75d545d9e05ebdf0be538b8c0820b08f9e43.yml
+openapi_spec_hash: e9f74a2fd07248b6b4737adaef9fb77a
config_hash: b64f821fbf26f8916969ad9664bb945f
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 0c8d58d2f..92074d1a3 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -902,6 +902,7 @@ def update_session(
name: Optional[str] | Omit = omit,
project_id: Optional[str] | Omit = omit,
skip_confirmations: Optional[bool] | Omit = omit,
+ user_message_head: 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,
@@ -928,6 +929,7 @@ def update_session(
"name": name,
"project_id": project_id,
"skip_confirmations": skip_confirmations,
+ "user_message_head": user_message_head,
},
chat_update_session_params.ChatUpdateSessionParams,
),
@@ -1853,6 +1855,7 @@ async def update_session(
name: Optional[str] | Omit = omit,
project_id: Optional[str] | Omit = omit,
skip_confirmations: Optional[bool] | Omit = omit,
+ user_message_head: 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,
@@ -1879,6 +1882,7 @@ async def update_session(
"name": name,
"project_id": project_id,
"skip_confirmations": skip_confirmations,
+ "user_message_head": user_message_head,
},
chat_update_session_params.ChatUpdateSessionParams,
),
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 658ce3c43..820100c79 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -121,6 +121,7 @@ def create_session(
*,
chat_session_id: str,
git_commit: str,
+ parent_chat_message_id: Optional[str] | Omit = omit,
workflow_schedule_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -145,6 +146,7 @@ def create_session(
{
"chat_session_id": chat_session_id,
"git_commit": git_commit,
+ "parent_chat_message_id": parent_chat_message_id,
"workflow_schedule_id": workflow_schedule_id,
},
session_create_session_params.SessionCreateSessionParams,
@@ -829,6 +831,7 @@ async def create_session(
*,
chat_session_id: str,
git_commit: str,
+ parent_chat_message_id: Optional[str] | Omit = omit,
workflow_schedule_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -853,6 +856,7 @@ async def create_session(
{
"chat_session_id": chat_session_id,
"git_commit": git_commit,
+ "parent_chat_message_id": parent_chat_message_id,
"workflow_schedule_id": workflow_schedule_id,
},
session_create_session_params.SessionCreateSessionParams,
diff --git a/src/structify/types/chat_session.py b/src/structify/types/chat_session.py
index a3e7305c9..9e28ab660 100644
--- a/src/structify/types/chat_session.py
+++ b/src/structify/types/chat_session.py
@@ -51,3 +51,5 @@ class ChatSession(BaseModel):
teams_conversation_id: Optional[str] = None
teams_tenant_id: Optional[str] = None
+
+ user_message_head: Optional[str] = None
diff --git a/src/structify/types/chat_session_with_messages.py b/src/structify/types/chat_session_with_messages.py
index 42a4f3ec3..8329df246 100644
--- a/src/structify/types/chat_session_with_messages.py
+++ b/src/structify/types/chat_session_with_messages.py
@@ -104,3 +104,5 @@ class ChatSessionWithMessages(BaseModel):
teams_conversation_id: Optional[str] = None
teams_tenant_id: Optional[str] = None
+
+ user_message_head: Optional[str] = None
diff --git a/src/structify/types/chat_update_session_params.py b/src/structify/types/chat_update_session_params.py
index e3ac063cb..8a0f005d4 100644
--- a/src/structify/types/chat_update_session_params.py
+++ b/src/structify/types/chat_update_session_params.py
@@ -14,3 +14,5 @@ class ChatUpdateSessionParams(TypedDict, total=False):
project_id: Optional[str]
skip_confirmations: Optional[bool]
+
+ user_message_head: Optional[str]
diff --git a/src/structify/types/get_chat_session_response.py b/src/structify/types/get_chat_session_response.py
index 5ad205a0d..f7e7b5738 100644
--- a/src/structify/types/get_chat_session_response.py
+++ b/src/structify/types/get_chat_session_response.py
@@ -7,6 +7,7 @@
from .._models import BaseModel
from .chat_event import ChatEvent
from .chat_visibility import ChatVisibility
+from .workflow_session import WorkflowSession
from .chat_session_role import ChatSessionRole
__all__ = ["GetChatSessionResponse", "Session", "SessionCommit", "SessionMessage"]
@@ -37,6 +38,8 @@ class SessionMessage(BaseModel):
timestamp: datetime
+ previous_message_id: Optional[str] = None
+
class Session(BaseModel):
id: str
@@ -63,6 +66,8 @@ class Session(BaseModel):
visibility: ChatVisibility
+ workflow_sessions: List[WorkflowSession]
+
latest_workflow_session_id: Optional[str] = None
name: Optional[str] = None
@@ -81,6 +86,8 @@ class Session(BaseModel):
teams_tenant_id: Optional[str] = None
+ user_message_head: Optional[str] = None
+
workflow_schedule_id: Optional[str] = None
diff --git a/src/structify/types/session_create_session_params.py b/src/structify/types/session_create_session_params.py
index df1aae369..d330ba7ec 100644
--- a/src/structify/types/session_create_session_params.py
+++ b/src/structify/types/session_create_session_params.py
@@ -13,4 +13,6 @@ class SessionCreateSessionParams(TypedDict, total=False):
git_commit: Required[str]
+ parent_chat_message_id: Optional[str]
+
workflow_schedule_id: Optional[str]
diff --git a/src/structify/types/workflow_session.py b/src/structify/types/workflow_session.py
index dfbcdbd57..55c559138 100644
--- a/src/structify/types/workflow_session.py
+++ b/src/structify/types/workflow_session.py
@@ -31,4 +31,6 @@ class WorkflowSession(BaseModel):
git_commit: Optional[str] = None
+ parent_chat_message_id: Optional[str] = None
+
workflow_schedule_id: Optional[str] = None
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 2d1b33db1..5a3326e3f 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -962,6 +962,7 @@ def test_method_update_session_with_all_params(self, client: Structify) -> None:
name="name",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
skip_confirmations=True,
+ user_message_head="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ChatSession, chat, path=["response"])
@@ -2010,6 +2011,7 @@ async def test_method_update_session_with_all_params(self, async_client: AsyncSt
name="name",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
skip_confirmations=True,
+ user_message_head="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ChatSession, chat, path=["response"])
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 97cdd8f69..2a7da0752 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -91,6 +91,7 @@ def test_method_create_session_with_all_params(self, client: Structify) -> None:
session = client.sessions.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
git_commit="git_commit",
+ parent_chat_message_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
workflow_schedule_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(WorkflowSession, session, path=["response"])
@@ -1142,6 +1143,7 @@ async def test_method_create_session_with_all_params(self, async_client: AsyncSt
session = await async_client.sessions.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
git_commit="git_commit",
+ parent_chat_message_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
workflow_schedule_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(WorkflowSession, session, path=["response"])
From 6f8c059edc0ed2a5fb61c805f3a28ece6397f207 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Feb 2026 02:42:55 +0000
Subject: [PATCH 018/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 10 ++
src/structify/resources/admin/admin.py | 92 +++++++++++++++++++
src/structify/types/__init__.py | 1 +
.../types/admin_report_critical_params.py | 11 +++
tests/api_resources/test_admin.py | 84 +++++++++++++++++
6 files changed, 202 insertions(+), 4 deletions(-)
create mode 100644 src/structify/types/admin_report_critical_params.py
create mode 100644 tests/api_resources/test_admin.py
diff --git a/.stats.yml b/.stats.yml
index 460e170d0..ae143cd82 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 234
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0b1b4a5942efd52970d7e864ec0b75d545d9e05ebdf0be538b8c0820b08f9e43.yml
-openapi_spec_hash: e9f74a2fd07248b6b4737adaef9fb77a
-config_hash: b64f821fbf26f8916969ad9664bb945f
+configured_endpoints: 235
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c50b742e1de43029b0a202bd144d382067eede0f1abe655f7cd39dc378f473f2.yml
+openapi_spec_hash: eb544b9cefa630eb4a391df62ab30b0e
+config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/api.md b/api.md
index 3cf77e481..f244b9914 100644
--- a/api.md
+++ b/api.md
@@ -258,6 +258,16 @@ Methods:
# Admin
+Types:
+
+```python
+from structify.types import ReportCriticalRequest
+```
+
+Methods:
+
+- client.admin.report_critical(\*\*params) -> None
+
## Teams
Types:
diff --git a/src/structify/resources/admin/admin.py b/src/structify/resources/admin/admin.py
index 2f19ae99c..585fe9825 100644
--- a/src/structify/resources/admin/admin.py
+++ b/src/structify/resources/admin/admin.py
@@ -2,6 +2,8 @@
from __future__ import annotations
+import httpx
+
from .jobs import (
JobsResource,
AsyncJobsResource,
@@ -26,6 +28,7 @@
UsersResourceWithStreamingResponse,
AsyncUsersResourceWithStreamingResponse,
)
+from ...types import admin_report_critical_params
from .dataset import (
DatasetResource,
AsyncDatasetResource,
@@ -42,6 +45,8 @@
SandboxResourceWithStreamingResponse,
AsyncSandboxResourceWithStreamingResponse,
)
+from ..._types import Body, Query, Headers, NoneType, NotGiven, not_given
+from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from .connector import (
ConnectorResource,
@@ -52,6 +57,13 @@
AsyncConnectorResourceWithStreamingResponse,
)
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 ..._base_client import make_request_options
from .chat_templates import (
ChatTemplatesResource,
AsyncChatTemplatesResource,
@@ -124,6 +136,37 @@ def with_streaming_response(self) -> AdminResourceWithStreamingResponse:
"""
return AdminResourceWithStreamingResponse(self)
+ def report_critical(
+ self,
+ *,
+ message: str,
+ # 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:
+ """
+ Args:
+ 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 {})}
+ return self._post(
+ "/admin/critical",
+ body=maybe_transform({"message": message}, admin_report_critical_params.AdminReportCriticalParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class AsyncAdminResource(AsyncAPIResource):
@cached_property
@@ -177,11 +220,48 @@ def with_streaming_response(self) -> AsyncAdminResourceWithStreamingResponse:
"""
return AsyncAdminResourceWithStreamingResponse(self)
+ async def report_critical(
+ self,
+ *,
+ message: str,
+ # 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:
+ """
+ Args:
+ 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 {})}
+ return await self._post(
+ "/admin/critical",
+ body=await async_maybe_transform(
+ {"message": message}, admin_report_critical_params.AdminReportCriticalParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class AdminResourceWithRawResponse:
def __init__(self, admin: AdminResource) -> None:
self._admin = admin
+ self.report_critical = to_raw_response_wrapper(
+ admin.report_critical,
+ )
+
@cached_property
def teams(self) -> TeamsResourceWithRawResponse:
return TeamsResourceWithRawResponse(self._admin.teams)
@@ -219,6 +299,10 @@ class AsyncAdminResourceWithRawResponse:
def __init__(self, admin: AsyncAdminResource) -> None:
self._admin = admin
+ self.report_critical = async_to_raw_response_wrapper(
+ admin.report_critical,
+ )
+
@cached_property
def teams(self) -> AsyncTeamsResourceWithRawResponse:
return AsyncTeamsResourceWithRawResponse(self._admin.teams)
@@ -256,6 +340,10 @@ class AdminResourceWithStreamingResponse:
def __init__(self, admin: AdminResource) -> None:
self._admin = admin
+ self.report_critical = to_streamed_response_wrapper(
+ admin.report_critical,
+ )
+
@cached_property
def teams(self) -> TeamsResourceWithStreamingResponse:
return TeamsResourceWithStreamingResponse(self._admin.teams)
@@ -293,6 +381,10 @@ class AsyncAdminResourceWithStreamingResponse:
def __init__(self, admin: AsyncAdminResource) -> None:
self._admin = admin
+ self.report_critical = async_to_streamed_response_wrapper(
+ admin.report_critical,
+ )
+
@cached_property
def teams(self) -> AsyncTeamsResourceWithStreamingResponse:
return AsyncTeamsResourceWithStreamingResponse(self._admin.teams)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 34f1f8e84..3cacb0784 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -231,6 +231,7 @@
from .source_delete_entity_params import SourceDeleteEntityParams as SourceDeleteEntityParams
from .structure_job_status_params import StructureJobStatusParams as StructureJobStatusParams
from .update_member_role_response import UpdateMemberRoleResponse as UpdateMemberRoleResponse
+from .admin_report_critical_params import AdminReportCriticalParams as AdminReportCriticalParams
from .chat_add_collaborator_params import ChatAddCollaboratorParams as ChatAddCollaboratorParams
from .chat_add_git_commit_response import ChatAddGitCommitResponse as ChatAddGitCommitResponse
from .chat_get_git_commit_response import ChatGetGitCommitResponse as ChatGetGitCommitResponse
diff --git a/src/structify/types/admin_report_critical_params.py b/src/structify/types/admin_report_critical_params.py
new file mode 100644
index 000000000..5e036be4f
--- /dev/null
+++ b/src/structify/types/admin_report_critical_params.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["AdminReportCriticalParams"]
+
+
+class AdminReportCriticalParams(TypedDict, total=False):
+ message: Required[str]
diff --git a/tests/api_resources/test_admin.py b/tests/api_resources/test_admin.py
new file mode 100644
index 000000000..2e6c742b9
--- /dev/null
+++ b/tests/api_resources/test_admin.py
@@ -0,0 +1,84 @@
+# 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 structify import Structify, AsyncStructify
+
+base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
+
+
+class TestAdmin:
+ parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+
+ @parametrize
+ def test_method_report_critical(self, client: Structify) -> None:
+ admin = client.admin.report_critical(
+ message="message",
+ )
+ assert admin is None
+
+ @parametrize
+ def test_raw_response_report_critical(self, client: Structify) -> None:
+ response = client.admin.with_raw_response.report_critical(
+ message="message",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ admin = response.parse()
+ assert admin is None
+
+ @parametrize
+ def test_streaming_response_report_critical(self, client: Structify) -> None:
+ with client.admin.with_streaming_response.report_critical(
+ message="message",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ admin = response.parse()
+ assert admin is None
+
+ assert cast(Any, response.is_closed) is True
+
+
+class TestAsyncAdmin:
+ parametrize = pytest.mark.parametrize(
+ "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
+ )
+
+ @parametrize
+ async def test_method_report_critical(self, async_client: AsyncStructify) -> None:
+ admin = await async_client.admin.report_critical(
+ message="message",
+ )
+ assert admin is None
+
+ @parametrize
+ async def test_raw_response_report_critical(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.with_raw_response.report_critical(
+ message="message",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ admin = await response.parse()
+ assert admin is None
+
+ @parametrize
+ async def test_streaming_response_report_critical(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.with_streaming_response.report_critical(
+ message="message",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ admin = await response.parse()
+ assert admin is None
+
+ assert cast(Any, response.is_closed) is True
From ef67e8857e56940b6d8f7b7d351ce8bf6d2d6d29 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Feb 2026 04:58:17 +0000
Subject: [PATCH 019/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +--
.../resources/connectors/connectors.py | 26 +++++++++++++++++++
.../types/connector_update_params.py | 17 +++++++++++-
tests/api_resources/test_connectors.py | 12 +++++++++
4 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index ae143cd82..c3dc0024c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c50b742e1de43029b0a202bd144d382067eede0f1abe655f7cd39dc378f473f2.yml
-openapi_spec_hash: eb544b9cefa630eb4a391df62ab30b0e
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-711c47583ac185bb9eae3a8726ca87a38b6b68d10ae8bc59ac2170486d23d9c5.yml
+openapi_spec_hash: a88c245384bed8ddefced34c097b77af
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index afe4aca65..47af88146 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -8,6 +8,7 @@
import httpx
from ...types import (
+ ConnectorCategory,
connector_list_params,
connector_create_params,
connector_update_params,
@@ -43,6 +44,7 @@
)
from ..._base_client import AsyncPaginator, make_request_options
from ...types.connector import Connector
+from ...types.connector_category import ConnectorCategory
from ...types.list_tables_response import ListTablesResponse
from ...types.update_table_response import UpdateTableResponse
from ...types.connector_get_response import ConnectorGetResponse
@@ -142,10 +144,16 @@ def update(
self,
connector_id: str,
*,
+ connector_category: Optional[ConnectorCategory] | Omit = omit,
+ datahub_urn: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
known_connector_type: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
+ nango_connection_id: Optional[str] | Omit = omit,
+ nango_integration_id: Optional[str] | Omit = omit,
+ team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
+ user_ids: Optional[SequenceNotStr[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,
@@ -170,10 +178,16 @@ def update(
f"/connectors/{connector_id}",
body=maybe_transform(
{
+ "connector_category": connector_category,
+ "datahub_urn": datahub_urn,
"description": description,
"known_connector_type": known_connector_type,
"name": name,
+ "nango_connection_id": nango_connection_id,
+ "nango_integration_id": nango_integration_id,
+ "team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
+ "user_ids": user_ids,
},
connector_update_params.ConnectorUpdateParams,
),
@@ -1238,10 +1252,16 @@ async def update(
self,
connector_id: str,
*,
+ connector_category: Optional[ConnectorCategory] | Omit = omit,
+ datahub_urn: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
known_connector_type: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
+ nango_connection_id: Optional[str] | Omit = omit,
+ nango_integration_id: Optional[str] | Omit = omit,
+ team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
+ user_ids: Optional[SequenceNotStr[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,
@@ -1266,10 +1286,16 @@ async def update(
f"/connectors/{connector_id}",
body=await async_maybe_transform(
{
+ "connector_category": connector_category,
+ "datahub_urn": datahub_urn,
"description": description,
"known_connector_type": known_connector_type,
"name": name,
+ "nango_connection_id": nango_connection_id,
+ "nango_integration_id": nango_integration_id,
+ "team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
+ "user_ids": user_ids,
},
connector_update_params.ConnectorUpdateParams,
),
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index 2d0fc0eb0..0b06e1ff7 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -3,16 +3,31 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
+
+from .._types import SequenceNotStr
+from .connector_category import ConnectorCategory
__all__ = ["ConnectorUpdateParams"]
class ConnectorUpdateParams(TypedDict, total=False):
+ connector_category: Optional[ConnectorCategory]
+
+ datahub_urn: Optional[str]
+
description: Optional[str]
known_connector_type: Optional[str]
name: Optional[str]
+ nango_connection_id: Optional[str]
+
+ nango_integration_id: Optional[str]
+
+ team_visibility: Optional[Literal["Team", "Private"]]
+
usage_snippet_override: Optional[str]
+
+ user_ids: Optional[SequenceNotStr[str]]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index c0d44fd46..ceb0e89dd 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -95,10 +95,16 @@ def test_method_update(self, client: Structify) -> None:
def test_method_update_with_all_params(self, client: Structify) -> None:
connector = client.connectors.update(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_category="RelationalDatabase",
+ datahub_urn="datahub_urn",
description="description",
known_connector_type="known_connector_type",
name="name",
+ nango_connection_id="nango_connection_id",
+ nango_integration_id="nango_integration_id",
+ team_visibility="Team",
usage_snippet_override="usage_snippet_override",
+ user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
)
assert connector is None
@@ -1353,10 +1359,16 @@ async def test_method_update(self, async_client: AsyncStructify) -> None:
async def test_method_update_with_all_params(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.update(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_category="RelationalDatabase",
+ datahub_urn="datahub_urn",
description="description",
known_connector_type="known_connector_type",
name="name",
+ nango_connection_id="nango_connection_id",
+ nango_integration_id="nango_integration_id",
+ team_visibility="Team",
usage_snippet_override="usage_snippet_override",
+ user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
)
assert connector is None
From 0b97c19265b6bd0d88bb70c350263a2ce0e7ac28 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Feb 2026 20:32:13 +0000
Subject: [PATCH 020/105] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c3dc0024c..57f7760d0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-711c47583ac185bb9eae3a8726ca87a38b6b68d10ae8bc59ac2170486d23d9c5.yml
-openapi_spec_hash: a88c245384bed8ddefced34c097b77af
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-571a393a85cc1263a5c4e0d89326330beb6023e782c4e4b0ae68d843fba68640.yml
+openapi_spec_hash: 0b59fd0bd5dd0605102f6d97807cdf29
config_hash: 56f5badddee4e07ac212faa9dba21141
From ffda5ed618ac602e2e9287512f4b0876c421d741 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 18 Feb 2026 22:21:34 +0000
Subject: [PATCH 021/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/connector_get_response.py | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 57f7760d0..da0a882be 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-571a393a85cc1263a5c4e0d89326330beb6023e782c4e4b0ae68d843fba68640.yml
-openapi_spec_hash: 0b59fd0bd5dd0605102f6d97807cdf29
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9da8910a7bb39a8d6a721f9c44bc5f283297260af52e072acbac7f69a9d251a0.yml
+openapi_spec_hash: bfbeffcc3790b108a4d3f6a87aa76506
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/types/connector_get_response.py b/src/structify/types/connector_get_response.py
index f1ec3ee59..c566b553e 100644
--- a/src/structify/types/connector_get_response.py
+++ b/src/structify/types/connector_get_response.py
@@ -23,3 +23,5 @@ class ConnectorGetResponseSecret(BaseModel):
class ConnectorGetResponse(Connector):
secrets: List[ConnectorGetResponseSecret]
+
+ shared_user_ids: List[str]
From 3e01edfbfeb5703f1e52a8d5fd7d7825a49adec3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Feb 2026 05:18:55 +0000
Subject: [PATCH 022/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/workflow_schedule_info.py | 7 +++++++
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index da0a882be..fc0c3bac6 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9da8910a7bb39a8d6a721f9c44bc5f283297260af52e072acbac7f69a9d251a0.yml
-openapi_spec_hash: bfbeffcc3790b108a4d3f6a87aa76506
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-944dbe109eff66b70a4a1d54c139ce75ca68a175268dcb7f08b5a0dbd01ab634.yml
+openapi_spec_hash: f358620d1937d9ee1a92591531d2ecb6
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/types/workflow_schedule_info.py b/src/structify/types/workflow_schedule_info.py
index a0e9bf44d..eae143b7e 100644
--- a/src/structify/types/workflow_schedule_info.py
+++ b/src/structify/types/workflow_schedule_info.py
@@ -3,6 +3,7 @@
from typing import Optional
from .._models import BaseModel
+from .chat_visibility import ChatVisibility
__all__ = ["WorkflowScheduleInfo"]
@@ -21,3 +22,9 @@ class WorkflowScheduleInfo(BaseModel):
git_commit_hash: Optional[str] = None
next_run_time: Optional[str] = None
+
+ owner_email: Optional[str] = None
+
+ updated_at: Optional[str] = None
+
+ visibility: Optional[ChatVisibility] = None
From d28fc512323f5c7eecd56e086a6894c4e2ea2794 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Feb 2026 17:12:45 +0000
Subject: [PATCH 023/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/chat.py | 8 ++++----
src/structify/types/chat_session.py | 4 ++--
src/structify/types/chat_session_with_messages.py | 4 ++--
src/structify/types/chat_update_session_params.py | 4 ++--
src/structify/types/get_chat_session_response.py | 4 ++--
tests/api_resources/test_chat.py | 4 ++--
7 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index fc0c3bac6..51e0f441f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-944dbe109eff66b70a4a1d54c139ce75ca68a175268dcb7f08b5a0dbd01ab634.yml
-openapi_spec_hash: f358620d1937d9ee1a92591531d2ecb6
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-200b7ecac4ccc9950171f45e4d13c90938e48e7750eb08a74381d3e3aee824c2.yml
+openapi_spec_hash: b9ca1d37cc4e578fa3ee62f16e8d2055
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 92074d1a3..e8fe4101d 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -899,10 +899,10 @@ def update_session(
self,
session_id: str,
*,
+ message_head: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
project_id: Optional[str] | Omit = omit,
skip_confirmations: Optional[bool] | Omit = omit,
- user_message_head: 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,
@@ -926,10 +926,10 @@ def update_session(
f"/chat/sessions/{session_id}",
body=maybe_transform(
{
+ "message_head": message_head,
"name": name,
"project_id": project_id,
"skip_confirmations": skip_confirmations,
- "user_message_head": user_message_head,
},
chat_update_session_params.ChatUpdateSessionParams,
),
@@ -1852,10 +1852,10 @@ async def update_session(
self,
session_id: str,
*,
+ message_head: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
project_id: Optional[str] | Omit = omit,
skip_confirmations: Optional[bool] | Omit = omit,
- user_message_head: 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,
@@ -1879,10 +1879,10 @@ async def update_session(
f"/chat/sessions/{session_id}",
body=await async_maybe_transform(
{
+ "message_head": message_head,
"name": name,
"project_id": project_id,
"skip_confirmations": skip_confirmations,
- "user_message_head": user_message_head,
},
chat_update_session_params.ChatUpdateSessionParams,
),
diff --git a/src/structify/types/chat_session.py b/src/structify/types/chat_session.py
index 9e28ab660..faa486f01 100644
--- a/src/structify/types/chat_session.py
+++ b/src/structify/types/chat_session.py
@@ -36,6 +36,8 @@ class ChatSession(BaseModel):
config_proto: Optional[object] = None
+ message_head: Optional[str] = None
+
name: Optional[str] = None
project_id: Optional[str] = None
@@ -51,5 +53,3 @@ class ChatSession(BaseModel):
teams_conversation_id: Optional[str] = None
teams_tenant_id: Optional[str] = None
-
- user_message_head: Optional[str] = None
diff --git a/src/structify/types/chat_session_with_messages.py b/src/structify/types/chat_session_with_messages.py
index 8329df246..0eb225721 100644
--- a/src/structify/types/chat_session_with_messages.py
+++ b/src/structify/types/chat_session_with_messages.py
@@ -89,6 +89,8 @@ class ChatSessionWithMessages(BaseModel):
latest_workflow_session_id: Optional[str] = None
+ message_head: Optional[str] = None
+
name: Optional[str] = None
project_id: Optional[str] = None
@@ -104,5 +106,3 @@ class ChatSessionWithMessages(BaseModel):
teams_conversation_id: Optional[str] = None
teams_tenant_id: Optional[str] = None
-
- user_message_head: Optional[str] = None
diff --git a/src/structify/types/chat_update_session_params.py b/src/structify/types/chat_update_session_params.py
index 8a0f005d4..b7f62a070 100644
--- a/src/structify/types/chat_update_session_params.py
+++ b/src/structify/types/chat_update_session_params.py
@@ -9,10 +9,10 @@
class ChatUpdateSessionParams(TypedDict, total=False):
+ message_head: Optional[str]
+
name: Optional[str]
project_id: Optional[str]
skip_confirmations: Optional[bool]
-
- user_message_head: Optional[str]
diff --git a/src/structify/types/get_chat_session_response.py b/src/structify/types/get_chat_session_response.py
index f7e7b5738..372c43c85 100644
--- a/src/structify/types/get_chat_session_response.py
+++ b/src/structify/types/get_chat_session_response.py
@@ -70,6 +70,8 @@ class Session(BaseModel):
latest_workflow_session_id: Optional[str] = None
+ message_head: Optional[str] = None
+
name: Optional[str] = None
project_id: Optional[str] = None
@@ -86,8 +88,6 @@ class Session(BaseModel):
teams_tenant_id: Optional[str] = None
- user_message_head: Optional[str] = None
-
workflow_schedule_id: Optional[str] = None
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 5a3326e3f..d3d4e4eff 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -959,10 +959,10 @@ def test_method_update_session(self, client: Structify) -> None:
def test_method_update_session_with_all_params(self, client: Structify) -> None:
chat = client.chat.update_session(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ message_head="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
name="name",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
skip_confirmations=True,
- user_message_head="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ChatSession, chat, path=["response"])
@@ -2008,10 +2008,10 @@ async def test_method_update_session(self, async_client: AsyncStructify) -> None
async def test_method_update_session_with_all_params(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.update_session(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ message_head="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
name="name",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
skip_confirmations=True,
- user_message_head="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ChatSession, chat, path=["response"])
From 06d6f5872b86da5de923d0657b0c340f312d42ec Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Feb 2026 21:39:12 +0000
Subject: [PATCH 024/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connectors/connectors.py | 4 ++++
src/structify/types/connector.py | 4 +++-
src/structify/types/connector_update_params.py | 2 ++
tests/api_resources/test_connectors.py | 2 ++
5 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 51e0f441f..7bd4e4363 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-200b7ecac4ccc9950171f45e4d13c90938e48e7750eb08a74381d3e3aee824c2.yml
-openapi_spec_hash: b9ca1d37cc4e578fa3ee62f16e8d2055
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-b1429bc6a7b1bb3a114260dee68a5df7dd272cb41f98cf930f380de48c009f65.yml
+openapi_spec_hash: 57af5cd10d1a5fee8d366320146e2067
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 47af88146..0aa1b276c 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -151,6 +151,7 @@ def update(
name: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
+ oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
user_ids: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -185,6 +186,7 @@ def update(
"name": name,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
+ "oauth_scopes": oauth_scopes,
"team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
"user_ids": user_ids,
@@ -1259,6 +1261,7 @@ async def update(
name: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
+ oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
user_ids: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -1293,6 +1296,7 @@ async def update(
"name": name,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
+ "oauth_scopes": oauth_scopes,
"team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
"user_ids": user_ids,
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 1a0441d0a..57b396a46 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -1,6 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import Optional
+from typing import List, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -44,4 +44,6 @@ class Connector(BaseModel):
nango_integration_id: Optional[str] = None
+ oauth_scopes: Optional[List[Optional[str]]] = None
+
usage_snippet_override: Optional[str] = None
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index 0b06e1ff7..c1b123fb0 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -26,6 +26,8 @@ class ConnectorUpdateParams(TypedDict, total=False):
nango_integration_id: Optional[str]
+ oauth_scopes: Optional[SequenceNotStr[Optional[str]]]
+
team_visibility: Optional[Literal["Team", "Private"]]
usage_snippet_override: Optional[str]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index ceb0e89dd..803817150 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -102,6 +102,7 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
name="name",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
+ oauth_scopes=["string"],
team_visibility="Team",
usage_snippet_override="usage_snippet_override",
user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
@@ -1366,6 +1367,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
name="name",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
+ oauth_scopes=["string"],
team_visibility="Team",
usage_snippet_override="usage_snippet_override",
user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
From 46fc19ded10bfac99a76d2c3a4a3f08d271c25e5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Feb 2026 00:16:10 +0000
Subject: [PATCH 025/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/chat_visibility.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 7bd4e4363..b1b73bf90 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-b1429bc6a7b1bb3a114260dee68a5df7dd272cb41f98cf930f380de48c009f65.yml
-openapi_spec_hash: 57af5cd10d1a5fee8d366320146e2067
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0fe3396cd506b5584cbc94eddbe8c4fb750781948991d7147d876feb8532b37a.yml
+openapi_spec_hash: c0fbe7bdbdb7c5acba691c7b156c0bf6
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/types/chat_visibility.py b/src/structify/types/chat_visibility.py
index 562a18934..d53c3721a 100644
--- a/src/structify/types/chat_visibility.py
+++ b/src/structify/types/chat_visibility.py
@@ -4,4 +4,4 @@
__all__ = ["ChatVisibility"]
-ChatVisibility: TypeAlias = Literal["private", "shared_with_team", "public"]
+ChatVisibility: TypeAlias = Literal["private", "shared_with_team", "shared_with_team_view", "public"]
From 8be62b67db9556a1a8dbd7f7cc5080ae2e164cde Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Feb 2026 01:35:15 +0000
Subject: [PATCH 026/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/sandbox.py | 4 +++-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index b1b73bf90..80be8b8ed 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0fe3396cd506b5584cbc94eddbe8c4fb750781948991d7147d876feb8532b37a.yml
-openapi_spec_hash: c0fbe7bdbdb7c5acba691c7b156c0bf6
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-78216a10dd35faf75b132b12a516d0db4ac0a6e5b8ed992f684eb6350ffc31ad.yml
+openapi_spec_hash: 1e15b64ce6a5c468aa92bc3b03a276b8
config_hash: 56f5badddee4e07ac212faa9dba21141
diff --git a/src/structify/types/sandbox.py b/src/structify/types/sandbox.py
index 47925e3a1..ce0ca3756 100644
--- a/src/structify/types/sandbox.py
+++ b/src/structify/types/sandbox.py
@@ -18,7 +18,7 @@ class Sandbox(BaseModel):
provider_id: str
- status: Literal["alive", "terminated"]
+ status: Literal["alive", "paused", "terminated"]
team_id: str
@@ -32,6 +32,8 @@ class Sandbox(BaseModel):
latest_node: Optional[str] = None
+ resumed_at: Optional[datetime] = None
+
session_id: Optional[str] = None
tunnel_url: Optional[str] = None
From e3ad58e6c063c306aa5e481ec97c74cf4e3ba313 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Feb 2026 04:47:47 +0000
Subject: [PATCH 027/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
README.md | 7 +-
api.md | 12 +-
src/structify/resources/chat.py | 529 +++++++++++++----
src/structify/resources/sessions.py | 4 -
src/structify/types/__init__.py | 9 +-
.../types/chat_create_session_params.py | 2 -
...ms.py => chat_delete_input_file_params.py} | 6 +-
....py => chat_delete_input_file_response.py} | 4 +-
src/structify/types/chat_event.py | 6 +
.../chat_get_session_timeline_response.py | 2 +-
.../types/chat_list_input_files_response.py | 24 +
.../types/chat_load_input_files_params.py | 15 +
.../types/chat_load_input_files_response.py | 14 +
.../types/chat_session_with_messages.py | 2 +-
.../types/chat_upload_input_file_params.py | 17 +
.../types/chat_upload_input_file_response.py | 23 +
.../types/get_chat_session_response.py | 2 +
.../types/session_create_session_params.py | 2 -
src/structify/types/workflow_session.py | 2 -
tests/api_resources/test_chat.py | 555 ++++++++++++++----
tests/api_resources/test_sessions.py | 8 -
22 files changed, 994 insertions(+), 259 deletions(-)
rename src/structify/types/{chat_delete_files_params.py => chat_delete_input_file_params.py} (60%)
rename src/structify/types/{chat_delete_files_response.py => chat_delete_input_file_response.py} (62%)
create mode 100644 src/structify/types/chat_list_input_files_response.py
create mode 100644 src/structify/types/chat_load_input_files_params.py
create mode 100644 src/structify/types/chat_load_input_files_response.py
create mode 100644 src/structify/types/chat_upload_input_file_params.py
create mode 100644 src/structify/types/chat_upload_input_file_response.py
diff --git a/.stats.yml b/.stats.yml
index 80be8b8ed..166066f1d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 235
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-78216a10dd35faf75b132b12a516d0db4ac0a6e5b8ed992f684eb6350ffc31ad.yml
-openapi_spec_hash: 1e15b64ce6a5c468aa92bc3b03a276b8
-config_hash: 56f5badddee4e07ac212faa9dba21141
+configured_endpoints: 238
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-13ee7c696d4028e178d153bbfd5fc16b6c9e42ce7e0e491f08384258f7a04925.yml
+openapi_spec_hash: e51ffb08d0edf6cc858b350f0615ebf4
+config_hash: ad7129c86de685d16828862aa96a884e
diff --git a/README.md b/README.md
index aceab7a36..2a8ad2bb6 100644
--- a/README.md
+++ b/README.md
@@ -195,10 +195,11 @@ from structify import Structify
client = Structify()
-client.documents.upload(
+client.chat.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
content=Path("/path/to/file"),
- file_type="Text",
- path=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
)
```
diff --git a/api.md b/api.md
index f244b9914..f6b046c0a 100644
--- a/api.md
+++ b/api.md
@@ -119,13 +119,16 @@ from structify.types import (
UpdateVisibilityResponse,
ChatAddGitCommitResponse,
ChatCopyNodeOutputByCodeHashResponse,
- ChatDeleteFilesResponse,
+ ChatDeleteInputFileResponse,
ChatGetGitCommitResponse,
ChatGetPartialChatsResponse,
ChatGetSessionTimelineResponse,
+ ChatListInputFilesResponse,
ChatListTemplatesResponse,
ChatLoadFilesResponse,
+ ChatLoadInputFilesResponse,
ChatRevertToCommitResponse,
+ ChatUploadInputFileResponse,
)
```
@@ -133,12 +136,11 @@ Methods:
- client.chat.add_collaborator(chat_id, \*\*params) -> None
- client.chat.add_git_commit(session_id, \*\*params) -> ChatAddGitCommitResponse
-- client.chat.admin_get_chat_prompt(session_id) -> ChatPrompt
- client.chat.admin_issue_found(chat_id, \*\*params) -> AdminIssueFoundResponse
- client.chat.copy(\*\*params) -> ChatSessionWithMessages
- client.chat.copy_node_output_by_code_hash(session_id, \*\*params) -> str
- client.chat.create_session(\*\*params) -> CreateChatSessionResponse
-- client.chat.delete_files(chat_id, \*\*params) -> ChatDeleteFilesResponse
+- client.chat.delete_input_file(chat_id, \*\*params) -> ChatDeleteInputFileResponse
- client.chat.delete_session(session_id) -> DeleteChatSessionResponse
- client.chat.get_dependencies(session_id) -> GetDependenciesResponse
- client.chat.get_git_commit(commit_hash, \*, chat_id) -> ChatGetGitCommitResponse
@@ -147,15 +149,19 @@ Methods:
- client.chat.get_session_timeline(session_id) -> ChatGetSessionTimelineResponse
- client.chat.grant_admin_override(chat_id, \*\*params) -> AdminGrantAccessResponse
- client.chat.list_collaborators(chat_id) -> ListCollaboratorsResponse
+- client.chat.list_input_files(chat_id) -> ChatListInputFilesResponse
- client.chat.list_sessions(\*\*params) -> ListChatSessionsResponse
- client.chat.list_templates() -> ChatListTemplatesResponse
- client.chat.load_files(\*\*params) -> ChatLoadFilesResponse
+- client.chat.load_input_file(filename, \*, chat_id) -> BinaryAPIResponse
+- client.chat.load_input_files(chat_id, \*\*params) -> ChatLoadInputFilesResponse
- client.chat.make_permanent(session_id) -> None
- client.chat.remove_collaborator(user_id, \*, chat_id) -> None
- client.chat.revert_to_commit(session_id, \*\*params) -> ChatRevertToCommitResponse
- client.chat.update_session(session_id, \*\*params) -> ChatSession
- client.chat.update_session_favorite(session_id, \*\*params) -> ChatSession
- client.chat.update_visibility(session_id, \*\*params) -> UpdateVisibilityResponse
+- client.chat.upload_input_file(chat_id, \*\*params) -> ChatUploadInputFileResponse
# Teams
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index e8fe4101d..ee70026a8 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -2,7 +2,8 @@
from __future__ import annotations
-from typing import Optional
+from typing import Union, Mapping, Optional, cast
+from datetime import datetime
import httpx
@@ -11,31 +12,40 @@
ChatSessionRole,
chat_copy_params,
chat_load_files_params,
- chat_delete_files_params,
chat_list_sessions_params,
chat_add_git_commit_params,
chat_create_session_params,
chat_update_session_params,
chat_add_collaborator_params,
+ chat_load_input_files_params,
chat_revert_to_commit_params,
chat_admin_issue_found_params,
+ chat_delete_input_file_params,
chat_update_visibility_params,
+ chat_upload_input_file_params,
chat_grant_admin_override_params,
chat_update_session_favorite_params,
chat_copy_node_output_by_code_hash_params,
)
-from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr, omit, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
+ to_custom_raw_response_wrapper,
async_to_streamed_response_wrapper,
+ to_custom_streamed_response_wrapper,
+ async_to_custom_raw_response_wrapper,
+ async_to_custom_streamed_response_wrapper,
)
from .._base_client import make_request_options
-from ..types.chat_prompt import ChatPrompt
from ..types.chat_session import ChatSession
from ..types.chat_visibility import ChatVisibility
from ..types.chat_session_role import ChatSessionRole
@@ -43,7 +53,6 @@
from ..types.get_chat_session_response import GetChatSessionResponse
from ..types.get_dependencies_response import GetDependenciesResponse
from ..types.admin_issue_found_response import AdminIssueFoundResponse
-from ..types.chat_delete_files_response import ChatDeleteFilesResponse
from ..types.chat_session_with_messages import ChatSessionWithMessages
from ..types.update_visibility_response import UpdateVisibilityResponse
from ..types.admin_grant_access_response import AdminGrantAccessResponse
@@ -54,8 +63,12 @@
from ..types.chat_list_templates_response import ChatListTemplatesResponse
from ..types.create_chat_session_response import CreateChatSessionResponse
from ..types.delete_chat_session_response import DeleteChatSessionResponse
+from ..types.chat_list_input_files_response import ChatListInputFilesResponse
+from ..types.chat_load_input_files_response import ChatLoadInputFilesResponse
from ..types.chat_revert_to_commit_response import ChatRevertToCommitResponse
+from ..types.chat_delete_input_file_response import ChatDeleteInputFileResponse
from ..types.chat_get_partial_chats_response import ChatGetPartialChatsResponse
+from ..types.chat_upload_input_file_response import ChatUploadInputFileResponse
from ..types.chat_get_session_timeline_response import ChatGetSessionTimelineResponse
__all__ = ["ChatResource", "AsyncChatResource"]
@@ -159,40 +172,6 @@ def add_git_commit(
cast_to=ChatAddGitCommitResponse,
)
- def admin_get_chat_prompt(
- self,
- session_id: str,
- *,
- # 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,
- ) -> ChatPrompt:
- """
- Get the actual chat prompt that the LLM will see on its next message (admin
- only)
-
- Args:
- 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
- """
- if not session_id:
- raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
- return self._get(
- f"/chat/sessions/{session_id}/admin/chat_prompt",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ChatPrompt,
- )
-
def admin_issue_found(
self,
chat_id: str,
@@ -326,7 +305,6 @@ def create_session(
team_id: str,
config: Optional[chat_create_session_params.Config] | Omit = omit,
ephemeral: Optional[bool] | Omit = omit,
- initial_message: Optional[str] | Omit = omit,
project_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -356,7 +334,6 @@ def create_session(
"team_id": team_id,
"config": config,
"ephemeral": ephemeral,
- "initial_message": initial_message,
"project_id": project_id,
},
chat_create_session_params.ChatCreateSessionParams,
@@ -367,20 +344,20 @@ def create_session(
cast_to=CreateChatSessionResponse,
)
- def delete_files(
+ def delete_input_file(
self,
chat_id: str,
*,
- paths: SequenceNotStr[str],
+ filenames: SequenceNotStr[str],
# 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,
- ) -> ChatDeleteFilesResponse:
+ ) -> ChatDeleteInputFileResponse:
"""
- Delete files from a chat session's git repository
+ Delete input files from a chat session
Args:
extra_headers: Send extra headers
@@ -394,12 +371,12 @@ def delete_files(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._post(
- f"/chat/files/delete/{chat_id}",
- body=maybe_transform({"paths": paths}, chat_delete_files_params.ChatDeleteFilesParams),
+ f"/chat/input-files/delete/{chat_id}",
+ body=maybe_transform({"filenames": filenames}, chat_delete_input_file_params.ChatDeleteInputFileParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ChatDeleteFilesResponse,
+ cast_to=ChatDeleteInputFileResponse,
)
def delete_session(
@@ -680,6 +657,39 @@ def list_collaborators(
cast_to=ListCollaboratorsResponse,
)
+ def list_input_files(
+ self,
+ chat_id: str,
+ *,
+ # 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,
+ ) -> ChatListInputFilesResponse:
+ """
+ List input files for a chat session
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ return self._get(
+ f"/chat/input-files/list/{chat_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatListInputFilesResponse,
+ )
+
def list_sessions(
self,
*,
@@ -789,6 +799,83 @@ def load_files(
cast_to=ChatLoadFilesResponse,
)
+ def load_input_file(
+ self,
+ filename: str,
+ *,
+ chat_id: str,
+ # 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,
+ ) -> BinaryAPIResponse:
+ """
+ Download a single input file by chat ID and filename
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ if not filename:
+ raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return self._get(
+ f"/chat/input-files/download/{chat_id}/{filename}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BinaryAPIResponse,
+ )
+
+ def load_input_files(
+ self,
+ chat_id: str,
+ *,
+ 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,
+ ) -> ChatLoadInputFilesResponse:
+ """
+ Pass `since` query param (RFC 3339 timestamp) to only get files created/updated
+ after that time. The response includes `latest_timestamp` which can be passed as
+ `since` on the next call.
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ return self._get(
+ f"/chat/input-files/download-all/{chat_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform({"since": since}, chat_load_input_files_params.ChatLoadInputFilesParams),
+ ),
+ cast_to=ChatLoadInputFilesResponse,
+ )
+
def make_permanent(
self,
session_id: str,
@@ -1009,6 +1096,56 @@ def update_visibility(
cast_to=UpdateVisibilityResponse,
)
+ def upload_input_file(
+ self,
+ chat_id: str,
+ *,
+ content: FileTypes,
+ content_type: str,
+ file_name: str,
+ # 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,
+ ) -> ChatUploadInputFileResponse:
+ """
+ Upload an input file to a chat session's bucket storage
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "content_type": content_type,
+ "file_name": file_name,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ f"/chat/input-files/upload/{chat_id}",
+ body=maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatUploadInputFileResponse,
+ )
+
class AsyncChatResource(AsyncAPIResource):
@cached_property
@@ -1110,40 +1247,6 @@ async def add_git_commit(
cast_to=ChatAddGitCommitResponse,
)
- async def admin_get_chat_prompt(
- self,
- session_id: str,
- *,
- # 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,
- ) -> ChatPrompt:
- """
- Get the actual chat prompt that the LLM will see on its next message (admin
- only)
-
- Args:
- 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
- """
- if not session_id:
- raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
- return await self._get(
- f"/chat/sessions/{session_id}/admin/chat_prompt",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ChatPrompt,
- )
-
async def admin_issue_found(
self,
chat_id: str,
@@ -1277,7 +1380,6 @@ async def create_session(
team_id: str,
config: Optional[chat_create_session_params.Config] | Omit = omit,
ephemeral: Optional[bool] | Omit = omit,
- initial_message: Optional[str] | Omit = omit,
project_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1307,7 +1409,6 @@ async def create_session(
"team_id": team_id,
"config": config,
"ephemeral": ephemeral,
- "initial_message": initial_message,
"project_id": project_id,
},
chat_create_session_params.ChatCreateSessionParams,
@@ -1318,20 +1419,20 @@ async def create_session(
cast_to=CreateChatSessionResponse,
)
- async def delete_files(
+ async def delete_input_file(
self,
chat_id: str,
*,
- paths: SequenceNotStr[str],
+ filenames: SequenceNotStr[str],
# 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,
- ) -> ChatDeleteFilesResponse:
+ ) -> ChatDeleteInputFileResponse:
"""
- Delete files from a chat session's git repository
+ Delete input files from a chat session
Args:
extra_headers: Send extra headers
@@ -1345,12 +1446,14 @@ async def delete_files(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._post(
- f"/chat/files/delete/{chat_id}",
- body=await async_maybe_transform({"paths": paths}, chat_delete_files_params.ChatDeleteFilesParams),
+ f"/chat/input-files/delete/{chat_id}",
+ body=await async_maybe_transform(
+ {"filenames": filenames}, chat_delete_input_file_params.ChatDeleteInputFileParams
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ChatDeleteFilesResponse,
+ cast_to=ChatDeleteInputFileResponse,
)
async def delete_session(
@@ -1631,6 +1734,39 @@ async def list_collaborators(
cast_to=ListCollaboratorsResponse,
)
+ async def list_input_files(
+ self,
+ chat_id: str,
+ *,
+ # 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,
+ ) -> ChatListInputFilesResponse:
+ """
+ List input files for a chat session
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ return await self._get(
+ f"/chat/input-files/list/{chat_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatListInputFilesResponse,
+ )
+
async def list_sessions(
self,
*,
@@ -1740,6 +1876,85 @@ async def load_files(
cast_to=ChatLoadFilesResponse,
)
+ async def load_input_file(
+ self,
+ filename: str,
+ *,
+ chat_id: str,
+ # 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,
+ ) -> AsyncBinaryAPIResponse:
+ """
+ Download a single input file by chat ID and filename
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ if not filename:
+ raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return await self._get(
+ f"/chat/input-files/download/{chat_id}/{filename}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AsyncBinaryAPIResponse,
+ )
+
+ async def load_input_files(
+ self,
+ chat_id: str,
+ *,
+ 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,
+ ) -> ChatLoadInputFilesResponse:
+ """
+ Pass `since` query param (RFC 3339 timestamp) to only get files created/updated
+ after that time. The response includes `latest_timestamp` which can be passed as
+ `since` on the next call.
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ return await self._get(
+ f"/chat/input-files/download-all/{chat_id}",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"since": since}, chat_load_input_files_params.ChatLoadInputFilesParams
+ ),
+ ),
+ cast_to=ChatLoadInputFilesResponse,
+ )
+
async def make_permanent(
self,
session_id: str,
@@ -1964,6 +2179,56 @@ async def update_visibility(
cast_to=UpdateVisibilityResponse,
)
+ async def upload_input_file(
+ self,
+ chat_id: str,
+ *,
+ content: FileTypes,
+ content_type: str,
+ file_name: str,
+ # 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,
+ ) -> ChatUploadInputFileResponse:
+ """
+ Upload an input file to a chat session's bucket storage
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "content_type": content_type,
+ "file_name": file_name,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ f"/chat/input-files/upload/{chat_id}",
+ body=await async_maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatUploadInputFileResponse,
+ )
+
class ChatResourceWithRawResponse:
def __init__(self, chat: ChatResource) -> None:
@@ -1975,9 +2240,6 @@ def __init__(self, chat: ChatResource) -> None:
self.add_git_commit = to_raw_response_wrapper(
chat.add_git_commit,
)
- self.admin_get_chat_prompt = to_raw_response_wrapper(
- chat.admin_get_chat_prompt,
- )
self.admin_issue_found = to_raw_response_wrapper(
chat.admin_issue_found,
)
@@ -1990,8 +2252,8 @@ def __init__(self, chat: ChatResource) -> None:
self.create_session = to_raw_response_wrapper(
chat.create_session,
)
- self.delete_files = to_raw_response_wrapper(
- chat.delete_files,
+ self.delete_input_file = to_raw_response_wrapper(
+ chat.delete_input_file,
)
self.delete_session = to_raw_response_wrapper(
chat.delete_session,
@@ -2017,6 +2279,9 @@ def __init__(self, chat: ChatResource) -> None:
self.list_collaborators = to_raw_response_wrapper(
chat.list_collaborators,
)
+ self.list_input_files = to_raw_response_wrapper(
+ chat.list_input_files,
+ )
self.list_sessions = to_raw_response_wrapper(
chat.list_sessions,
)
@@ -2026,6 +2291,13 @@ def __init__(self, chat: ChatResource) -> None:
self.load_files = to_raw_response_wrapper(
chat.load_files,
)
+ self.load_input_file = to_custom_raw_response_wrapper(
+ chat.load_input_file,
+ BinaryAPIResponse,
+ )
+ self.load_input_files = to_raw_response_wrapper(
+ chat.load_input_files,
+ )
self.make_permanent = to_raw_response_wrapper(
chat.make_permanent,
)
@@ -2044,6 +2316,9 @@ def __init__(self, chat: ChatResource) -> None:
self.update_visibility = to_raw_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = to_raw_response_wrapper(
+ chat.upload_input_file,
+ )
class AsyncChatResourceWithRawResponse:
@@ -2056,9 +2331,6 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.add_git_commit = async_to_raw_response_wrapper(
chat.add_git_commit,
)
- self.admin_get_chat_prompt = async_to_raw_response_wrapper(
- chat.admin_get_chat_prompt,
- )
self.admin_issue_found = async_to_raw_response_wrapper(
chat.admin_issue_found,
)
@@ -2071,8 +2343,8 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.create_session = async_to_raw_response_wrapper(
chat.create_session,
)
- self.delete_files = async_to_raw_response_wrapper(
- chat.delete_files,
+ self.delete_input_file = async_to_raw_response_wrapper(
+ chat.delete_input_file,
)
self.delete_session = async_to_raw_response_wrapper(
chat.delete_session,
@@ -2098,6 +2370,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.list_collaborators = async_to_raw_response_wrapper(
chat.list_collaborators,
)
+ self.list_input_files = async_to_raw_response_wrapper(
+ chat.list_input_files,
+ )
self.list_sessions = async_to_raw_response_wrapper(
chat.list_sessions,
)
@@ -2107,6 +2382,13 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.load_files = async_to_raw_response_wrapper(
chat.load_files,
)
+ self.load_input_file = async_to_custom_raw_response_wrapper(
+ chat.load_input_file,
+ AsyncBinaryAPIResponse,
+ )
+ self.load_input_files = async_to_raw_response_wrapper(
+ chat.load_input_files,
+ )
self.make_permanent = async_to_raw_response_wrapper(
chat.make_permanent,
)
@@ -2125,6 +2407,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.update_visibility = async_to_raw_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = async_to_raw_response_wrapper(
+ chat.upload_input_file,
+ )
class ChatResourceWithStreamingResponse:
@@ -2137,9 +2422,6 @@ def __init__(self, chat: ChatResource) -> None:
self.add_git_commit = to_streamed_response_wrapper(
chat.add_git_commit,
)
- self.admin_get_chat_prompt = to_streamed_response_wrapper(
- chat.admin_get_chat_prompt,
- )
self.admin_issue_found = to_streamed_response_wrapper(
chat.admin_issue_found,
)
@@ -2152,8 +2434,8 @@ def __init__(self, chat: ChatResource) -> None:
self.create_session = to_streamed_response_wrapper(
chat.create_session,
)
- self.delete_files = to_streamed_response_wrapper(
- chat.delete_files,
+ self.delete_input_file = to_streamed_response_wrapper(
+ chat.delete_input_file,
)
self.delete_session = to_streamed_response_wrapper(
chat.delete_session,
@@ -2179,6 +2461,9 @@ def __init__(self, chat: ChatResource) -> None:
self.list_collaborators = to_streamed_response_wrapper(
chat.list_collaborators,
)
+ self.list_input_files = to_streamed_response_wrapper(
+ chat.list_input_files,
+ )
self.list_sessions = to_streamed_response_wrapper(
chat.list_sessions,
)
@@ -2188,6 +2473,13 @@ def __init__(self, chat: ChatResource) -> None:
self.load_files = to_streamed_response_wrapper(
chat.load_files,
)
+ self.load_input_file = to_custom_streamed_response_wrapper(
+ chat.load_input_file,
+ StreamedBinaryAPIResponse,
+ )
+ self.load_input_files = to_streamed_response_wrapper(
+ chat.load_input_files,
+ )
self.make_permanent = to_streamed_response_wrapper(
chat.make_permanent,
)
@@ -2206,6 +2498,9 @@ def __init__(self, chat: ChatResource) -> None:
self.update_visibility = to_streamed_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = to_streamed_response_wrapper(
+ chat.upload_input_file,
+ )
class AsyncChatResourceWithStreamingResponse:
@@ -2218,9 +2513,6 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.add_git_commit = async_to_streamed_response_wrapper(
chat.add_git_commit,
)
- self.admin_get_chat_prompt = async_to_streamed_response_wrapper(
- chat.admin_get_chat_prompt,
- )
self.admin_issue_found = async_to_streamed_response_wrapper(
chat.admin_issue_found,
)
@@ -2233,8 +2525,8 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.create_session = async_to_streamed_response_wrapper(
chat.create_session,
)
- self.delete_files = async_to_streamed_response_wrapper(
- chat.delete_files,
+ self.delete_input_file = async_to_streamed_response_wrapper(
+ chat.delete_input_file,
)
self.delete_session = async_to_streamed_response_wrapper(
chat.delete_session,
@@ -2260,6 +2552,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.list_collaborators = async_to_streamed_response_wrapper(
chat.list_collaborators,
)
+ self.list_input_files = async_to_streamed_response_wrapper(
+ chat.list_input_files,
+ )
self.list_sessions = async_to_streamed_response_wrapper(
chat.list_sessions,
)
@@ -2269,6 +2564,13 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.load_files = async_to_streamed_response_wrapper(
chat.load_files,
)
+ self.load_input_file = async_to_custom_streamed_response_wrapper(
+ chat.load_input_file,
+ AsyncStreamedBinaryAPIResponse,
+ )
+ self.load_input_files = async_to_streamed_response_wrapper(
+ chat.load_input_files,
+ )
self.make_permanent = async_to_streamed_response_wrapper(
chat.make_permanent,
)
@@ -2287,3 +2589,6 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.update_visibility = async_to_streamed_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = async_to_streamed_response_wrapper(
+ chat.upload_input_file,
+ )
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 820100c79..38180878e 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -120,7 +120,6 @@ def create_session(
self,
*,
chat_session_id: str,
- git_commit: str,
parent_chat_message_id: Optional[str] | Omit = omit,
workflow_schedule_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.
@@ -145,7 +144,6 @@ def create_session(
body=maybe_transform(
{
"chat_session_id": chat_session_id,
- "git_commit": git_commit,
"parent_chat_message_id": parent_chat_message_id,
"workflow_schedule_id": workflow_schedule_id,
},
@@ -830,7 +828,6 @@ async def create_session(
self,
*,
chat_session_id: str,
- git_commit: str,
parent_chat_message_id: Optional[str] | Omit = omit,
workflow_schedule_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.
@@ -855,7 +852,6 @@ async def create_session(
body=await async_maybe_transform(
{
"chat_session_id": chat_session_id,
- "git_commit": git_commit,
"parent_chat_message_id": parent_chat_message_id,
"workflow_schedule_id": workflow_schedule_id,
},
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 3cacb0784..8a1d889a2 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -166,7 +166,6 @@
from .entity_summarize_params import EntitySummarizeParams as EntitySummarizeParams
from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
-from .chat_delete_files_params import ChatDeleteFilesParams as ChatDeleteFilesParams
from .chat_load_files_response import ChatLoadFilesResponse as ChatLoadFilesResponse
from .connector_explore_params import ConnectorExploreParams as ConnectorExploreParams
from .connector_store_response import ConnectorStoreResponse as ConnectorStoreResponse
@@ -199,7 +198,6 @@
from .admin_issue_found_response import AdminIssueFoundResponse as AdminIssueFoundResponse
from .chat_add_git_commit_params import ChatAddGitCommitParams as ChatAddGitCommitParams
from .chat_create_session_params import ChatCreateSessionParams as ChatCreateSessionParams
-from .chat_delete_files_response import ChatDeleteFilesResponse as ChatDeleteFilesResponse
from .chat_session_with_messages import ChatSessionWithMessages as ChatSessionWithMessages
from .chat_update_session_params import ChatUpdateSessionParams as ChatUpdateSessionParams
from .connector_credential_field import ConnectorCredentialField as ConnectorCredentialField
@@ -236,6 +234,7 @@
from .chat_add_git_commit_response import ChatAddGitCommitResponse as ChatAddGitCommitResponse
from .chat_get_git_commit_response import ChatGetGitCommitResponse as ChatGetGitCommitResponse
from .chat_list_templates_response import ChatListTemplatesResponse as ChatListTemplatesResponse
+from .chat_load_input_files_params import ChatLoadInputFilesParams as ChatLoadInputFilesParams
from .chat_revert_to_commit_params import ChatRevertToCommitParams as ChatRevertToCommitParams
from .connector_summaries_response import ConnectorSummariesResponse as ConnectorSummariesResponse
from .create_chat_session_response import CreateChatSessionResponse as CreateChatSessionResponse
@@ -246,7 +245,9 @@
from .structure_is_complete_params import StructureIsCompleteParams as StructureIsCompleteParams
from .structure_run_async_response import StructureRunAsyncResponse as StructureRunAsyncResponse
from .chat_admin_issue_found_params import ChatAdminIssueFoundParams as ChatAdminIssueFoundParams
+from .chat_delete_input_file_params import ChatDeleteInputFileParams as ChatDeleteInputFileParams
from .chat_update_visibility_params import ChatUpdateVisibilityParams as ChatUpdateVisibilityParams
+from .chat_upload_input_file_params import ChatUploadInputFileParams as ChatUploadInputFileParams
from .connector_catalog_list_params import ConnectorCatalogListParams as ConnectorCatalogListParams
from .connector_update_table_params import ConnectorUpdateTableParams as ConnectorUpdateTableParams
from .delete_schema_object_response import DeleteSchemaObjectResponse as DeleteSchemaObjectResponse
@@ -258,6 +259,8 @@
from .structure_job_status_response import StructureJobStatusResponse as StructureJobStatusResponse
from .team_accept_invitation_params import TeamAcceptInvitationParams as TeamAcceptInvitationParams
from .team_cancel_invitation_params import TeamCancelInvitationParams as TeamCancelInvitationParams
+from .chat_list_input_files_response import ChatListInputFilesResponse as ChatListInputFilesResponse
+from .chat_load_input_files_response import ChatLoadInputFilesResponse as ChatLoadInputFilesResponse
from .chat_revert_to_commit_response import ChatRevertToCommitResponse as ChatRevertToCommitResponse
from .connector_catalog_with_methods import ConnectorCatalogWithMethods as ConnectorCatalogWithMethods
from .connector_create_secret_params import ConnectorCreateSecretParams as ConnectorCreateSecretParams
@@ -272,7 +275,9 @@
from .team_update_member_role_params import TeamUpdateMemberRoleParams as TeamUpdateMemberRoleParams
from .workflow_node_execution_status import WorkflowNodeExecutionStatus as WorkflowNodeExecutionStatus
from .workflow_schedule_pause_params import WorkflowSchedulePauseParams as WorkflowSchedulePauseParams
+from .chat_delete_input_file_response import ChatDeleteInputFileResponse as ChatDeleteInputFileResponse
from .chat_get_partial_chats_response import ChatGetPartialChatsResponse as ChatGetPartialChatsResponse
+from .chat_upload_input_file_response import ChatUploadInputFileResponse as ChatUploadInputFileResponse
from .connector_catalog_list_response import ConnectorCatalogListResponse as ConnectorCatalogListResponse
from .entity_update_property_response import EntityUpdatePropertyResponse as EntityUpdatePropertyResponse
from .session_edit_node_output_params import SessionEditNodeOutputParams as SessionEditNodeOutputParams
diff --git a/src/structify/types/chat_create_session_params.py b/src/structify/types/chat_create_session_params.py
index b7c894703..da5dc01a8 100644
--- a/src/structify/types/chat_create_session_params.py
+++ b/src/structify/types/chat_create_session_params.py
@@ -16,8 +16,6 @@ class ChatCreateSessionParams(TypedDict, total=False):
ephemeral: Optional[bool]
- initial_message: Optional[str]
-
project_id: Optional[str]
diff --git a/src/structify/types/chat_delete_files_params.py b/src/structify/types/chat_delete_input_file_params.py
similarity index 60%
rename from src/structify/types/chat_delete_files_params.py
rename to src/structify/types/chat_delete_input_file_params.py
index ed4fcfadc..9b9c5e0e8 100644
--- a/src/structify/types/chat_delete_files_params.py
+++ b/src/structify/types/chat_delete_input_file_params.py
@@ -6,8 +6,8 @@
from .._types import SequenceNotStr
-__all__ = ["ChatDeleteFilesParams"]
+__all__ = ["ChatDeleteInputFileParams"]
-class ChatDeleteFilesParams(TypedDict, total=False):
- paths: Required[SequenceNotStr[str]]
+class ChatDeleteInputFileParams(TypedDict, total=False):
+ filenames: Required[SequenceNotStr[str]]
diff --git a/src/structify/types/chat_delete_files_response.py b/src/structify/types/chat_delete_input_file_response.py
similarity index 62%
rename from src/structify/types/chat_delete_files_response.py
rename to src/structify/types/chat_delete_input_file_response.py
index c075f48c7..b0c00de63 100644
--- a/src/structify/types/chat_delete_files_response.py
+++ b/src/structify/types/chat_delete_input_file_response.py
@@ -2,8 +2,8 @@
from .._models import BaseModel
-__all__ = ["ChatDeleteFilesResponse"]
+__all__ = ["ChatDeleteInputFileResponse"]
-class ChatDeleteFilesResponse(BaseModel):
+class ChatDeleteInputFileResponse(BaseModel):
files_deleted: int
diff --git a/src/structify/types/chat_event.py b/src/structify/types/chat_event.py
index e44f40a4c..60369bfd7 100644
--- a/src/structify/types/chat_event.py
+++ b/src/structify/types/chat_event.py
@@ -35,6 +35,7 @@
"AttachedFileAttachedFile",
"ConnectorRequest",
"ConnectorRequestConnectorRequest",
+ "UserInterrupted",
]
@@ -185,6 +186,10 @@ class ConnectorRequest(BaseModel):
connector_request: ConnectorRequestConnectorRequest = FieldInfo(alias="ConnectorRequest")
+class UserInterrupted(BaseModel):
+ user_interrupted: object = FieldInfo(alias="UserInterrupted")
+
+
ChatEvent: TypeAlias = Union[
TextMessage,
Thinking,
@@ -197,4 +202,5 @@ class ConnectorRequest(BaseModel):
ReviewRequest,
AttachedFile,
ConnectorRequest,
+ UserInterrupted,
]
diff --git a/src/structify/types/chat_get_session_timeline_response.py b/src/structify/types/chat_get_session_timeline_response.py
index e50cb2803..1d936f547 100644
--- a/src/structify/types/chat_get_session_timeline_response.py
+++ b/src/structify/types/chat_get_session_timeline_response.py
@@ -41,7 +41,7 @@ class TimelineMessage(BaseModel):
content_proto: Optional[object] = None
- git_commit_id: Optional[str] = None
+ git_hash: Optional[str] = None
previous_message_id: Optional[str] = None
diff --git a/src/structify/types/chat_list_input_files_response.py b/src/structify/types/chat_list_input_files_response.py
new file mode 100644
index 000000000..f8597a2d8
--- /dev/null
+++ b/src/structify/types/chat_list_input_files_response.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+from datetime import datetime
+from typing_extensions import TypeAlias
+
+from .._models import BaseModel
+
+__all__ = ["ChatListInputFilesResponse", "ChatListInputFilesResponseItem"]
+
+
+class ChatListInputFilesResponseItem(BaseModel):
+ chat_session_id: str
+
+ content_type: str
+
+ created_at: datetime
+
+ file_size: int
+
+ filename: str
+
+
+ChatListInputFilesResponse: TypeAlias = List[ChatListInputFilesResponseItem]
diff --git a/src/structify/types/chat_load_input_files_params.py b/src/structify/types/chat_load_input_files_params.py
new file mode 100644
index 000000000..ddc8dbd3a
--- /dev/null
+++ b/src/structify/types/chat_load_input_files_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from datetime import datetime
+from typing_extensions import Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["ChatLoadInputFilesParams"]
+
+
+class ChatLoadInputFilesParams(TypedDict, total=False):
+ since: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")]
diff --git a/src/structify/types/chat_load_input_files_response.py b/src/structify/types/chat_load_input_files_response.py
new file mode 100644
index 000000000..19c08da4a
--- /dev/null
+++ b/src/structify/types/chat_load_input_files_response.py
@@ -0,0 +1,14 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, Optional
+from datetime import datetime
+
+from .._models import BaseModel
+
+__all__ = ["ChatLoadInputFilesResponse"]
+
+
+class ChatLoadInputFilesResponse(BaseModel):
+ files: Dict[str, str]
+
+ latest_timestamp: Optional[datetime] = None
diff --git a/src/structify/types/chat_session_with_messages.py b/src/structify/types/chat_session_with_messages.py
index 0eb225721..c7e989c41 100644
--- a/src/structify/types/chat_session_with_messages.py
+++ b/src/structify/types/chat_session_with_messages.py
@@ -43,7 +43,7 @@ class Message(BaseModel):
content_proto: Optional[object] = None
- git_commit_id: Optional[str] = None
+ git_hash: Optional[str] = None
previous_message_id: Optional[str] = None
diff --git a/src/structify/types/chat_upload_input_file_params.py b/src/structify/types/chat_upload_input_file_params.py
new file mode 100644
index 000000000..a4a6eb732
--- /dev/null
+++ b/src/structify/types/chat_upload_input_file_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ChatUploadInputFileParams"]
+
+
+class ChatUploadInputFileParams(TypedDict, total=False):
+ content: Required[FileTypes]
+
+ content_type: Required[str]
+
+ file_name: Required[str]
diff --git a/src/structify/types/chat_upload_input_file_response.py b/src/structify/types/chat_upload_input_file_response.py
new file mode 100644
index 000000000..29e08729c
--- /dev/null
+++ b/src/structify/types/chat_upload_input_file_response.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from .._models import BaseModel
+
+__all__ = ["ChatUploadInputFileResponse", "File"]
+
+
+class File(BaseModel):
+ chat_session_id: str
+
+ content_type: str
+
+ created_at: datetime
+
+ file_size: int
+
+ filename: str
+
+
+class ChatUploadInputFileResponse(BaseModel):
+ file: File
diff --git a/src/structify/types/get_chat_session_response.py b/src/structify/types/get_chat_session_response.py
index 372c43c85..827dd24b3 100644
--- a/src/structify/types/get_chat_session_response.py
+++ b/src/structify/types/get_chat_session_response.py
@@ -38,6 +38,8 @@ class SessionMessage(BaseModel):
timestamp: datetime
+ git_hash: Optional[str] = None
+
previous_message_id: Optional[str] = None
diff --git a/src/structify/types/session_create_session_params.py b/src/structify/types/session_create_session_params.py
index d330ba7ec..2f08f0c31 100644
--- a/src/structify/types/session_create_session_params.py
+++ b/src/structify/types/session_create_session_params.py
@@ -11,8 +11,6 @@
class SessionCreateSessionParams(TypedDict, total=False):
chat_session_id: Required[str]
- git_commit: Required[str]
-
parent_chat_message_id: Optional[str]
workflow_schedule_id: Optional[str]
diff --git a/src/structify/types/workflow_session.py b/src/structify/types/workflow_session.py
index 55c559138..49284cb58 100644
--- a/src/structify/types/workflow_session.py
+++ b/src/structify/types/workflow_session.py
@@ -29,8 +29,6 @@ class WorkflowSession(BaseModel):
error_traceback: Optional[str] = None
- git_commit: Optional[str] = None
-
parent_chat_message_id: Optional[str] = None
workflow_schedule_id: Optional[str] = None
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index d3d4e4eff..ff4e531d3 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -5,17 +5,17 @@
import os
from typing import Any, cast
+import httpx
import pytest
+from respx import MockRouter
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
from structify.types import (
- ChatPrompt,
ChatSession,
ChatLoadFilesResponse,
GetChatSessionResponse,
AdminIssueFoundResponse,
- ChatDeleteFilesResponse,
ChatSessionWithMessages,
GetDependenciesResponse,
AdminGrantAccessResponse,
@@ -27,10 +27,21 @@
CreateChatSessionResponse,
DeleteChatSessionResponse,
ListCollaboratorsResponse,
+ ChatListInputFilesResponse,
+ ChatLoadInputFilesResponse,
ChatRevertToCommitResponse,
+ ChatDeleteInputFileResponse,
ChatGetPartialChatsResponse,
+ ChatUploadInputFileResponse,
ChatGetSessionTimelineResponse,
)
+from structify._utils import parse_datetime
+from structify._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -126,44 +137,6 @@ def test_path_params_add_git_commit(self, client: Structify) -> None:
commit_hash="commit_hash",
)
- @parametrize
- def test_method_admin_get_chat_prompt(self, client: Structify) -> None:
- chat = client.chat.admin_get_chat_prompt(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(ChatPrompt, chat, path=["response"])
-
- @parametrize
- def test_raw_response_admin_get_chat_prompt(self, client: Structify) -> None:
- response = client.chat.with_raw_response.admin_get_chat_prompt(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = response.parse()
- assert_matches_type(ChatPrompt, chat, path=["response"])
-
- @parametrize
- def test_streaming_response_admin_get_chat_prompt(self, client: Structify) -> None:
- with client.chat.with_streaming_response.admin_get_chat_prompt(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = response.parse()
- assert_matches_type(ChatPrompt, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_admin_get_chat_prompt(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
- client.chat.with_raw_response.admin_get_chat_prompt(
- "",
- )
-
@parametrize
def test_method_admin_issue_found(self, client: Structify) -> None:
chat = client.chat.admin_issue_found(
@@ -323,7 +296,6 @@ def test_method_create_session_with_all_params(self, client: Structify) -> None:
"system_prompt": "system_prompt",
},
ephemeral=True,
- initial_message="initial_message",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(CreateChatSessionResponse, chat, path=["response"])
@@ -353,45 +325,45 @@ def test_streaming_response_create_session(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
@parametrize
- def test_method_delete_files(self, client: Structify) -> None:
- chat = client.chat.delete_files(
+ def test_method_delete_input_file(self, client: Structify) -> None:
+ chat = client.chat.delete_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- paths=["string"],
+ filenames=["string"],
)
- assert_matches_type(ChatDeleteFilesResponse, chat, path=["response"])
+ assert_matches_type(ChatDeleteInputFileResponse, chat, path=["response"])
@parametrize
- def test_raw_response_delete_files(self, client: Structify) -> None:
- response = client.chat.with_raw_response.delete_files(
+ def test_raw_response_delete_input_file(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.delete_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- paths=["string"],
+ filenames=["string"],
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = response.parse()
- assert_matches_type(ChatDeleteFilesResponse, chat, path=["response"])
+ assert_matches_type(ChatDeleteInputFileResponse, chat, path=["response"])
@parametrize
- def test_streaming_response_delete_files(self, client: Structify) -> None:
- with client.chat.with_streaming_response.delete_files(
+ def test_streaming_response_delete_input_file(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.delete_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- paths=["string"],
+ filenames=["string"],
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = response.parse()
- assert_matches_type(ChatDeleteFilesResponse, chat, path=["response"])
+ assert_matches_type(ChatDeleteInputFileResponse, chat, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_delete_files(self, client: Structify) -> None:
+ def test_path_params_delete_input_file(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
- client.chat.with_raw_response.delete_files(
+ client.chat.with_raw_response.delete_input_file(
chat_id="",
- paths=["string"],
+ filenames=["string"],
)
@parametrize
@@ -716,6 +688,44 @@ def test_path_params_list_collaborators(self, client: Structify) -> None:
"",
)
+ @parametrize
+ def test_method_list_input_files(self, client: Structify) -> None:
+ chat = client.chat.list_input_files(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ChatListInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_list_input_files(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.list_input_files(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatListInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list_input_files(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.list_input_files(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatListInputFilesResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list_input_files(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.chat.with_raw_response.list_input_files(
+ "",
+ )
+
@parametrize
def test_method_list_sessions(self, client: Structify) -> None:
chat = client.chat.list_sessions(
@@ -820,6 +830,118 @@ def test_streaming_response_load_files(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_load_input_file(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/chat/input-files/download/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/filename").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ chat = client.chat.load_input_file(
+ filename="filename",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert chat.is_closed
+ assert chat.json() == {"foo": "bar"}
+ assert cast(Any, chat.is_closed) is True
+ assert isinstance(chat, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_load_input_file(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/chat/input-files/download/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/filename").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ chat = client.chat.with_raw_response.load_input_file(
+ filename="filename",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert chat.is_closed is True
+ assert chat.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert chat.json() == {"foo": "bar"}
+ assert isinstance(chat, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_load_input_file(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/chat/input-files/download/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/filename").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ with client.chat.with_streaming_response.load_input_file(
+ filename="filename",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as chat:
+ assert not chat.is_closed
+ assert chat.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert chat.json() == {"foo": "bar"}
+ assert cast(Any, chat.is_closed) is True
+ assert isinstance(chat, StreamedBinaryAPIResponse)
+
+ assert cast(Any, chat.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_path_params_load_input_file(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.chat.with_raw_response.load_input_file(
+ filename="filename",
+ chat_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `filename` but received ''"):
+ client.chat.with_raw_response.load_input_file(
+ filename="",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ @parametrize
+ def test_method_load_input_files(self, client: Structify) -> None:
+ chat = client.chat.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ def test_method_load_input_files_with_all_params(self, client: Structify) -> None:
+ chat = client.chat.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ since=parse_datetime("2019-12-27T18:11:19.117Z"),
+ )
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_load_input_files(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_load_input_files(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_load_input_files(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.chat.with_raw_response.load_input_files(
+ chat_id="",
+ )
+
@parametrize
def test_method_make_permanent(self, client: Structify) -> None:
chat = client.chat.make_permanent(
@@ -1081,6 +1203,56 @@ def test_path_params_update_visibility(self, client: Structify) -> None:
visibility="private",
)
+ @parametrize
+ def test_method_upload_input_file(self, client: Structify) -> None:
+ chat = client.chat.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ )
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_upload_input_file(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_upload_input_file(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_input_file(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.chat.with_raw_response.upload_input_file(
+ chat_id="",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ )
+
class TestAsyncChat:
parametrize = pytest.mark.parametrize(
@@ -1175,44 +1347,6 @@ async def test_path_params_add_git_commit(self, async_client: AsyncStructify) ->
commit_hash="commit_hash",
)
- @parametrize
- async def test_method_admin_get_chat_prompt(self, async_client: AsyncStructify) -> None:
- chat = await async_client.chat.admin_get_chat_prompt(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(ChatPrompt, chat, path=["response"])
-
- @parametrize
- async def test_raw_response_admin_get_chat_prompt(self, async_client: AsyncStructify) -> None:
- response = await async_client.chat.with_raw_response.admin_get_chat_prompt(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = await response.parse()
- assert_matches_type(ChatPrompt, chat, path=["response"])
-
- @parametrize
- async def test_streaming_response_admin_get_chat_prompt(self, async_client: AsyncStructify) -> None:
- async with async_client.chat.with_streaming_response.admin_get_chat_prompt(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = await response.parse()
- assert_matches_type(ChatPrompt, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_admin_get_chat_prompt(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
- await async_client.chat.with_raw_response.admin_get_chat_prompt(
- "",
- )
-
@parametrize
async def test_method_admin_issue_found(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.admin_issue_found(
@@ -1372,7 +1506,6 @@ async def test_method_create_session_with_all_params(self, async_client: AsyncSt
"system_prompt": "system_prompt",
},
ephemeral=True,
- initial_message="initial_message",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(CreateChatSessionResponse, chat, path=["response"])
@@ -1402,45 +1535,45 @@ async def test_streaming_response_create_session(self, async_client: AsyncStruct
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_method_delete_files(self, async_client: AsyncStructify) -> None:
- chat = await async_client.chat.delete_files(
+ async def test_method_delete_input_file(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.delete_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- paths=["string"],
+ filenames=["string"],
)
- assert_matches_type(ChatDeleteFilesResponse, chat, path=["response"])
+ assert_matches_type(ChatDeleteInputFileResponse, chat, path=["response"])
@parametrize
- async def test_raw_response_delete_files(self, async_client: AsyncStructify) -> None:
- response = await async_client.chat.with_raw_response.delete_files(
+ async def test_raw_response_delete_input_file(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.delete_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- paths=["string"],
+ filenames=["string"],
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = await response.parse()
- assert_matches_type(ChatDeleteFilesResponse, chat, path=["response"])
+ assert_matches_type(ChatDeleteInputFileResponse, chat, path=["response"])
@parametrize
- async def test_streaming_response_delete_files(self, async_client: AsyncStructify) -> None:
- async with async_client.chat.with_streaming_response.delete_files(
+ async def test_streaming_response_delete_input_file(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.delete_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- paths=["string"],
+ filenames=["string"],
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = await response.parse()
- assert_matches_type(ChatDeleteFilesResponse, chat, path=["response"])
+ assert_matches_type(ChatDeleteInputFileResponse, chat, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_delete_files(self, async_client: AsyncStructify) -> None:
+ async def test_path_params_delete_input_file(self, async_client: AsyncStructify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
- await async_client.chat.with_raw_response.delete_files(
+ await async_client.chat.with_raw_response.delete_input_file(
chat_id="",
- paths=["string"],
+ filenames=["string"],
)
@parametrize
@@ -1765,6 +1898,44 @@ async def test_path_params_list_collaborators(self, async_client: AsyncStructify
"",
)
+ @parametrize
+ async def test_method_list_input_files(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.list_input_files(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ChatListInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list_input_files(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.list_input_files(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatListInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list_input_files(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.list_input_files(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatListInputFilesResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list_input_files(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.chat.with_raw_response.list_input_files(
+ "",
+ )
+
@parametrize
async def test_method_list_sessions(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.list_sessions(
@@ -1869,6 +2040,120 @@ async def test_streaming_response_load_files(self, async_client: AsyncStructify)
assert cast(Any, response.is_closed) is True
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_load_input_file(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/chat/input-files/download/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/filename").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ chat = await async_client.chat.load_input_file(
+ filename="filename",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert chat.is_closed
+ assert await chat.json() == {"foo": "bar"}
+ assert cast(Any, chat.is_closed) is True
+ assert isinstance(chat, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_raw_response_load_input_file(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/chat/input-files/download/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/filename").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ chat = await async_client.chat.with_raw_response.load_input_file(
+ filename="filename",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert chat.is_closed is True
+ assert chat.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert await chat.json() == {"foo": "bar"}
+ assert isinstance(chat, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_streaming_response_load_input_file(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/chat/input-files/download/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/filename").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ async with async_client.chat.with_streaming_response.load_input_file(
+ filename="filename",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as chat:
+ assert not chat.is_closed
+ assert chat.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert await chat.json() == {"foo": "bar"}
+ assert cast(Any, chat.is_closed) is True
+ assert isinstance(chat, AsyncStreamedBinaryAPIResponse)
+
+ assert cast(Any, chat.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_path_params_load_input_file(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.chat.with_raw_response.load_input_file(
+ filename="filename",
+ chat_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `filename` but received ''"):
+ await async_client.chat.with_raw_response.load_input_file(
+ filename="",
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ @parametrize
+ async def test_method_load_input_files(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_method_load_input_files_with_all_params(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ since=parse_datetime("2019-12-27T18:11:19.117Z"),
+ )
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_load_input_files(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_load_input_files(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.load_input_files(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatLoadInputFilesResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_load_input_files(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.chat.with_raw_response.load_input_files(
+ chat_id="",
+ )
+
@parametrize
async def test_method_make_permanent(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.make_permanent(
@@ -2129,3 +2414,53 @@ async def test_path_params_update_visibility(self, async_client: AsyncStructify)
session_id="",
visibility="private",
)
+
+ @parametrize
+ async def test_method_upload_input_file(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ )
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_upload_input_file(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_upload_input_file(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_input_file(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.chat.with_raw_response.upload_input_file(
+ chat_id="",
+ content=b"raw file contents",
+ content_type="content_type",
+ file_name="file_name",
+ )
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 2a7da0752..17189af95 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -82,7 +82,6 @@ def test_path_params_confirm_node(self, client: Structify) -> None:
def test_method_create_session(self, client: Structify) -> None:
session = client.sessions.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
)
assert_matches_type(WorkflowSession, session, path=["response"])
@@ -90,7 +89,6 @@ def test_method_create_session(self, client: Structify) -> None:
def test_method_create_session_with_all_params(self, client: Structify) -> None:
session = client.sessions.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
parent_chat_message_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
workflow_schedule_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -100,7 +98,6 @@ def test_method_create_session_with_all_params(self, client: Structify) -> None:
def test_raw_response_create_session(self, client: Structify) -> None:
response = client.sessions.with_raw_response.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
)
assert response.is_closed is True
@@ -112,7 +109,6 @@ def test_raw_response_create_session(self, client: Structify) -> None:
def test_streaming_response_create_session(self, client: Structify) -> None:
with client.sessions.with_streaming_response.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1134,7 +1130,6 @@ async def test_path_params_confirm_node(self, async_client: AsyncStructify) -> N
async def test_method_create_session(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
)
assert_matches_type(WorkflowSession, session, path=["response"])
@@ -1142,7 +1137,6 @@ async def test_method_create_session(self, async_client: AsyncStructify) -> None
async def test_method_create_session_with_all_params(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
parent_chat_message_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
workflow_schedule_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -1152,7 +1146,6 @@ async def test_method_create_session_with_all_params(self, async_client: AsyncSt
async def test_raw_response_create_session(self, async_client: AsyncStructify) -> None:
response = await async_client.sessions.with_raw_response.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
)
assert response.is_closed is True
@@ -1164,7 +1157,6 @@ async def test_raw_response_create_session(self, async_client: AsyncStructify) -
async def test_streaming_response_create_session(self, async_client: AsyncStructify) -> None:
async with async_client.sessions.with_streaming_response.create_session(
chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- git_commit="git_commit",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
From c7ba1b2e113db5b1df0282216045997064362d93 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Feb 2026 07:28:29 +0000
Subject: [PATCH 028/105] chore: update mock server docs
---
CONTRIBUTING.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 15492f27f..abde1f04b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -88,8 +88,7 @@ $ pip install ./path-to-wheel-file.whl
Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
```sh
-# you will need npm installed
-$ npx prism mock path/to/your/openapi.yml
+$ ./scripts/mock
```
```sh
From 657d6aae3f7758ec809f7e41a7805405dfe617b7 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sun, 22 Feb 2026 23:05:08 +0000
Subject: [PATCH 029/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/chat_event.py | 15 +++++++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 166066f1d..81861fa5d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 238
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-13ee7c696d4028e178d153bbfd5fc16b6c9e42ce7e0e491f08384258f7a04925.yml
-openapi_spec_hash: e51ffb08d0edf6cc858b350f0615ebf4
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-7ec3940eaba885756ee47d654ee4d588a41c7dfd6f514e4dd8eaadfd9bece09d.yml
+openapi_spec_hash: 9e9bcc884657e9ff59e5fb192e63fac4
config_hash: ad7129c86de685d16828862aa96a884e
diff --git a/src/structify/types/chat_event.py b/src/structify/types/chat_event.py
index 60369bfd7..5d4504056 100644
--- a/src/structify/types/chat_event.py
+++ b/src/structify/types/chat_event.py
@@ -36,6 +36,8 @@
"ConnectorRequest",
"ConnectorRequestConnectorRequest",
"UserInterrupted",
+ "IssueFound",
+ "IssueFoundIssueFound",
]
@@ -190,6 +192,18 @@ class UserInterrupted(BaseModel):
user_interrupted: object = FieldInfo(alias="UserInterrupted")
+class IssueFoundIssueFound(BaseModel):
+ admin_override: bool
+
+ description: str
+
+ title: str
+
+
+class IssueFound(BaseModel):
+ issue_found: IssueFoundIssueFound = FieldInfo(alias="IssueFound")
+
+
ChatEvent: TypeAlias = Union[
TextMessage,
Thinking,
@@ -203,4 +217,5 @@ class UserInterrupted(BaseModel):
AttachedFile,
ConnectorRequest,
UserInterrupted,
+ IssueFound,
]
From 11b106e4ed0d8d8990206878d403f3462f244b67 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Feb 2026 20:53:49 +0000
Subject: [PATCH 030/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
.../types/chat_get_partial_chats_response.py | 17 ++++++++++++++---
2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 81861fa5d..c14b58016 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 238
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-7ec3940eaba885756ee47d654ee4d588a41c7dfd6f514e4dd8eaadfd9bece09d.yml
-openapi_spec_hash: 9e9bcc884657e9ff59e5fb192e63fac4
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-67fc816aae287ec7baa5b7d0f42d8661ff6ecf6fe019b50110cec742154b2040.yml
+openapi_spec_hash: 82cfe3f3a8e51e23ee3149e2ed1c3312
config_hash: ad7129c86de685d16828862aa96a884e
diff --git a/src/structify/types/chat_get_partial_chats_response.py b/src/structify/types/chat_get_partial_chats_response.py
index f2fa66051..659af4c13 100644
--- a/src/structify/types/chat_get_partial_chats_response.py
+++ b/src/structify/types/chat_get_partial_chats_response.py
@@ -1,10 +1,21 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-from typing import List
+from typing import List, Optional
+from datetime import datetime
from typing_extensions import TypeAlias
+from .._models import BaseModel
from .chat_prompt import ChatPrompt
-__all__ = ["ChatGetPartialChatsResponse"]
+__all__ = ["ChatGetPartialChatsResponse", "ChatGetPartialChatsResponseItem"]
-ChatGetPartialChatsResponse: TypeAlias = List[ChatPrompt]
+
+class ChatGetPartialChatsResponseItem(BaseModel):
+ chat_prompt: ChatPrompt
+
+ created_at: datetime
+
+ message_id: Optional[str] = None
+
+
+ChatGetPartialChatsResponse: TypeAlias = List[ChatGetPartialChatsResponseItem]
From 7b2a30a861fb15068c26b16f4dc6f8fc9de7a59c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Feb 2026 21:23:52 +0000
Subject: [PATCH 031/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +-
api.md | 2 +-
src/structify/resources/admin/connector.py | 8 ++
.../resources/connectors/connectors.py | 91 ++-----------------
src/structify/types/__init__.py | 1 -
.../types/admin/connector_clone_params.py | 4 +
src/structify/types/connector.py | 2 +
.../types/connector_create_params.py | 2 -
src/structify/types/connector_list_params.py | 5 +-
.../connector_list_with_snippets_params.py | 12 ---
.../types/connector_search_tables_params.py | 3 -
.../types/connector_summaries_params.py | 2 -
tests/api_resources/admin/test_connector.py | 12 +++
tests/api_resources/test_connectors.py | 70 +++-----------
14 files changed, 48 insertions(+), 170 deletions(-)
delete mode 100644 src/structify/types/connector_list_with_snippets_params.py
diff --git a/.stats.yml b/.stats.yml
index c14b58016..64fe20e87 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 238
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-67fc816aae287ec7baa5b7d0f42d8661ff6ecf6fe019b50110cec742154b2040.yml
-openapi_spec_hash: 82cfe3f3a8e51e23ee3149e2ed1c3312
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-4d1a1ad59efc4dcbb4854ce30f2b90f45d2627c49ec530cd6175332b2e32e712.yml
+openapi_spec_hash: b7362c33e7f3f23135270f76af892be1
config_hash: ad7129c86de685d16828862aa96a884e
diff --git a/api.md b/api.md
index f6b046c0a..df7e27639 100644
--- a/api.md
+++ b/api.md
@@ -715,7 +715,7 @@ Methods:
- client.connectors.get_explorer_chat(connector_id, \*\*params) -> ExplorerChatResponse
- client.connectors.get_store(connector_id) -> ConnectorStoreResponse
- client.connectors.list_tables(connector_id) -> ListTablesResponse
-- client.connectors.list_with_snippets(\*\*params) -> ConnectorListWithSnippetsResponse
+- client.connectors.list_with_snippets() -> ConnectorListWithSnippetsResponse
- client.connectors.resolve_clarification(clarification_id) -> None
- client.connectors.search_tables(\*\*params) -> ConnectorSearchTablesResponse
- client.connectors.summaries(\*\*params) -> ConnectorSummariesResponse
diff --git a/src/structify/resources/admin/connector.py b/src/structify/resources/admin/connector.py
index 85e094b90..399924bd4 100644
--- a/src/structify/resources/admin/connector.py
+++ b/src/structify/resources/admin/connector.py
@@ -48,6 +48,8 @@ def clone(
self,
*,
connectors: Iterable[CloneConnectorItemParam],
+ source_membership_id: str,
+ source_team_id: str,
target_team_id: str,
# 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.
@@ -71,6 +73,8 @@ def clone(
body=maybe_transform(
{
"connectors": connectors,
+ "source_membership_id": source_membership_id,
+ "source_team_id": source_team_id,
"target_team_id": target_team_id,
},
connector_clone_params.ConnectorCloneParams,
@@ -106,6 +110,8 @@ async def clone(
self,
*,
connectors: Iterable[CloneConnectorItemParam],
+ source_membership_id: str,
+ source_team_id: str,
target_team_id: str,
# 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.
@@ -129,6 +135,8 @@ async def clone(
body=await async_maybe_transform(
{
"connectors": connectors,
+ "source_membership_id": source_membership_id,
+ "source_team_id": source_team_id,
"target_team_id": target_team_id,
},
connector_clone_params.ConnectorCloneParams,
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 0aa1b276c..911ecccd4 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -20,7 +20,6 @@
connector_update_column_params,
connector_add_schema_object_params,
connector_get_explorer_chat_params,
- connector_list_with_snippets_params,
connector_delete_schema_object_params,
)
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
@@ -92,7 +91,6 @@ def create(
*,
known_connector_type: str,
name: str,
- team_id: str,
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
@@ -126,7 +124,6 @@ def create(
{
"known_connector_type": known_connector_type,
"name": name,
- "team_id": team_id,
"description": description,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
@@ -202,7 +199,6 @@ def update(
def list(
self,
*,
- team_id: str,
limit: int | Omit = omit,
offset: int | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -214,8 +210,6 @@ def list(
) -> SyncJobsList[ConnectorWithSecrets]:
"""
Args:
- team_id: Team ID to list connectors for
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -234,7 +228,6 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "team_id": team_id,
"limit": limit,
"offset": offset,
},
@@ -945,7 +938,6 @@ def list_tables(
def list_with_snippets(
self,
*,
- team_id: str,
# 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,
@@ -953,28 +945,10 @@ def list_with_snippets(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConnectorListWithSnippetsResponse:
- """
- Args:
- team_id: Team ID to list connectors for
-
- 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
- """
return self._get(
"/connectors/with-snippets",
options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {"team_id": team_id}, connector_list_with_snippets_params.ConnectorListWithSnippetsParams
- ),
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=ConnectorListWithSnippetsResponse,
)
@@ -1017,7 +991,6 @@ def search_tables(
self,
*,
query: str,
- team_id: str,
# 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,
@@ -1029,8 +1002,6 @@ def search_tables(
Args:
query: Search query string
- team_id: Team ID to search tables for
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -1046,13 +1017,7 @@ def search_tables(
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=maybe_transform(
- {
- "query": query,
- "team_id": team_id,
- },
- connector_search_tables_params.ConnectorSearchTablesParams,
- ),
+ query=maybe_transform({"query": query}, connector_search_tables_params.ConnectorSearchTablesParams),
),
cast_to=ConnectorSearchTablesResponse,
)
@@ -1061,7 +1026,6 @@ def summaries(
self,
*,
connector_ids: SequenceNotStr[str],
- team_id: str,
# 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,
@@ -1081,13 +1045,7 @@ def summaries(
"""
return self._post(
"/connectors/summaries",
- body=maybe_transform(
- {
- "connector_ids": connector_ids,
- "team_id": team_id,
- },
- connector_summaries_params.ConnectorSummariesParams,
- ),
+ body=maybe_transform({"connector_ids": connector_ids}, connector_summaries_params.ConnectorSummariesParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1202,7 +1160,6 @@ async def create(
*,
known_connector_type: str,
name: str,
- team_id: str,
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
@@ -1236,7 +1193,6 @@ async def create(
{
"known_connector_type": known_connector_type,
"name": name,
- "team_id": team_id,
"description": description,
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
@@ -1312,7 +1268,6 @@ async def update(
def list(
self,
*,
- team_id: str,
limit: int | Omit = omit,
offset: int | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -1324,8 +1279,6 @@ def list(
) -> AsyncPaginator[ConnectorWithSecrets, AsyncJobsList[ConnectorWithSecrets]]:
"""
Args:
- team_id: Team ID to list connectors for
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -1344,7 +1297,6 @@ def list(
timeout=timeout,
query=maybe_transform(
{
- "team_id": team_id,
"limit": limit,
"offset": offset,
},
@@ -2055,7 +2007,6 @@ async def list_tables(
async def list_with_snippets(
self,
*,
- team_id: str,
# 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,
@@ -2063,28 +2014,10 @@ async def list_with_snippets(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ConnectorListWithSnippetsResponse:
- """
- Args:
- team_id: Team ID to list connectors for
-
- 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
- """
return await self._get(
"/connectors/with-snippets",
options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {"team_id": team_id}, connector_list_with_snippets_params.ConnectorListWithSnippetsParams
- ),
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
cast_to=ConnectorListWithSnippetsResponse,
)
@@ -2127,7 +2060,6 @@ async def search_tables(
self,
*,
query: str,
- team_id: str,
# 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,
@@ -2139,8 +2071,6 @@ async def search_tables(
Args:
query: Search query string
- team_id: Team ID to search tables for
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -2157,11 +2087,7 @@ async def search_tables(
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
- {
- "query": query,
- "team_id": team_id,
- },
- connector_search_tables_params.ConnectorSearchTablesParams,
+ {"query": query}, connector_search_tables_params.ConnectorSearchTablesParams
),
),
cast_to=ConnectorSearchTablesResponse,
@@ -2171,7 +2097,6 @@ async def summaries(
self,
*,
connector_ids: SequenceNotStr[str],
- team_id: str,
# 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,
@@ -2192,11 +2117,7 @@ async def summaries(
return await self._post(
"/connectors/summaries",
body=await async_maybe_transform(
- {
- "connector_ids": connector_ids,
- "team_id": team_id,
- },
- connector_summaries_params.ConnectorSummariesParams,
+ {"connector_ids": connector_ids}, connector_summaries_params.ConnectorSummariesParams
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 8a1d889a2..1bbf51228 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -311,7 +311,6 @@
from .structure_find_relationship_params import StructureFindRelationshipParams as StructureFindRelationshipParams
from .workflow_schedule_get_all_response import WorkflowScheduleGetAllResponse as WorkflowScheduleGetAllResponse
from .chat_update_session_favorite_params import ChatUpdateSessionFavoriteParams as ChatUpdateSessionFavoriteParams
-from .connector_list_with_snippets_params import ConnectorListWithSnippetsParams as ConnectorListWithSnippetsParams
from .dataset_view_relationships_response import DatasetViewRelationshipsResponse as DatasetViewRelationshipsResponse
from .delete_source_relationship_response import DeleteSourceRelationshipResponse as DeleteSourceRelationshipResponse
from .entity_get_source_entities_response import EntityGetSourceEntitiesResponse as EntityGetSourceEntitiesResponse
diff --git a/src/structify/types/admin/connector_clone_params.py b/src/structify/types/admin/connector_clone_params.py
index 0b2cd0195..b7511f31b 100644
--- a/src/structify/types/admin/connector_clone_params.py
+++ b/src/structify/types/admin/connector_clone_params.py
@@ -13,4 +13,8 @@
class ConnectorCloneParams(TypedDict, total=False):
connectors: Required[Iterable[CloneConnectorItemParam]]
+ source_membership_id: Required[str]
+
+ source_team_id: Required[str]
+
target_team_id: Required[str]
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 57b396a46..81a2a0a75 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -22,6 +22,8 @@ class Connector(BaseModel):
name: str
+ owner_user_id: str
+
team_id: str
team_visibility: Literal["Team", "Private"]
diff --git a/src/structify/types/connector_create_params.py b/src/structify/types/connector_create_params.py
index 2f9bbec48..7c01a2da1 100644
--- a/src/structify/types/connector_create_params.py
+++ b/src/structify/types/connector_create_params.py
@@ -13,8 +13,6 @@ class ConnectorCreateParams(TypedDict, total=False):
name: Required[str]
- team_id: Required[str]
-
description: Optional[str]
nango_connection_id: Optional[str]
diff --git a/src/structify/types/connector_list_params.py b/src/structify/types/connector_list_params.py
index 6f9c91258..7be465a02 100644
--- a/src/structify/types/connector_list_params.py
+++ b/src/structify/types/connector_list_params.py
@@ -2,15 +2,12 @@
from __future__ import annotations
-from typing_extensions import Required, TypedDict
+from typing_extensions import TypedDict
__all__ = ["ConnectorListParams"]
class ConnectorListParams(TypedDict, total=False):
- team_id: Required[str]
- """Team ID to list connectors for"""
-
limit: int
offset: int
diff --git a/src/structify/types/connector_list_with_snippets_params.py b/src/structify/types/connector_list_with_snippets_params.py
deleted file mode 100644
index 998cd2f6b..000000000
--- a/src/structify/types/connector_list_with_snippets_params.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-__all__ = ["ConnectorListWithSnippetsParams"]
-
-
-class ConnectorListWithSnippetsParams(TypedDict, total=False):
- team_id: Required[str]
- """Team ID to list connectors for"""
diff --git a/src/structify/types/connector_search_tables_params.py b/src/structify/types/connector_search_tables_params.py
index 2f2847016..e81d04d94 100644
--- a/src/structify/types/connector_search_tables_params.py
+++ b/src/structify/types/connector_search_tables_params.py
@@ -10,6 +10,3 @@
class ConnectorSearchTablesParams(TypedDict, total=False):
query: Required[str]
"""Search query string"""
-
- team_id: Required[str]
- """Team ID to search tables for"""
diff --git a/src/structify/types/connector_summaries_params.py b/src/structify/types/connector_summaries_params.py
index 886dfcca3..46632c7f3 100644
--- a/src/structify/types/connector_summaries_params.py
+++ b/src/structify/types/connector_summaries_params.py
@@ -11,5 +11,3 @@
class ConnectorSummariesParams(TypedDict, total=False):
connector_ids: Required[SequenceNotStr[str]]
-
- team_id: Required[str]
diff --git a/tests/api_resources/admin/test_connector.py b/tests/api_resources/admin/test_connector.py
index 3535580ac..7eee1bfba 100644
--- a/tests/api_resources/admin/test_connector.py
+++ b/tests/api_resources/admin/test_connector.py
@@ -27,6 +27,8 @@ def test_method_clone(self, client: Structify) -> None:
"source_connector_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
}
],
+ source_membership_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
@@ -41,6 +43,8 @@ def test_raw_response_clone(self, client: Structify) -> None:
"source_connector_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
}
],
+ source_membership_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -59,6 +63,8 @@ def test_streaming_response_clone(self, client: Structify) -> None:
"source_connector_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
}
],
+ source_membership_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
@@ -85,6 +91,8 @@ async def test_method_clone(self, async_client: AsyncStructify) -> None:
"source_connector_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
}
],
+ source_membership_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
@@ -99,6 +107,8 @@ async def test_raw_response_clone(self, async_client: AsyncStructify) -> None:
"source_connector_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
}
],
+ source_membership_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -117,6 +127,8 @@ async def test_streaming_response_clone(self, async_client: AsyncStructify) -> N
"source_connector_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
}
],
+ source_membership_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index 803817150..3102058ab 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -39,7 +39,6 @@ def test_method_create(self, client: Structify) -> None:
connector = client.connectors.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(Connector, connector, path=["response"])
@@ -48,7 +47,6 @@ def test_method_create_with_all_params(self, client: Structify) -> None:
connector = client.connectors.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
description="description",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
@@ -61,7 +59,6 @@ def test_raw_response_create(self, client: Structify) -> None:
response = client.connectors.with_raw_response.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -74,7 +71,6 @@ def test_streaming_response_create(self, client: Structify) -> None:
with client.connectors.with_streaming_response.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -142,15 +138,12 @@ def test_path_params_update(self, client: Structify) -> None:
@parametrize
def test_method_list(self, client: Structify) -> None:
- connector = client.connectors.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ connector = client.connectors.list()
assert_matches_type(SyncJobsList[ConnectorWithSecrets], connector, path=["response"])
@parametrize
def test_method_list_with_all_params(self, client: Structify) -> None:
connector = client.connectors.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
offset=0,
)
@@ -158,9 +151,7 @@ def test_method_list_with_all_params(self, client: Structify) -> None:
@parametrize
def test_raw_response_list(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ response = client.connectors.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -169,9 +160,7 @@ def test_raw_response_list(self, client: Structify) -> None:
@parametrize
def test_streaming_response_list(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
+ with client.connectors.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1065,16 +1054,12 @@ def test_path_params_list_tables(self, client: Structify) -> None:
@parametrize
def test_method_list_with_snippets(self, client: Structify) -> None:
- connector = client.connectors.list_with_snippets(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ connector = client.connectors.list_with_snippets()
assert_matches_type(ConnectorListWithSnippetsResponse, connector, path=["response"])
@parametrize
def test_raw_response_list_with_snippets(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.list_with_snippets(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ response = client.connectors.with_raw_response.list_with_snippets()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1083,9 +1068,7 @@ def test_raw_response_list_with_snippets(self, client: Structify) -> None:
@parametrize
def test_streaming_response_list_with_snippets(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.list_with_snippets(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
+ with client.connectors.with_streaming_response.list_with_snippets() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1136,7 +1119,6 @@ def test_path_params_resolve_clarification(self, client: Structify) -> None:
def test_method_search_tables(self, client: Structify) -> None:
connector = client.connectors.search_tables(
query="query",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ConnectorSearchTablesResponse, connector, path=["response"])
@@ -1144,7 +1126,6 @@ def test_method_search_tables(self, client: Structify) -> None:
def test_raw_response_search_tables(self, client: Structify) -> None:
response = client.connectors.with_raw_response.search_tables(
query="query",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -1156,7 +1137,6 @@ def test_raw_response_search_tables(self, client: Structify) -> None:
def test_streaming_response_search_tables(self, client: Structify) -> None:
with client.connectors.with_streaming_response.search_tables(
query="query",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1170,7 +1150,6 @@ def test_streaming_response_search_tables(self, client: Structify) -> None:
def test_method_summaries(self, client: Structify) -> None:
connector = client.connectors.summaries(
connector_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ConnectorSummariesResponse, connector, path=["response"])
@@ -1178,7 +1157,6 @@ def test_method_summaries(self, client: Structify) -> None:
def test_raw_response_summaries(self, client: Structify) -> None:
response = client.connectors.with_raw_response.summaries(
connector_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -1190,7 +1168,6 @@ def test_raw_response_summaries(self, client: Structify) -> None:
def test_streaming_response_summaries(self, client: Structify) -> None:
with client.connectors.with_streaming_response.summaries(
connector_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1304,7 +1281,6 @@ async def test_method_create(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(Connector, connector, path=["response"])
@@ -1313,7 +1289,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncStructify)
connector = await async_client.connectors.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
description="description",
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
@@ -1326,7 +1301,6 @@ async def test_raw_response_create(self, async_client: AsyncStructify) -> None:
response = await async_client.connectors.with_raw_response.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -1339,7 +1313,6 @@ async def test_streaming_response_create(self, async_client: AsyncStructify) ->
async with async_client.connectors.with_streaming_response.create(
known_connector_type="known_connector_type",
name="name",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1407,15 +1380,12 @@ async def test_path_params_update(self, async_client: AsyncStructify) -> None:
@parametrize
async def test_method_list(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ connector = await async_client.connectors.list()
assert_matches_type(AsyncJobsList[ConnectorWithSecrets], connector, path=["response"])
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
offset=0,
)
@@ -1423,9 +1393,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncStructify) -
@parametrize
async def test_raw_response_list(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ response = await async_client.connectors.with_raw_response.list()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1434,9 +1402,7 @@ async def test_raw_response_list(self, async_client: AsyncStructify) -> None:
@parametrize
async def test_streaming_response_list(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.list(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
+ async with async_client.connectors.with_streaming_response.list() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2330,16 +2296,12 @@ async def test_path_params_list_tables(self, async_client: AsyncStructify) -> No
@parametrize
async def test_method_list_with_snippets(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.list_with_snippets(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ connector = await async_client.connectors.list_with_snippets()
assert_matches_type(ConnectorListWithSnippetsResponse, connector, path=["response"])
@parametrize
async def test_raw_response_list_with_snippets(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.list_with_snippets(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
+ response = await async_client.connectors.with_raw_response.list_with_snippets()
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2348,9 +2310,7 @@ async def test_raw_response_list_with_snippets(self, async_client: AsyncStructif
@parametrize
async def test_streaming_response_list_with_snippets(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.list_with_snippets(
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
+ async with async_client.connectors.with_streaming_response.list_with_snippets() as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2401,7 +2361,6 @@ async def test_path_params_resolve_clarification(self, async_client: AsyncStruct
async def test_method_search_tables(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.search_tables(
query="query",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ConnectorSearchTablesResponse, connector, path=["response"])
@@ -2409,7 +2368,6 @@ async def test_method_search_tables(self, async_client: AsyncStructify) -> None:
async def test_raw_response_search_tables(self, async_client: AsyncStructify) -> None:
response = await async_client.connectors.with_raw_response.search_tables(
query="query",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -2421,7 +2379,6 @@ async def test_raw_response_search_tables(self, async_client: AsyncStructify) ->
async def test_streaming_response_search_tables(self, async_client: AsyncStructify) -> None:
async with async_client.connectors.with_streaming_response.search_tables(
query="query",
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2435,7 +2392,6 @@ async def test_streaming_response_search_tables(self, async_client: AsyncStructi
async def test_method_summaries(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.summaries(
connector_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ConnectorSummariesResponse, connector, path=["response"])
@@ -2443,7 +2399,6 @@ async def test_method_summaries(self, async_client: AsyncStructify) -> None:
async def test_raw_response_summaries(self, async_client: AsyncStructify) -> None:
response = await async_client.connectors.with_raw_response.summaries(
connector_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -2455,7 +2410,6 @@ async def test_raw_response_summaries(self, async_client: AsyncStructify) -> Non
async def test_streaming_response_summaries(self, async_client: AsyncStructify) -> None:
async with async_client.connectors.with_streaming_response.summaries(
connector_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
- team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
From 06905d33be13a97cb80f22d04354695456429e7f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Feb 2026 21:42:54 +0000
Subject: [PATCH 032/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/tool_invocation.py | 13 +++++++++++++
src/structify/types/tool_result.py | 6 ++++++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 64fe20e87..19c4a86db 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 238
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-4d1a1ad59efc4dcbb4854ce30f2b90f45d2627c49ec530cd6175332b2e32e712.yml
-openapi_spec_hash: b7362c33e7f3f23135270f76af892be1
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-e97019dac5862bc362cc54cbcc7e0b103eaca93a8b4f35a224f544c8068e1a9c.yml
+openapi_spec_hash: 4b054c1940891efb0e1915462a617682
config_hash: ad7129c86de685d16828862aa96a884e
diff --git a/src/structify/types/tool_invocation.py b/src/structify/types/tool_invocation.py
index 97fa0e021..ab34ba5cf 100644
--- a/src/structify/types/tool_invocation.py
+++ b/src/structify/types/tool_invocation.py
@@ -66,6 +66,8 @@
"CreateConnectorInput",
"SearchConnectorTypes",
"SearchConnectorTypesInput",
+ "PinPreviousTool",
+ "PinPreviousToolInput",
]
@@ -432,6 +434,16 @@ class SearchConnectorTypes(BaseModel):
name: Literal["SearchConnectorTypes"]
+class PinPreviousToolInput(BaseModel):
+ path: str
+
+
+class PinPreviousTool(BaseModel):
+ input: PinPreviousToolInput
+
+ name: Literal["PinPreviousTool"]
+
+
ToolInvocation: TypeAlias = Annotated[
Union[
WebSearch,
@@ -463,6 +475,7 @@ class SearchConnectorTypes(BaseModel):
SelectData,
CreateConnector,
SearchConnectorTypes,
+ PinPreviousTool,
],
PropertyInfo(discriminator="name"),
]
diff --git a/src/structify/types/tool_result.py b/src/structify/types/tool_result.py
index e81cdfc57..54ab93253 100644
--- a/src/structify/types/tool_result.py
+++ b/src/structify/types/tool_result.py
@@ -22,6 +22,7 @@
"NodeLogs",
"Image",
"ImageImage",
+ "Pinned",
]
@@ -101,6 +102,10 @@ class Image(BaseModel):
image: ImageImage = FieldInfo(alias="Image")
+class Pinned(BaseModel):
+ pinned: str = FieldInfo(alias="Pinned")
+
+
ToolResult: TypeAlias = Union[
Literal["Pending", "NoResult", "Completed"],
Error,
@@ -111,4 +116,5 @@ class Image(BaseModel):
ConnectorSearch,
NodeLogs,
Image,
+ Pinned,
]
From aa6dc7fc0ef92720834578efa70fc6661b4b69a8 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Feb 2026 07:40:29 +0000
Subject: [PATCH 033/105] chore(internal): add request options to SSE classes
---
src/structify/_response.py | 3 +++
src/structify/_streaming.py | 11 ++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/structify/_response.py b/src/structify/_response.py
index d9e6c9425..46c56282f 100644
--- a/src/structify/_response.py
+++ b/src/structify/_response.py
@@ -152,6 +152,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
),
response=self.http_response,
client=cast(Any, self._client),
+ options=self._options,
),
)
@@ -162,6 +163,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
cast_to=extract_stream_chunk_type(self._stream_cls),
response=self.http_response,
client=cast(Any, self._client),
+ options=self._options,
),
)
@@ -175,6 +177,7 @@ def _parse(self, *, to: type[_T] | None = None) -> R | _T:
cast_to=cast_to,
response=self.http_response,
client=cast(Any, self._client),
+ options=self._options,
),
)
diff --git a/src/structify/_streaming.py b/src/structify/_streaming.py
index 2eadb0067..da79cc765 100644
--- a/src/structify/_streaming.py
+++ b/src/structify/_streaming.py
@@ -4,7 +4,7 @@
import json
import inspect
from types import TracebackType
-from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, AsyncIterator, cast
+from typing import TYPE_CHECKING, Any, Generic, TypeVar, Iterator, Optional, AsyncIterator, cast
from typing_extensions import Self, Protocol, TypeGuard, override, get_origin, runtime_checkable
import httpx
@@ -13,6 +13,7 @@
if TYPE_CHECKING:
from ._client import Structify, AsyncStructify
+ from ._models import FinalRequestOptions
_T = TypeVar("_T")
@@ -22,7 +23,7 @@ class Stream(Generic[_T]):
"""Provides the core interface to iterate over a synchronous stream response."""
response: httpx.Response
-
+ _options: Optional[FinalRequestOptions] = None
_decoder: SSEBytesDecoder
def __init__(
@@ -31,10 +32,12 @@ def __init__(
cast_to: type[_T],
response: httpx.Response,
client: Structify,
+ options: Optional[FinalRequestOptions] = None,
) -> None:
self.response = response
self._cast_to = cast_to
self._client = client
+ self._options = options
self._decoder = client._make_sse_decoder()
self._iterator = self.__stream__()
@@ -85,7 +88,7 @@ class AsyncStream(Generic[_T]):
"""Provides the core interface to iterate over an asynchronous stream response."""
response: httpx.Response
-
+ _options: Optional[FinalRequestOptions] = None
_decoder: SSEDecoder | SSEBytesDecoder
def __init__(
@@ -94,10 +97,12 @@ def __init__(
cast_to: type[_T],
response: httpx.Response,
client: AsyncStructify,
+ options: Optional[FinalRequestOptions] = None,
) -> None:
self.response = response
self._cast_to = cast_to
self._client = client
+ self._options = options
self._decoder = client._make_sse_decoder()
self._iterator = self.__stream__()
From 3543b8f5f16df6c661e561ecb5d01d5959fc0f72 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Feb 2026 07:50:50 +0000
Subject: [PATCH 034/105] chore(internal): make
`test_proxy_environment_variables` more resilient
---
tests/test_client.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/test_client.py b/tests/test_client.py
index 7adaaa6c4..601df2d84 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -966,6 +966,8 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
+ # Delete in case our environment has this set
+ monkeypatch.delenv("HTTP_PROXY", raising=False)
client = DefaultHttpxClient()
@@ -1891,6 +1893,8 @@ async def test_get_platform(self) -> None:
async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
+ # Delete in case our environment has this set
+ monkeypatch.delenv("HTTP_PROXY", raising=False)
client = DefaultAsyncHttpxClient()
From 42b68e89e75ab91d86ee3b492c2a648acd338ad6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Feb 2026 07:33:31 +0000
Subject: [PATCH 035/105] chore(internal): make
`test_proxy_environment_variables` more resilient to env
---
tests/test_client.py | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/tests/test_client.py b/tests/test_client.py
index 601df2d84..378c73e3e 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -966,8 +966,14 @@ def retry_handler(_request: httpx.Request) -> httpx.Response:
def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
- # Delete in case our environment has this set
+ # Delete in case our environment has any proxy env vars set
monkeypatch.delenv("HTTP_PROXY", raising=False)
+ monkeypatch.delenv("ALL_PROXY", raising=False)
+ monkeypatch.delenv("NO_PROXY", raising=False)
+ monkeypatch.delenv("http_proxy", raising=False)
+ monkeypatch.delenv("https_proxy", raising=False)
+ monkeypatch.delenv("all_proxy", raising=False)
+ monkeypatch.delenv("no_proxy", raising=False)
client = DefaultHttpxClient()
@@ -1893,8 +1899,14 @@ async def test_get_platform(self) -> None:
async def test_proxy_environment_variables(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Test that the proxy environment variables are set correctly
monkeypatch.setenv("HTTPS_PROXY", "https://example.org")
- # Delete in case our environment has this set
+ # Delete in case our environment has any proxy env vars set
monkeypatch.delenv("HTTP_PROXY", raising=False)
+ monkeypatch.delenv("ALL_PROXY", raising=False)
+ monkeypatch.delenv("NO_PROXY", raising=False)
+ monkeypatch.delenv("http_proxy", raising=False)
+ monkeypatch.delenv("https_proxy", raising=False)
+ monkeypatch.delenv("all_proxy", raising=False)
+ monkeypatch.delenv("no_proxy", raising=False)
client = DefaultAsyncHttpxClient()
From f0e673a1faeef8766e2a3d315c13efea2e1e27fd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Feb 2026 21:00:15 +0000
Subject: [PATCH 036/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 +
.../resources/connectors/connectors.py | 95 ++++++++++++++++++-
src/structify/types/__init__.py | 1 +
.../types/connector_search_tables_params.py | 3 +
.../types/connector_table_path_response.py | 15 +++
tests/api_resources/test_connectors.py | 83 ++++++++++++++++
7 files changed, 201 insertions(+), 6 deletions(-)
create mode 100644 src/structify/types/connector_table_path_response.py
diff --git a/.stats.yml b/.stats.yml
index 19c4a86db..153690e71 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 238
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-e97019dac5862bc362cc54cbcc7e0b103eaca93a8b4f35a224f544c8068e1a9c.yml
-openapi_spec_hash: 4b054c1940891efb0e1915462a617682
-config_hash: ad7129c86de685d16828862aa96a884e
+configured_endpoints: 239
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-39b2a3aca15e296ba636ee748fcd80f7c70c30cadb53de230062e1706f52e697.yml
+openapi_spec_hash: 42475eb9e7c202e25cffbe9c9cd8970c
+config_hash: f1ac63e6803cb48ae689be81a70a350b
diff --git a/api.md b/api.md
index df7e27639..edf4bce96 100644
--- a/api.md
+++ b/api.md
@@ -668,6 +668,7 @@ from structify.types import (
ConnectorSummariesRequest,
ConnectorSummary,
ConnectorTableInfo,
+ ConnectorTablePathResponse,
ConnectorWithSecrets,
ConnectorWithSnippets,
CreateConnectorRequest,
@@ -714,6 +715,7 @@ Methods:
- client.connectors.get_exploration_status(connector_id) -> ExploreStatusResponse
- client.connectors.get_explorer_chat(connector_id, \*\*params) -> ExplorerChatResponse
- client.connectors.get_store(connector_id) -> ConnectorStoreResponse
+- client.connectors.get_table_path(table_id) -> ConnectorTablePathResponse
- client.connectors.list_tables(connector_id) -> ListTablesResponse
- client.connectors.list_with_snippets() -> ConnectorListWithSnippetsResponse
- client.connectors.resolve_clarification(clarification_id) -> None
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 911ecccd4..ce3f1a9f8 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -53,6 +53,7 @@
from ...types.connector_store_response import ConnectorStoreResponse
from ...types.exploration_runs_response import ExplorationRunsResponse
from ...types.connector_summaries_response import ConnectorSummariesResponse
+from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
from ...types.connector_search_tables_response import ConnectorSearchTablesResponse
from ...types.connector_add_schema_object_response import ConnectorAddSchemaObjectResponse
@@ -900,6 +901,37 @@ def get_store(
cast_to=ConnectorStoreResponse,
)
+ def get_table_path(
+ self,
+ table_id: str,
+ *,
+ # 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,
+ ) -> ConnectorTablePathResponse:
+ """
+ Args:
+ 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
+ """
+ if not table_id:
+ raise ValueError(f"Expected a non-empty value for `table_id` but received {table_id!r}")
+ return self._get(
+ f"/connectors/tables/{table_id}/path",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ConnectorTablePathResponse,
+ )
+
def list_tables(
self,
connector_id: str,
@@ -991,6 +1023,7 @@ def search_tables(
self,
*,
query: str,
+ team_id: str,
# 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,
@@ -1002,6 +1035,8 @@ def search_tables(
Args:
query: Search query string
+ team_id: Team ID to scope table search
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -1017,7 +1052,13 @@ def search_tables(
extra_query=extra_query,
extra_body=extra_body,
timeout=timeout,
- query=maybe_transform({"query": query}, connector_search_tables_params.ConnectorSearchTablesParams),
+ query=maybe_transform(
+ {
+ "query": query,
+ "team_id": team_id,
+ },
+ connector_search_tables_params.ConnectorSearchTablesParams,
+ ),
),
cast_to=ConnectorSearchTablesResponse,
)
@@ -1969,6 +2010,37 @@ async def get_store(
cast_to=ConnectorStoreResponse,
)
+ async def get_table_path(
+ self,
+ table_id: str,
+ *,
+ # 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,
+ ) -> ConnectorTablePathResponse:
+ """
+ Args:
+ 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
+ """
+ if not table_id:
+ raise ValueError(f"Expected a non-empty value for `table_id` but received {table_id!r}")
+ return await self._get(
+ f"/connectors/tables/{table_id}/path",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ConnectorTablePathResponse,
+ )
+
async def list_tables(
self,
connector_id: str,
@@ -2060,6 +2132,7 @@ async def search_tables(
self,
*,
query: str,
+ team_id: str,
# 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,
@@ -2071,6 +2144,8 @@ async def search_tables(
Args:
query: Search query string
+ team_id: Team ID to scope table search
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -2087,7 +2162,11 @@ async def search_tables(
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
- {"query": query}, connector_search_tables_params.ConnectorSearchTablesParams
+ {
+ "query": query,
+ "team_id": team_id,
+ },
+ connector_search_tables_params.ConnectorSearchTablesParams,
),
),
cast_to=ConnectorSearchTablesResponse,
@@ -2255,6 +2334,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_store = to_raw_response_wrapper(
connectors.get_store,
)
+ self.get_table_path = to_raw_response_wrapper(
+ connectors.get_table_path,
+ )
self.list_tables = to_raw_response_wrapper(
connectors.list_tables,
)
@@ -2331,6 +2413,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_store = async_to_raw_response_wrapper(
connectors.get_store,
)
+ self.get_table_path = async_to_raw_response_wrapper(
+ connectors.get_table_path,
+ )
self.list_tables = async_to_raw_response_wrapper(
connectors.list_tables,
)
@@ -2407,6 +2492,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_store = to_streamed_response_wrapper(
connectors.get_store,
)
+ self.get_table_path = to_streamed_response_wrapper(
+ connectors.get_table_path,
+ )
self.list_tables = to_streamed_response_wrapper(
connectors.list_tables,
)
@@ -2483,6 +2571,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_store = async_to_streamed_response_wrapper(
connectors.get_store,
)
+ self.get_table_path = async_to_streamed_response_wrapper(
+ connectors.get_table_path,
+ )
self.list_tables = async_to_streamed_response_wrapper(
connectors.list_tables,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 1bbf51228..9796a63c2 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -249,6 +249,7 @@
from .chat_update_visibility_params import ChatUpdateVisibilityParams as ChatUpdateVisibilityParams
from .chat_upload_input_file_params import ChatUploadInputFileParams as ChatUploadInputFileParams
from .connector_catalog_list_params import ConnectorCatalogListParams as ConnectorCatalogListParams
+from .connector_table_path_response import ConnectorTablePathResponse as ConnectorTablePathResponse
from .connector_update_table_params import ConnectorUpdateTableParams as ConnectorUpdateTableParams
from .delete_schema_object_response import DeleteSchemaObjectResponse as DeleteSchemaObjectResponse
from .delete_source_entity_response import DeleteSourceEntityResponse as DeleteSourceEntityResponse
diff --git a/src/structify/types/connector_search_tables_params.py b/src/structify/types/connector_search_tables_params.py
index e81d04d94..83b002eec 100644
--- a/src/structify/types/connector_search_tables_params.py
+++ b/src/structify/types/connector_search_tables_params.py
@@ -10,3 +10,6 @@
class ConnectorSearchTablesParams(TypedDict, total=False):
query: Required[str]
"""Search query string"""
+
+ team_id: Required[str]
+ """Team ID to scope table search"""
diff --git a/src/structify/types/connector_table_path_response.py b/src/structify/types/connector_table_path_response.py
new file mode 100644
index 000000000..973e2493a
--- /dev/null
+++ b/src/structify/types/connector_table_path_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["ConnectorTablePathResponse"]
+
+
+class ConnectorTablePathResponse(BaseModel):
+ connector_id: str
+
+ database_name: str
+
+ schema_name: str
+
+ table_name: str
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index 3102058ab..f00858f1a 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -20,6 +20,7 @@
ConnectorStoreResponse,
ExplorationRunsResponse,
ConnectorSummariesResponse,
+ ConnectorTablePathResponse,
DeleteSchemaObjectResponse,
ConnectorSearchTablesResponse,
ConnectorAddSchemaObjectResponse,
@@ -1014,6 +1015,44 @@ def test_path_params_get_store(self, client: Structify) -> None:
"",
)
+ @parametrize
+ def test_method_get_table_path(self, client: Structify) -> None:
+ connector = client.connectors.get_table_path(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ConnectorTablePathResponse, connector, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_table_path(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.get_table_path(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert_matches_type(ConnectorTablePathResponse, connector, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_table_path(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.get_table_path(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert_matches_type(ConnectorTablePathResponse, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get_table_path(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `table_id` but received ''"):
+ client.connectors.with_raw_response.get_table_path(
+ "",
+ )
+
@parametrize
def test_method_list_tables(self, client: Structify) -> None:
connector = client.connectors.list_tables(
@@ -1119,6 +1158,7 @@ def test_path_params_resolve_clarification(self, client: Structify) -> None:
def test_method_search_tables(self, client: Structify) -> None:
connector = client.connectors.search_tables(
query="query",
+ team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ConnectorSearchTablesResponse, connector, path=["response"])
@@ -1126,6 +1166,7 @@ def test_method_search_tables(self, client: Structify) -> None:
def test_raw_response_search_tables(self, client: Structify) -> None:
response = client.connectors.with_raw_response.search_tables(
query="query",
+ team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -1137,6 +1178,7 @@ def test_raw_response_search_tables(self, client: Structify) -> None:
def test_streaming_response_search_tables(self, client: Structify) -> None:
with client.connectors.with_streaming_response.search_tables(
query="query",
+ team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2256,6 +2298,44 @@ async def test_path_params_get_store(self, async_client: AsyncStructify) -> None
"",
)
+ @parametrize
+ async def test_method_get_table_path(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.get_table_path(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ConnectorTablePathResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_table_path(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.get_table_path(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert_matches_type(ConnectorTablePathResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_table_path(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.get_table_path(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert_matches_type(ConnectorTablePathResponse, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get_table_path(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `table_id` but received ''"):
+ await async_client.connectors.with_raw_response.get_table_path(
+ "",
+ )
+
@parametrize
async def test_method_list_tables(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.list_tables(
@@ -2361,6 +2441,7 @@ async def test_path_params_resolve_clarification(self, async_client: AsyncStruct
async def test_method_search_tables(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.search_tables(
query="query",
+ team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ConnectorSearchTablesResponse, connector, path=["response"])
@@ -2368,6 +2449,7 @@ async def test_method_search_tables(self, async_client: AsyncStructify) -> None:
async def test_raw_response_search_tables(self, async_client: AsyncStructify) -> None:
response = await async_client.connectors.with_raw_response.search_tables(
query="query",
+ team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
@@ -2379,6 +2461,7 @@ async def test_raw_response_search_tables(self, async_client: AsyncStructify) ->
async def test_streaming_response_search_tables(self, async_client: AsyncStructify) -> None:
async with async_client.connectors.with_streaming_response.search_tables(
query="query",
+ team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
From 1e163ca21cb69ea540293df7fa86a2edd74b9c6a Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Feb 2026 21:37:55 +0000
Subject: [PATCH 037/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 8 +-
src/structify/resources/sandbox.py | 75 +++++++++++++++++
src/structify/types/__init__.py | 1 +
.../types/sandbox_get_metrics_response.py | 41 ++++++++++
tests/api_resources/test_sandbox.py | 82 ++++++++++++++++++-
6 files changed, 209 insertions(+), 6 deletions(-)
create mode 100644 src/structify/types/sandbox_get_metrics_response.py
diff --git a/.stats.yml b/.stats.yml
index 153690e71..887facac7 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 239
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-39b2a3aca15e296ba636ee748fcd80f7c70c30cadb53de230062e1706f52e697.yml
-openapi_spec_hash: 42475eb9e7c202e25cffbe9c9cd8970c
-config_hash: f1ac63e6803cb48ae689be81a70a350b
+configured_endpoints: 240
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9c1831c48886d3a27df4609722216aadd053fe094a961317679ce4fa9f246d69.yml
+openapi_spec_hash: 40849903c5daa6c29fcfb14f0378578d
+config_hash: cdb96bee0e686c90cee384c7bc7bfb49
diff --git a/api.md b/api.md
index edf4bce96..42579e4fe 100644
--- a/api.md
+++ b/api.md
@@ -889,13 +889,19 @@ Methods:
Types:
```python
-from structify.types import GetSandboxRequest, Sandbox, SandboxListResponse
+from structify.types import (
+ GetSandboxRequest,
+ Sandbox,
+ SandboxListResponse,
+ SandboxGetMetricsResponse,
+)
```
Methods:
- client.sandbox.list(chat_id) -> SandboxListResponse
- client.sandbox.get(chat_id, \*\*params) -> Sandbox
+- client.sandbox.get_metrics(sandbox_id) -> SandboxGetMetricsResponse
- client.sandbox.update_status(sandbox_id, \*\*params) -> Sandbox
# Scrape
diff --git a/src/structify/resources/sandbox.py b/src/structify/resources/sandbox.py
index 7f9c9bdfc..9a695dcb1 100644
--- a/src/structify/resources/sandbox.py
+++ b/src/structify/resources/sandbox.py
@@ -20,6 +20,7 @@
from .._base_client import make_request_options
from ..types.sandbox import Sandbox
from ..types.sandbox_list_response import SandboxListResponse
+from ..types.sandbox_get_metrics_response import SandboxGetMetricsResponse
__all__ = ["SandboxResource", "AsyncSandboxResource"]
@@ -113,6 +114,37 @@ def get(
cast_to=Sandbox,
)
+ def get_metrics(
+ self,
+ sandbox_id: str,
+ *,
+ # 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,
+ ) -> SandboxGetMetricsResponse:
+ """
+ Args:
+ 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
+ """
+ if not sandbox_id:
+ raise ValueError(f"Expected a non-empty value for `sandbox_id` but received {sandbox_id!r}")
+ return self._get(
+ f"/sandbox/{sandbox_id}/metrics",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SandboxGetMetricsResponse,
+ )
+
def update_status(
self,
sandbox_id: str,
@@ -236,6 +268,37 @@ async def get(
cast_to=Sandbox,
)
+ async def get_metrics(
+ self,
+ sandbox_id: str,
+ *,
+ # 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,
+ ) -> SandboxGetMetricsResponse:
+ """
+ Args:
+ 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
+ """
+ if not sandbox_id:
+ raise ValueError(f"Expected a non-empty value for `sandbox_id` but received {sandbox_id!r}")
+ return await self._get(
+ f"/sandbox/{sandbox_id}/metrics",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SandboxGetMetricsResponse,
+ )
+
async def update_status(
self,
sandbox_id: str,
@@ -282,6 +345,9 @@ def __init__(self, sandbox: SandboxResource) -> None:
self.get = to_raw_response_wrapper(
sandbox.get,
)
+ self.get_metrics = to_raw_response_wrapper(
+ sandbox.get_metrics,
+ )
self.update_status = to_raw_response_wrapper(
sandbox.update_status,
)
@@ -297,6 +363,9 @@ def __init__(self, sandbox: AsyncSandboxResource) -> None:
self.get = async_to_raw_response_wrapper(
sandbox.get,
)
+ self.get_metrics = async_to_raw_response_wrapper(
+ sandbox.get_metrics,
+ )
self.update_status = async_to_raw_response_wrapper(
sandbox.update_status,
)
@@ -312,6 +381,9 @@ def __init__(self, sandbox: SandboxResource) -> None:
self.get = to_streamed_response_wrapper(
sandbox.get,
)
+ self.get_metrics = to_streamed_response_wrapper(
+ sandbox.get_metrics,
+ )
self.update_status = to_streamed_response_wrapper(
sandbox.update_status,
)
@@ -327,6 +399,9 @@ def __init__(self, sandbox: AsyncSandboxResource) -> None:
self.get = async_to_streamed_response_wrapper(
sandbox.get,
)
+ self.get_metrics = async_to_streamed_response_wrapper(
+ sandbox.get_metrics,
+ )
self.update_status = async_to_streamed_response_wrapper(
sandbox.update_status,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 9796a63c2..295561673 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -241,6 +241,7 @@
from .dataset_export_to_csv_params import DatasetExportToCsvParams as DatasetExportToCsvParams
from .delete_chat_session_response import DeleteChatSessionResponse as DeleteChatSessionResponse
from .entity_upload_parquet_params import EntityUploadParquetParams as EntityUploadParquetParams
+from .sandbox_get_metrics_response import SandboxGetMetricsResponse as SandboxGetMetricsResponse
from .sandbox_update_status_params import SandboxUpdateStatusParams as SandboxUpdateStatusParams
from .structure_is_complete_params import StructureIsCompleteParams as StructureIsCompleteParams
from .structure_run_async_response import StructureRunAsyncResponse as StructureRunAsyncResponse
diff --git a/src/structify/types/sandbox_get_metrics_response.py b/src/structify/types/sandbox_get_metrics_response.py
new file mode 100644
index 000000000..bb9d4ee97
--- /dev/null
+++ b/src/structify/types/sandbox_get_metrics_response.py
@@ -0,0 +1,41 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["SandboxGetMetricsResponse", "Memory", "Process", "Sandbox"]
+
+
+class Memory(BaseModel):
+ available_mb: float
+
+ percent: float
+
+ total_mb: float
+
+ used_mb: float
+
+
+class Process(BaseModel):
+ cpu_percent: float
+
+ memory_mb: float
+
+
+class Sandbox(BaseModel):
+ remaining_seconds: int
+
+ start_time: float
+
+ total_timeout_seconds: int
+
+ uptime_seconds: int
+
+
+class SandboxGetMetricsResponse(BaseModel):
+ cpu_percent: float
+
+ memory: Memory
+
+ process: Process
+
+ sandbox: Sandbox
diff --git a/tests/api_resources/test_sandbox.py b/tests/api_resources/test_sandbox.py
index a278863de..a485ed22b 100644
--- a/tests/api_resources/test_sandbox.py
+++ b/tests/api_resources/test_sandbox.py
@@ -9,7 +9,11 @@
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
-from structify.types import Sandbox, SandboxListResponse
+from structify.types import (
+ Sandbox,
+ SandboxListResponse,
+ SandboxGetMetricsResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -101,6 +105,44 @@ def test_path_params_get(self, client: Structify) -> None:
chat_id="",
)
+ @parametrize
+ def test_method_get_metrics(self, client: Structify) -> None:
+ sandbox = client.sandbox.get_metrics(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(SandboxGetMetricsResponse, sandbox, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_metrics(self, client: Structify) -> None:
+ response = client.sandbox.with_raw_response.get_metrics(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sandbox = response.parse()
+ assert_matches_type(SandboxGetMetricsResponse, sandbox, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_metrics(self, client: Structify) -> None:
+ with client.sandbox.with_streaming_response.get_metrics(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sandbox = response.parse()
+ assert_matches_type(SandboxGetMetricsResponse, sandbox, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get_metrics(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sandbox_id` but received ''"):
+ client.sandbox.with_raw_response.get_metrics(
+ "",
+ )
+
@parametrize
def test_method_update_status(self, client: Structify) -> None:
sandbox = client.sandbox.update_status(
@@ -233,6 +275,44 @@ async def test_path_params_get(self, async_client: AsyncStructify) -> None:
chat_id="",
)
+ @parametrize
+ async def test_method_get_metrics(self, async_client: AsyncStructify) -> None:
+ sandbox = await async_client.sandbox.get_metrics(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(SandboxGetMetricsResponse, sandbox, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_metrics(self, async_client: AsyncStructify) -> None:
+ response = await async_client.sandbox.with_raw_response.get_metrics(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sandbox = await response.parse()
+ assert_matches_type(SandboxGetMetricsResponse, sandbox, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_metrics(self, async_client: AsyncStructify) -> None:
+ async with async_client.sandbox.with_streaming_response.get_metrics(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sandbox = await response.parse()
+ assert_matches_type(SandboxGetMetricsResponse, sandbox, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get_metrics(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sandbox_id` but received ''"):
+ await async_client.sandbox.with_raw_response.get_metrics(
+ "",
+ )
+
@parametrize
async def test_method_update_status(self, async_client: AsyncStructify) -> None:
sandbox = await async_client.sandbox.update_status(
From 37cc1d9c7a286de5680f51b9f97125d824022cf1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Feb 2026 01:34:26 +0000
Subject: [PATCH 038/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connectors/connectors.py | 4 ++++
src/structify/types/connector_update_params.py | 2 ++
tests/api_resources/test_connectors.py | 2 ++
4 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 887facac7..15db538b8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 240
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9c1831c48886d3a27df4609722216aadd053fe094a961317679ce4fa9f246d69.yml
-openapi_spec_hash: 40849903c5daa6c29fcfb14f0378578d
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-47c55ba434cd77680d5f49e2a2731af2ca29274b6c435ae3b17b302c11d9446b.yml
+openapi_spec_hash: 10d07bac1c8f7519774379db7191affc
config_hash: cdb96bee0e686c90cee384c7bc7bfb49
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index ce3f1a9f8..54ded075a 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -150,6 +150,7 @@ def update(
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
+ owner_user_id: Optional[str] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
user_ids: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -185,6 +186,7 @@ def update(
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
"oauth_scopes": oauth_scopes,
+ "owner_user_id": owner_user_id,
"team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
"user_ids": user_ids,
@@ -1259,6 +1261,7 @@ async def update(
nango_connection_id: Optional[str] | Omit = omit,
nango_integration_id: Optional[str] | Omit = omit,
oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
+ owner_user_id: Optional[str] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
user_ids: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -1294,6 +1297,7 @@ async def update(
"nango_connection_id": nango_connection_id,
"nango_integration_id": nango_integration_id,
"oauth_scopes": oauth_scopes,
+ "owner_user_id": owner_user_id,
"team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
"user_ids": user_ids,
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index c1b123fb0..9bfcf4a43 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -28,6 +28,8 @@ class ConnectorUpdateParams(TypedDict, total=False):
oauth_scopes: Optional[SequenceNotStr[Optional[str]]]
+ owner_user_id: Optional[str]
+
team_visibility: Optional[Literal["Team", "Private"]]
usage_snippet_override: Optional[str]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index f00858f1a..c468e9ed3 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -100,6 +100,7 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
oauth_scopes=["string"],
+ owner_user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
team_visibility="Team",
usage_snippet_override="usage_snippet_override",
user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
@@ -1383,6 +1384,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
nango_connection_id="nango_connection_id",
nango_integration_id="nango_integration_id",
oauth_scopes=["string"],
+ owner_user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
team_visibility="Team",
usage_snippet_override="usage_snippet_override",
user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
From 003a774cb8dd043eda2b550b00acdb9e9e3b5a64 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Feb 2026 03:00:09 +0000
Subject: [PATCH 039/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connectors/connectors.py | 12 ------------
src/structify/types/connector.py | 2 --
src/structify/types/connector_create_params.py | 3 ---
src/structify/types/connector_update_params.py | 2 --
tests/api_resources/test_connectors.py | 4 ----
6 files changed, 2 insertions(+), 25 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 15db538b8..465ffc462 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 240
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-47c55ba434cd77680d5f49e2a2731af2ca29274b6c435ae3b17b302c11d9446b.yml
-openapi_spec_hash: 10d07bac1c8f7519774379db7191affc
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-cf79b568122c74507adc8e2136a8a4f2cd9b68ddccc08d8a77307bd80930c57e.yml
+openapi_spec_hash: 488c6e6b4eb06f2e780529bb7ac86387
config_hash: cdb96bee0e686c90cee384c7bc7bfb49
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 54ded075a..6326c8ceb 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -94,7 +94,6 @@ def create(
name: str,
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
- nango_integration_id: Optional[str] | Omit = omit,
secrets: Dict[str, 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.
@@ -107,8 +106,6 @@ def create(
Args:
nango_connection_id: Nango connection ID for OAuth token management
- nango_integration_id: Nango integration ID (e.g., "linear", "slack")
-
secrets: Optional secrets/environment variables for the connector
extra_headers: Send extra headers
@@ -127,7 +124,6 @@ def create(
"name": name,
"description": description,
"nango_connection_id": nango_connection_id,
- "nango_integration_id": nango_integration_id,
"secrets": secrets,
},
connector_create_params.ConnectorCreateParams,
@@ -148,7 +144,6 @@ def update(
known_connector_type: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
- nango_integration_id: Optional[str] | Omit = omit,
oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
owner_user_id: Optional[str] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
@@ -184,7 +179,6 @@ def update(
"known_connector_type": known_connector_type,
"name": name,
"nango_connection_id": nango_connection_id,
- "nango_integration_id": nango_integration_id,
"oauth_scopes": oauth_scopes,
"owner_user_id": owner_user_id,
"team_visibility": team_visibility,
@@ -1205,7 +1199,6 @@ async def create(
name: str,
description: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
- nango_integration_id: Optional[str] | Omit = omit,
secrets: Dict[str, 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.
@@ -1218,8 +1211,6 @@ async def create(
Args:
nango_connection_id: Nango connection ID for OAuth token management
- nango_integration_id: Nango integration ID (e.g., "linear", "slack")
-
secrets: Optional secrets/environment variables for the connector
extra_headers: Send extra headers
@@ -1238,7 +1229,6 @@ async def create(
"name": name,
"description": description,
"nango_connection_id": nango_connection_id,
- "nango_integration_id": nango_integration_id,
"secrets": secrets,
},
connector_create_params.ConnectorCreateParams,
@@ -1259,7 +1249,6 @@ async def update(
known_connector_type: Optional[str] | Omit = omit,
name: Optional[str] | Omit = omit,
nango_connection_id: Optional[str] | Omit = omit,
- nango_integration_id: Optional[str] | Omit = omit,
oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
owner_user_id: Optional[str] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
@@ -1295,7 +1284,6 @@ async def update(
"known_connector_type": known_connector_type,
"name": name,
"nango_connection_id": nango_connection_id,
- "nango_integration_id": nango_integration_id,
"oauth_scopes": oauth_scopes,
"owner_user_id": owner_user_id,
"team_visibility": team_visibility,
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 81a2a0a75..a6d645c0e 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -44,8 +44,6 @@ class Connector(BaseModel):
nango_connection_id: Optional[str] = None
- nango_integration_id: Optional[str] = None
-
oauth_scopes: Optional[List[Optional[str]]] = None
usage_snippet_override: Optional[str] = None
diff --git a/src/structify/types/connector_create_params.py b/src/structify/types/connector_create_params.py
index 7c01a2da1..1195618b6 100644
--- a/src/structify/types/connector_create_params.py
+++ b/src/structify/types/connector_create_params.py
@@ -18,8 +18,5 @@ class ConnectorCreateParams(TypedDict, total=False):
nango_connection_id: Optional[str]
"""Nango connection ID for OAuth token management"""
- nango_integration_id: Optional[str]
- """Nango integration ID (e.g., "linear", "slack")"""
-
secrets: Dict[str, str]
"""Optional secrets/environment variables for the connector"""
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index 9bfcf4a43..d9de647ea 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -24,8 +24,6 @@ class ConnectorUpdateParams(TypedDict, total=False):
nango_connection_id: Optional[str]
- nango_integration_id: Optional[str]
-
oauth_scopes: Optional[SequenceNotStr[Optional[str]]]
owner_user_id: Optional[str]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index c468e9ed3..f265f270b 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -50,7 +50,6 @@ def test_method_create_with_all_params(self, client: Structify) -> None:
name="name",
description="description",
nango_connection_id="nango_connection_id",
- nango_integration_id="nango_integration_id",
secrets={"foo": "string"},
)
assert_matches_type(Connector, connector, path=["response"])
@@ -98,7 +97,6 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
known_connector_type="known_connector_type",
name="name",
nango_connection_id="nango_connection_id",
- nango_integration_id="nango_integration_id",
oauth_scopes=["string"],
owner_user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
team_visibility="Team",
@@ -1334,7 +1332,6 @@ async def test_method_create_with_all_params(self, async_client: AsyncStructify)
name="name",
description="description",
nango_connection_id="nango_connection_id",
- nango_integration_id="nango_integration_id",
secrets={"foo": "string"},
)
assert_matches_type(Connector, connector, path=["response"])
@@ -1382,7 +1379,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
known_connector_type="known_connector_type",
name="name",
nango_connection_id="nango_connection_id",
- nango_integration_id="nango_integration_id",
oauth_scopes=["string"],
owner_user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
team_visibility="Team",
From 27ab73d19b4c16c19c1b95015d3a10cd4d9bd58f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Feb 2026 20:57:15 +0000
Subject: [PATCH 040/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 3 +
src/structify/resources/chat.py | 87 +++
src/structify/types/__init__.py | 5 +
src/structify/types/chat_prompt_param.py | 257 +++++++++
.../types/chat_simulate_prompt_params.py | 13 +
src/structify/types/message_param.py | 37 ++
.../types/simulate_prompt_response.py | 9 +
src/structify/types/tool_metadata_param.py | 17 +
tests/api_resources/test_chat.py | 517 ++++++++++++++++++
10 files changed, 949 insertions(+), 4 deletions(-)
create mode 100644 src/structify/types/chat_prompt_param.py
create mode 100644 src/structify/types/chat_simulate_prompt_params.py
create mode 100644 src/structify/types/message_param.py
create mode 100644 src/structify/types/simulate_prompt_response.py
create mode 100644 src/structify/types/tool_metadata_param.py
diff --git a/.stats.yml b/.stats.yml
index 465ffc462..6635bf92f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 240
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-cf79b568122c74507adc8e2136a8a4f2cd9b68ddccc08d8a77307bd80930c57e.yml
-openapi_spec_hash: 488c6e6b4eb06f2e780529bb7ac86387
-config_hash: cdb96bee0e686c90cee384c7bc7bfb49
+configured_endpoints: 241
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-bc7cb8f8c100cf14088a88bd0f9e1f0eb6b00203390e0550a893c677deae2afd.yml
+openapi_spec_hash: 5359dbe81b5021fea1ccc35a42acedf8
+config_hash: ee4e855915a8e241bac39435061fb683
diff --git a/api.md b/api.md
index 42579e4fe..c162f29aa 100644
--- a/api.md
+++ b/api.md
@@ -111,6 +111,8 @@ from structify.types import (
ListChatSessionsResponse,
ListCollaboratorsResponse,
Message,
+ SimulatePromptRequest,
+ SimulatePromptResponse,
ToolInvocation,
ToolResult,
UpdateChatSessionFavoriteRequest,
@@ -158,6 +160,7 @@ Methods:
- client.chat.make_permanent(session_id) -> None
- client.chat.remove_collaborator(user_id, \*, chat_id) -> None
- client.chat.revert_to_commit(session_id, \*\*params) -> ChatRevertToCommitResponse
+- client.chat.simulate_prompt(chat_session_id, \*\*params) -> SimulatePromptResponse
- client.chat.update_session(session_id, \*\*params) -> ChatSession
- client.chat.update_session_favorite(session_id, \*\*params) -> ChatSession
- client.chat.update_visibility(session_id, \*\*params) -> UpdateVisibilityResponse
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index ee70026a8..89b73b3e6 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -16,6 +16,7 @@
chat_add_git_commit_params,
chat_create_session_params,
chat_update_session_params,
+ chat_simulate_prompt_params,
chat_add_collaborator_params,
chat_load_input_files_params,
chat_revert_to_commit_params,
@@ -48,8 +49,10 @@
from .._base_client import make_request_options
from ..types.chat_session import ChatSession
from ..types.chat_visibility import ChatVisibility
+from ..types.chat_prompt_param import ChatPromptParam
from ..types.chat_session_role import ChatSessionRole
from ..types.chat_load_files_response import ChatLoadFilesResponse
+from ..types.simulate_prompt_response import SimulatePromptResponse
from ..types.get_chat_session_response import GetChatSessionResponse
from ..types.get_dependencies_response import GetDependenciesResponse
from ..types.admin_issue_found_response import AdminIssueFoundResponse
@@ -982,6 +985,41 @@ def revert_to_commit(
cast_to=ChatRevertToCommitResponse,
)
+ def simulate_prompt(
+ self,
+ chat_session_id: str,
+ *,
+ chat_prompt: ChatPromptParam,
+ # 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,
+ ) -> SimulatePromptResponse:
+ """
+ any messages to the database.
+
+ Args:
+ 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
+ """
+ if not chat_session_id:
+ raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
+ return self._post(
+ f"/chat/{chat_session_id}/simulate-prompt",
+ body=maybe_transform({"chat_prompt": chat_prompt}, chat_simulate_prompt_params.ChatSimulatePromptParams),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SimulatePromptResponse,
+ )
+
def update_session(
self,
session_id: str,
@@ -2063,6 +2101,43 @@ async def revert_to_commit(
cast_to=ChatRevertToCommitResponse,
)
+ async def simulate_prompt(
+ self,
+ chat_session_id: str,
+ *,
+ chat_prompt: ChatPromptParam,
+ # 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,
+ ) -> SimulatePromptResponse:
+ """
+ any messages to the database.
+
+ Args:
+ 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
+ """
+ if not chat_session_id:
+ raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
+ return await self._post(
+ f"/chat/{chat_session_id}/simulate-prompt",
+ body=await async_maybe_transform(
+ {"chat_prompt": chat_prompt}, chat_simulate_prompt_params.ChatSimulatePromptParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SimulatePromptResponse,
+ )
+
async def update_session(
self,
session_id: str,
@@ -2307,6 +2382,9 @@ def __init__(self, chat: ChatResource) -> None:
self.revert_to_commit = to_raw_response_wrapper(
chat.revert_to_commit,
)
+ self.simulate_prompt = to_raw_response_wrapper(
+ chat.simulate_prompt,
+ )
self.update_session = to_raw_response_wrapper(
chat.update_session,
)
@@ -2398,6 +2476,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.revert_to_commit = async_to_raw_response_wrapper(
chat.revert_to_commit,
)
+ self.simulate_prompt = async_to_raw_response_wrapper(
+ chat.simulate_prompt,
+ )
self.update_session = async_to_raw_response_wrapper(
chat.update_session,
)
@@ -2489,6 +2570,9 @@ def __init__(self, chat: ChatResource) -> None:
self.revert_to_commit = to_streamed_response_wrapper(
chat.revert_to_commit,
)
+ self.simulate_prompt = to_streamed_response_wrapper(
+ chat.simulate_prompt,
+ )
self.update_session = to_streamed_response_wrapper(
chat.update_session,
)
@@ -2580,6 +2664,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.revert_to_commit = async_to_streamed_response_wrapper(
chat.revert_to_commit,
)
+ self.simulate_prompt = async_to_streamed_response_wrapper(
+ chat.simulate_prompt,
+ )
self.update_session = async_to_streamed_response_wrapper(
chat.update_session,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 295561673..1d5c896aa 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -29,6 +29,7 @@
from .relationship import Relationship as Relationship
from .workflow_dag import WorkflowDag as WorkflowDag
from .chat_template import ChatTemplate as ChatTemplate
+from .message_param import MessageParam as MessageParam
from .property_type import PropertyType as PropertyType
from .tool_metadata import ToolMetadata as ToolMetadata
from .dashboard_page import DashboardPage as DashboardPage
@@ -53,6 +54,7 @@
from .job_get_response import JobGetResponse as JobGetResponse
from .save_requirement import SaveRequirement as SaveRequirement
from .workflow_session import WorkflowSession as WorkflowSession
+from .chat_prompt_param import ChatPromptParam as ChatPromptParam
from .chat_session_role import ChatSessionRole as ChatSessionRole
from .connector_catalog import ConnectorCatalog as ConnectorCatalog
from .connector_summary import ConnectorSummary as ConnectorSummary
@@ -95,6 +97,7 @@
from .list_teams_response import ListTeamsResponse as ListTeamsResponse
from .property_type_param import PropertyTypeParam as PropertyTypeParam
from .slack_events_params import SlackEventsParams as SlackEventsParams
+from .tool_metadata_param import ToolMetadataParam as ToolMetadataParam
from .user_refresh_params import UserRefreshParams as UserRefreshParams
from .user_usage_response import UserUsageResponse as UserUsageResponse
from .workflow_run_params import WorkflowRunParams as WorkflowRunParams
@@ -176,6 +179,7 @@
from .match_create_jobs_params import MatchCreateJobsParams as MatchCreateJobsParams
from .refresh_session_response import RefreshSessionResponse as RefreshSessionResponse
from .session_kill_jobs_params import SessionKillJobsParams as SessionKillJobsParams
+from .simulate_prompt_response import SimulatePromptResponse as SimulatePromptResponse
from .team_subscription_status import TeamSubscriptionStatus as TeamSubscriptionStatus
from .wiki_connector_reference import WikiConnectorReference as WikiConnectorReference
from .chat_list_sessions_params import ChatListSessionsParams as ChatListSessionsParams
@@ -214,6 +218,7 @@
from .update_visibility_response import UpdateVisibilityResponse as UpdateVisibilityResponse
from .user_transactions_response import UserTransactionsResponse as UserTransactionsResponse
from .admin_grant_access_response import AdminGrantAccessResponse as AdminGrantAccessResponse
+from .chat_simulate_prompt_params import ChatSimulatePromptParams as ChatSimulatePromptParams
from .dataset_add_property_params import DatasetAddPropertyParams as DatasetAddPropertyParams
from .dataset_view_table_response import DatasetViewTableResponse as DatasetViewTableResponse
from .entity_trigger_merge_params import EntityTriggerMergeParams as EntityTriggerMergeParams
diff --git a/src/structify/types/chat_prompt_param.py b/src/structify/types/chat_prompt_param.py
new file mode 100644
index 000000000..d7817d346
--- /dev/null
+++ b/src/structify/types/chat_prompt_param.py
@@ -0,0 +1,257 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Union, Iterable, Optional
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
+
+from .._types import FileTypes, SequenceNotStr
+from .._utils import PropertyInfo
+from .message_param import MessageParam
+from .tool_metadata_param import ToolMetadataParam
+from .knowledge_graph_param import KnowledgeGraphParam
+from .save_requirement_param import SaveRequirementParam
+from .dataset_descriptor_param import DatasetDescriptorParam
+
+__all__ = [
+ "ChatPromptParam",
+ "DecodingParams",
+ "DecodingParamsParameter",
+ "DecodingParamsParameterMaxTokens",
+ "DecodingParamsParameterMaxCompletionTokens",
+ "DecodingParamsParameterTopP",
+ "DecodingParamsParameterRepeatWindow",
+ "DecodingParamsParameterRepeatPenalty",
+ "DecodingParamsParameterTemperature",
+ "DecodingParamsParameterStopTokens",
+ "DecodingParamsParameterLogitBias",
+ "DecodingParamsParameterFunctions",
+ "DecodingParamsParameterJsonValidator",
+ "DecodingParamsParameterRegexValidator",
+ "DecodingParamsParameterContextFreeGrammar",
+ "DecodingParamsParameterNumBeams",
+ "DecodingParamsParameterCrop",
+ "DecodingParamsParameterThinking",
+ "DecodingParamsParameterVerbosity",
+ "DecodingParamsParameterReasoningEffort",
+ "Metadata",
+ "MetadataFormatterSpecific",
+ "MetadataFormatterSpecificImageMeta",
+ "MetadataFormatterSpecificImageMetaImageMeta",
+ "MetadataFormatterSpecificWebMeta",
+ "MetadataFormatterSpecificWebMetaWebMeta",
+ "MetadataFormatterSpecificWebMetaWebMetaFlag",
+ "MetadataFormatterSpecificTextMeta",
+ "MetadataFormatterSpecificTextMetaTextMeta",
+ "MetadataFormatterSpecificScraperMeta",
+ "MetadataFormatterSpecificScraperMetaScraperMeta",
+]
+
+
+class DecodingParamsParameterMaxTokens(TypedDict, total=False):
+ max_tokens: Required[Annotated[int, PropertyInfo(alias="MaxTokens")]]
+
+
+class DecodingParamsParameterMaxCompletionTokens(TypedDict, total=False):
+ max_completion_tokens: Required[Annotated[int, PropertyInfo(alias="MaxCompletionTokens")]]
+
+
+class DecodingParamsParameterTopP(TypedDict, total=False):
+ top_p: Required[Annotated[float, PropertyInfo(alias="TopP")]]
+
+
+class DecodingParamsParameterRepeatWindow(TypedDict, total=False):
+ repeat_window: Required[Annotated[int, PropertyInfo(alias="RepeatWindow")]]
+
+
+class DecodingParamsParameterRepeatPenalty(TypedDict, total=False):
+ repeat_penalty: Required[Annotated[float, PropertyInfo(alias="RepeatPenalty")]]
+
+
+class DecodingParamsParameterTemperature(TypedDict, total=False):
+ temperature: Required[Annotated[float, PropertyInfo(alias="Temperature")]]
+
+
+class DecodingParamsParameterStopTokens(TypedDict, total=False):
+ stop_tokens: Required[Annotated[SequenceNotStr[str], PropertyInfo(alias="StopTokens")]]
+
+
+class DecodingParamsParameterLogitBias(TypedDict, total=False):
+ logit_bias: Required[Annotated[Dict[str, float], PropertyInfo(alias="LogitBias")]]
+
+
+class DecodingParamsParameterFunctions(TypedDict, total=False):
+ functions: Required[Annotated[Iterable[Dict[str, object]], PropertyInfo(alias="Functions")]]
+
+
+class DecodingParamsParameterJsonValidator(TypedDict, total=False):
+ json_validator: Required[Annotated[Dict[str, object], PropertyInfo(alias="JsonValidator")]]
+
+
+class DecodingParamsParameterRegexValidator(TypedDict, total=False):
+ regex_validator: Required[Annotated[str, PropertyInfo(alias="RegexValidator")]]
+
+
+class DecodingParamsParameterContextFreeGrammar(TypedDict, total=False):
+ context_free_grammar: Required[Annotated[str, PropertyInfo(alias="ContextFreeGrammar")]]
+
+
+class DecodingParamsParameterNumBeams(TypedDict, total=False):
+ num_beams: Required[Annotated[int, PropertyInfo(alias="NumBeams")]]
+
+
+class DecodingParamsParameterCrop(TypedDict, total=False):
+ crop: Required[Annotated[bool, PropertyInfo(alias="Crop")]]
+
+
+class DecodingParamsParameterThinking(TypedDict, total=False):
+ thinking: Required[Annotated[int, PropertyInfo(alias="Thinking")]]
+ """Thinking tokens for Claude 3.7. Contains the budget in tokens for thinking."""
+
+
+class DecodingParamsParameterVerbosity(TypedDict, total=False):
+ verbosity: Required[Annotated[Literal["low", "medium", "high"], PropertyInfo(alias="Verbosity")]]
+
+
+class DecodingParamsParameterReasoningEffort(TypedDict, total=False):
+ reasoning_effort: Required[
+ Annotated[Literal["low", "medium", "high", "minimal"], PropertyInfo(alias="ReasoningEffort")]
+ ]
+
+
+DecodingParamsParameter: TypeAlias = Union[
+ DecodingParamsParameterMaxTokens,
+ DecodingParamsParameterMaxCompletionTokens,
+ DecodingParamsParameterTopP,
+ DecodingParamsParameterRepeatWindow,
+ DecodingParamsParameterRepeatPenalty,
+ DecodingParamsParameterTemperature,
+ DecodingParamsParameterStopTokens,
+ DecodingParamsParameterLogitBias,
+ DecodingParamsParameterFunctions,
+ DecodingParamsParameterJsonValidator,
+ DecodingParamsParameterRegexValidator,
+ DecodingParamsParameterContextFreeGrammar,
+ DecodingParamsParameterNumBeams,
+ DecodingParamsParameterCrop,
+ DecodingParamsParameterThinking,
+ DecodingParamsParameterVerbosity,
+ DecodingParamsParameterReasoningEffort,
+]
+
+
+class DecodingParams(TypedDict, total=False):
+ parameters: Required[Iterable[DecodingParamsParameter]]
+
+
+class MetadataFormatterSpecificImageMetaImageMeta(TypedDict, total=False):
+ image: Required[Optional[str]]
+
+ document_name: Optional[str]
+
+ document_page: Optional[int]
+
+ ocr_content: Optional[str]
+
+
+class MetadataFormatterSpecificImageMeta(TypedDict, total=False):
+ image_meta: Required[Annotated[MetadataFormatterSpecificImageMetaImageMeta, PropertyInfo(alias="ImageMeta")]]
+
+
+class MetadataFormatterSpecificWebMetaWebMetaFlag(TypedDict, total=False):
+ aria_label: Required[Annotated[str, PropertyInfo(alias="ariaLabel")]]
+
+ type: Required[str]
+
+ x: Required[float]
+
+ y: Required[float]
+
+ height: float
+
+ href: Optional[str]
+
+ is_interactive: Annotated[Optional[bool], PropertyInfo(alias="isInteractive")]
+
+ number: Optional[int]
+ """The number by which the flag is referred in image, prompt, and tool calls."""
+
+ text: str
+
+ width: float
+ """
+ The serde default here is to give us backwards compatibility it's fine for these
+ to be anything as long as the image isn't given since it won't regenerate.
+ """
+
+
+class MetadataFormatterSpecificWebMetaWebMeta(TypedDict, total=False):
+ flags: Required[Iterable[MetadataFormatterSpecificWebMetaWebMetaFlag]]
+
+ url: Required[str]
+
+ ocr_content: Optional[str]
+
+ screenshot: Optional[FileTypes]
+
+
+class MetadataFormatterSpecificWebMeta(TypedDict, total=False):
+ web_meta: Required[Annotated[MetadataFormatterSpecificWebMetaWebMeta, PropertyInfo(alias="WebMeta")]]
+
+
+class MetadataFormatterSpecificTextMetaTextMeta(TypedDict, total=False):
+ text: Required[str]
+
+
+class MetadataFormatterSpecificTextMeta(TypedDict, total=False):
+ text_meta: Required[Annotated[MetadataFormatterSpecificTextMetaTextMeta, PropertyInfo(alias="TextMeta")]]
+
+
+class MetadataFormatterSpecificScraperMetaScraperMeta(TypedDict, total=False):
+ html_content: Required[str]
+
+ url: Required[str]
+
+
+class MetadataFormatterSpecificScraperMeta(TypedDict, total=False):
+ scraper_meta: Required[
+ Annotated[MetadataFormatterSpecificScraperMetaScraperMeta, PropertyInfo(alias="ScraperMeta")]
+ ]
+
+
+MetadataFormatterSpecific: TypeAlias = Union[
+ MetadataFormatterSpecificImageMeta,
+ MetadataFormatterSpecificWebMeta,
+ MetadataFormatterSpecificTextMeta,
+ MetadataFormatterSpecificScraperMeta,
+]
+
+
+class Metadata(TypedDict, total=False):
+ """All metadata required to generate a prompt for the LLM"""
+
+ dataset_descriptor: Required[DatasetDescriptorParam]
+ """A dataset is where you put multiple referential schemas.
+
+ A dataset is a complete namespace where all references between schemas are held
+ within the dataset.
+ """
+
+ extracted_entities: Required[Iterable[KnowledgeGraphParam]]
+
+ extraction_criteria: Required[Iterable[SaveRequirementParam]]
+
+ formatter_specific: Required[MetadataFormatterSpecific]
+
+ tool_metadata: Required[Iterable[ToolMetadataParam]]
+
+ qa_potentially_sus_response: Optional[str]
+
+
+class ChatPromptParam(TypedDict, total=False):
+ decoding_params: Required[DecodingParams]
+
+ messages: Required[Iterable[MessageParam]]
+
+ metadata: Required[Metadata]
+ """All metadata required to generate a prompt for the LLM"""
diff --git a/src/structify/types/chat_simulate_prompt_params.py b/src/structify/types/chat_simulate_prompt_params.py
new file mode 100644
index 000000000..c9a3df372
--- /dev/null
+++ b/src/structify/types/chat_simulate_prompt_params.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .chat_prompt_param import ChatPromptParam
+
+__all__ = ["ChatSimulatePromptParams"]
+
+
+class ChatSimulatePromptParams(TypedDict, total=False):
+ chat_prompt: Required[ChatPromptParam]
diff --git a/src/structify/types/message_param.py b/src/structify/types/message_param.py
new file mode 100644
index 000000000..8b5d1bcf9
--- /dev/null
+++ b/src/structify/types/message_param.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, Iterable
+from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict
+
+from .._types import FileTypes
+from .._utils import PropertyInfo
+
+__all__ = ["MessageParam", "Content", "ContentText", "ContentImage"]
+
+
+class ContentText(TypedDict, total=False):
+ text: Required[Annotated[str, PropertyInfo(alias="Text")]]
+
+
+class ContentImage(TypedDict, total=False):
+ image: Required[Annotated[FileTypes, PropertyInfo(alias="Image")]]
+
+
+Content: TypeAlias = Union[ContentText, ContentImage]
+
+
+class MessageParam(TypedDict, total=False):
+ """Our generic definition of a message to a chat agent."""
+
+ content: Required[Iterable[Content]]
+ """
+ We want this to be a vec of contents so we can accurately capture an
+ interleaving of images and text.
+
+ This is meant to be a completely raw, unprocessed representation of the text.
+ Don't take stuff out.
+ """
+
+ role: Required[Literal["user", "system", "assistant"]]
diff --git a/src/structify/types/simulate_prompt_response.py b/src/structify/types/simulate_prompt_response.py
new file mode 100644
index 000000000..a6e39100a
--- /dev/null
+++ b/src/structify/types/simulate_prompt_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["SimulatePromptResponse"]
+
+
+class SimulatePromptResponse(BaseModel):
+ response: str
diff --git a/src/structify/types/tool_metadata_param.py b/src/structify/types/tool_metadata_param.py
new file mode 100644
index 000000000..4ccab3eb5
--- /dev/null
+++ b/src/structify/types/tool_metadata_param.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, TypedDict
+
+__all__ = ["ToolMetadataParam"]
+
+
+class ToolMetadataParam(TypedDict, total=False):
+ description: Required[str]
+
+ name: Required[
+ Literal["Exit", "Save", "Wait", "Type", "Scroll", "ScrollToBottom", "Click", "Hover", "Error", "Google"]
+ ]
+
+ regex_validator: Required[str]
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index ff4e531d3..4db0dcbee 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -15,6 +15,7 @@
ChatSession,
ChatLoadFilesResponse,
GetChatSessionResponse,
+ SimulatePromptResponse,
AdminIssueFoundResponse,
ChatSessionWithMessages,
GetDependenciesResponse,
@@ -1070,6 +1071,264 @@ def test_path_params_revert_to_commit(self, client: Structify) -> None:
commit_hash="commit_hash",
)
+ @parametrize
+ def test_method_simulate_prompt(self, client: Structify) -> None:
+ chat = client.chat.simulate_prompt(
+ chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ )
+ assert_matches_type(SimulatePromptResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_simulate_prompt(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.simulate_prompt(
+ chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(SimulatePromptResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_simulate_prompt(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.simulate_prompt(
+ chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(SimulatePromptResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_simulate_prompt(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_session_id` but received ''"):
+ client.chat.with_raw_response.simulate_prompt(
+ chat_session_id="",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ )
+
@parametrize
def test_method_update_session(self, client: Structify) -> None:
chat = client.chat.update_session(
@@ -2282,6 +2541,264 @@ async def test_path_params_revert_to_commit(self, async_client: AsyncStructify)
commit_hash="commit_hash",
)
+ @parametrize
+ async def test_method_simulate_prompt(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.simulate_prompt(
+ chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ )
+ assert_matches_type(SimulatePromptResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_simulate_prompt(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.simulate_prompt(
+ chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(SimulatePromptResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_simulate_prompt(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.simulate_prompt(
+ chat_session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(SimulatePromptResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_simulate_prompt(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_session_id` but received ''"):
+ await async_client.chat.with_raw_response.simulate_prompt(
+ chat_session_id="",
+ chat_prompt={
+ "decoding_params": {"parameters": [{"max_tokens": 0}]},
+ "messages": [
+ {
+ "content": [{"text": "Text"}],
+ "role": "user",
+ }
+ ],
+ "metadata": {
+ "dataset_descriptor": {
+ "description": "description",
+ "name": "name",
+ "relationships": [
+ {
+ "description": "description",
+ "name": "name",
+ "source_table": "source_table",
+ "target_table": "target_table",
+ }
+ ],
+ "tables": [
+ {
+ "description": "description",
+ "name": "name",
+ "properties": [
+ {
+ "description": "description",
+ "name": "name",
+ }
+ ],
+ }
+ ],
+ },
+ "extracted_entities": [
+ {
+ "entities": [
+ {
+ "id": 0,
+ "properties": {"foo": "string"},
+ "type": "type",
+ }
+ ]
+ }
+ ],
+ "extraction_criteria": [{"relationship_name": "relationship_name"}],
+ "formatter_specific": {"image_meta": {"image": "image"}},
+ "tool_metadata": [
+ {
+ "description": "description",
+ "name": "Exit",
+ "regex_validator": "regex_validator",
+ }
+ ],
+ },
+ },
+ )
+
@parametrize
async def test_method_update_session(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.update_session(
From 74b1b217602570cb51c926fb93057318b4e63a81 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Feb 2026 23:03:51 +0000
Subject: [PATCH 041/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/admin/user.py | 2 ++
src/structify/types/user_info.py | 2 ++
src/structify/types/user_update_params.py | 2 ++
tests/api_resources/test_user.py | 2 ++
5 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6635bf92f..36cbae51e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 241
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-bc7cb8f8c100cf14088a88bd0f9e1f0eb6b00203390e0550a893c677deae2afd.yml
-openapi_spec_hash: 5359dbe81b5021fea1ccc35a42acedf8
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-169747345032c5b1015c8e603b66cc2c18ed3c65d7da6ae08cd5b6f2e8fcdbd2.yml
+openapi_spec_hash: 393c7376e55a96505b67bbac49c69e55
config_hash: ee4e855915a8e241bac39435061fb683
diff --git a/src/structify/types/admin/user.py b/src/structify/types/admin/user.py
index e4c6019d9..75eccf6b7 100644
--- a/src/structify/types/admin/user.py
+++ b/src/structify/types/admin/user.py
@@ -42,6 +42,8 @@ class User(BaseModel):
is_developer: bool
+ notify_for_interaction: bool
+
permissions: List[Optional[Literal["labeler", "qa_labeler", "debug", "human_llm", "none"]]]
updated_at: datetime
diff --git a/src/structify/types/user_info.py b/src/structify/types/user_info.py
index 32a8d4e7e..2977019ec 100644
--- a/src/structify/types/user_info.py
+++ b/src/structify/types/user_info.py
@@ -36,6 +36,8 @@ class UserInfo(BaseModel):
is_developer: bool
+ notify_for_interaction: bool
+
permissions: List[Literal["labeler", "qa_labeler", "debug", "human_llm", "none"]]
user_id: str
diff --git a/src/structify/types/user_update_params.py b/src/structify/types/user_update_params.py
index 9db7c6e9a..a7c787dc4 100644
--- a/src/structify/types/user_update_params.py
+++ b/src/structify/types/user_update_params.py
@@ -62,6 +62,8 @@ class Updates(TypedDict, total=False):
linkedin_url: Optional[str]
+ notify_for_interaction: Optional[bool]
+
onboarding_session_id: Optional[str]
permissions: Optional[List[Optional[Literal["labeler", "qa_labeler", "debug", "human_llm", "none"]]]]
diff --git a/tests/api_resources/test_user.py b/tests/api_resources/test_user.py
index 17f025ce9..a236b9144 100644
--- a/tests/api_resources/test_user.py
+++ b/tests/api_resources/test_user.py
@@ -49,6 +49,7 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
"job_title": "job_title",
"last_selected_team_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
"linkedin_url": "linkedin_url",
+ "notify_for_interaction": True,
"onboarding_session_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
"permissions": ["labeler"],
"slack_user_id": "slack_user_id",
@@ -295,6 +296,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
"job_title": "job_title",
"last_selected_team_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
"linkedin_url": "linkedin_url",
+ "notify_for_interaction": True,
"onboarding_session_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
"permissions": ["labeler"],
"slack_user_id": "slack_user_id",
From e6f9de054fb1e15331baa2949f171b9284e83690 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 3 Mar 2026 00:27:58 +0000
Subject: [PATCH 042/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +--
src/structify/types/tool_invocation.py | 24 +++++++++++++++
src/structify/types/tool_metadata.py | 34 +++++++++++++++++++++-
src/structify/types/tool_metadata_param.py | 34 +++++++++++++++++++++-
tests/api_resources/test_chat.py | 16 +++++-----
5 files changed, 100 insertions(+), 12 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 36cbae51e..73131ed61 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 241
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-169747345032c5b1015c8e603b66cc2c18ed3c65d7da6ae08cd5b6f2e8fcdbd2.yml
-openapi_spec_hash: 393c7376e55a96505b67bbac49c69e55
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-ed3509cffa5c7417ac7329a82bd077e0998bd56f68faed7fb386794ed25c98d6.yml
+openapi_spec_hash: b400292099898ff3aa3af5845f6c3c22
config_hash: ee4e855915a8e241bac39435061fb683
diff --git a/src/structify/types/tool_invocation.py b/src/structify/types/tool_invocation.py
index ab34ba5cf..00ce844d4 100644
--- a/src/structify/types/tool_invocation.py
+++ b/src/structify/types/tool_invocation.py
@@ -36,6 +36,9 @@
"DeleteFileInput",
"MoveFile",
"MoveFileInput",
+ "ApplyPatch",
+ "ApplyPatchInput",
+ "ApplyPatchInputEdit",
"RunBash",
"RunBashInput",
"RunPython",
@@ -230,6 +233,26 @@ class MoveFile(BaseModel):
name: Literal["MoveFile"]
+class ApplyPatchInputEdit(BaseModel):
+ new_string: str
+
+ old_string: str
+
+
+class ApplyPatchInput(BaseModel):
+ apply_all: bool
+
+ edits: List[ApplyPatchInputEdit]
+
+ file: str
+
+
+class ApplyPatch(BaseModel):
+ input: ApplyPatchInput
+
+ name: Literal["ApplyPatch"]
+
+
class RunBashInput(BaseModel):
command: str
@@ -460,6 +483,7 @@ class PinPreviousTool(BaseModel):
ReadNodeLogs,
DeleteFile,
MoveFile,
+ ApplyPatch,
RunBash,
RunPython,
IssueFound,
diff --git a/src/structify/types/tool_metadata.py b/src/structify/types/tool_metadata.py
index a9e3f084c..776b58e24 100644
--- a/src/structify/types/tool_metadata.py
+++ b/src/structify/types/tool_metadata.py
@@ -10,6 +10,38 @@
class ToolMetadata(BaseModel):
description: str
- name: Literal["Exit", "Save", "Wait", "Type", "Scroll", "ScrollToBottom", "Click", "Hover", "Error", "Google"]
+ name: Literal[
+ "WebSearch",
+ "WebNavigate",
+ "ViewPage",
+ "Save",
+ "SaveEntities",
+ "Exit",
+ "ApiExecute",
+ "Javascript",
+ "NavigateToIFrame",
+ "InfiniteScroll",
+ "InspectStep",
+ "ReadNodeLogs",
+ "DeleteFile",
+ "MoveFile",
+ "ApplyPatch",
+ "RunBash",
+ "RunPython",
+ "IssueFound",
+ "SaveDatabase",
+ "SaveSchema",
+ "SaveTable",
+ "SaveColumn",
+ "SaveApiResource",
+ "SaveMemory",
+ "SearchConnectorTables",
+ "RequestClarification",
+ "AddDependency",
+ "SelectData",
+ "CreateConnector",
+ "SearchConnectorTypes",
+ "PinPreviousTool",
+ ]
regex_validator: str
diff --git a/src/structify/types/tool_metadata_param.py b/src/structify/types/tool_metadata_param.py
index 4ccab3eb5..6b3f77eed 100644
--- a/src/structify/types/tool_metadata_param.py
+++ b/src/structify/types/tool_metadata_param.py
@@ -11,7 +11,39 @@ class ToolMetadataParam(TypedDict, total=False):
description: Required[str]
name: Required[
- Literal["Exit", "Save", "Wait", "Type", "Scroll", "ScrollToBottom", "Click", "Hover", "Error", "Google"]
+ Literal[
+ "WebSearch",
+ "WebNavigate",
+ "ViewPage",
+ "Save",
+ "SaveEntities",
+ "Exit",
+ "ApiExecute",
+ "Javascript",
+ "NavigateToIFrame",
+ "InfiniteScroll",
+ "InspectStep",
+ "ReadNodeLogs",
+ "DeleteFile",
+ "MoveFile",
+ "ApplyPatch",
+ "RunBash",
+ "RunPython",
+ "IssueFound",
+ "SaveDatabase",
+ "SaveSchema",
+ "SaveTable",
+ "SaveColumn",
+ "SaveApiResource",
+ "SaveMemory",
+ "SearchConnectorTables",
+ "RequestClarification",
+ "AddDependency",
+ "SelectData",
+ "CreateConnector",
+ "SearchConnectorTypes",
+ "PinPreviousTool",
+ ]
]
regex_validator: Required[str]
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 4db0dcbee..b2e5a6069 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -1124,7 +1124,7 @@ def test_method_simulate_prompt(self, client: Structify) -> None:
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -1186,7 +1186,7 @@ def test_raw_response_simulate_prompt(self, client: Structify) -> None:
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -1252,7 +1252,7 @@ def test_streaming_response_simulate_prompt(self, client: Structify) -> None:
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -1321,7 +1321,7 @@ def test_path_params_simulate_prompt(self, client: Structify) -> None:
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -2594,7 +2594,7 @@ async def test_method_simulate_prompt(self, async_client: AsyncStructify) -> Non
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -2656,7 +2656,7 @@ async def test_raw_response_simulate_prompt(self, async_client: AsyncStructify)
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -2722,7 +2722,7 @@ async def test_streaming_response_simulate_prompt(self, async_client: AsyncStruc
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
@@ -2791,7 +2791,7 @@ async def test_path_params_simulate_prompt(self, async_client: AsyncStructify) -
"tool_metadata": [
{
"description": "description",
- "name": "Exit",
+ "name": "WebSearch",
"regex_validator": "regex_validator",
}
],
From 206ea94f15ea80ed61eca73e32ef753a57b2ede7 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 3 Mar 2026 13:47:54 +0000
Subject: [PATCH 043/105] chore(internal): codegen related update
---
src/structify/_client.py | 42 +++++++++++++++
src/structify/resources/admin/admin.py | 52 +++++++++++++++++++
.../resources/admin/chat_templates.py | 4 ++
src/structify/resources/admin/connector.py | 4 ++
src/structify/resources/admin/dataset.py | 4 ++
.../resources/admin/functional_tests.py | 4 ++
src/structify/resources/admin/jobs.py | 4 ++
src/structify/resources/admin/sandbox.py | 4 ++
src/structify/resources/admin/teams.py | 4 ++
src/structify/resources/admin/users.py | 4 ++
src/structify/resources/code.py | 4 ++
.../resources/connector_catalog/admin.py | 4 ++
.../connector_catalog/connector_catalog.py | 6 +++
src/structify/resources/datasets/datasets.py | 4 ++
src/structify/resources/projects.py | 4 ++
src/structify/resources/sandbox.py | 4 ++
src/structify/resources/user/api_keys.py | 4 ++
src/structify/resources/user/user.py | 6 +++
src/structify/resources/whitelabel.py | 4 ++
src/structify/resources/wiki.py | 4 ++
20 files changed, 170 insertions(+)
diff --git a/src/structify/_client.py b/src/structify/_client.py
index 76bd5e434..213456c0c 100644
--- a/src/structify/_client.py
+++ b/src/structify/_client.py
@@ -192,6 +192,7 @@ def __init__(
@cached_property
def whitelabel(self) -> WhitelabelResource:
+ """Whitelabeled service proxy endpoints"""
from .resources.whitelabel import WhitelabelResource
return WhitelabelResource(self)
@@ -216,6 +217,7 @@ def teams(self) -> TeamsResource:
@cached_property
def wiki(self) -> WikiResource:
+ """Team wiki page management endpoints"""
from .resources.wiki import WikiResource
return WikiResource(self)
@@ -228,18 +230,21 @@ def polars(self) -> PolarsResource:
@cached_property
def projects(self) -> ProjectsResource:
+ """Project management endpoints"""
from .resources.projects import ProjectsResource
return ProjectsResource(self)
@cached_property
def admin(self) -> AdminResource:
+ """Admin endpoints"""
from .resources.admin import AdminResource
return AdminResource(self)
@cached_property
def datasets(self) -> DatasetsResource:
+ """Dataset management endpoints"""
from .resources.datasets import DatasetsResource
return DatasetsResource(self)
@@ -312,6 +317,7 @@ def entities(self) -> EntitiesResource:
@cached_property
def sandbox(self) -> SandboxResource:
+ """Sandbox management endpoints"""
from .resources.sandbox import SandboxResource
return SandboxResource(self)
@@ -324,6 +330,7 @@ def scrape(self) -> ScrapeResource:
@cached_property
def code(self) -> CodeResource:
+ """Code generation endpoints"""
from .resources.code import CodeResource
return CodeResource(self)
@@ -579,6 +586,7 @@ def __init__(
@cached_property
def whitelabel(self) -> AsyncWhitelabelResource:
+ """Whitelabeled service proxy endpoints"""
from .resources.whitelabel import AsyncWhitelabelResource
return AsyncWhitelabelResource(self)
@@ -603,24 +611,28 @@ def teams(self) -> AsyncTeamsResource:
@cached_property
def wiki(self) -> AsyncWikiResource:
+ """Team wiki page management endpoints"""
from .resources.wiki import AsyncWikiResource
return AsyncWikiResource(self)
@cached_property
def projects(self) -> AsyncProjectsResource:
+ """Project management endpoints"""
from .resources.projects import AsyncProjectsResource
return AsyncProjectsResource(self)
@cached_property
def admin(self) -> AsyncAdminResource:
+ """Admin endpoints"""
from .resources.admin import AsyncAdminResource
return AsyncAdminResource(self)
@cached_property
def datasets(self) -> AsyncDatasetsResource:
+ """Dataset management endpoints"""
from .resources.datasets import AsyncDatasetsResource
return AsyncDatasetsResource(self)
@@ -693,6 +705,7 @@ def entities(self) -> AsyncEntitiesResource:
@cached_property
def sandbox(self) -> AsyncSandboxResource:
+ """Sandbox management endpoints"""
from .resources.sandbox import AsyncSandboxResource
return AsyncSandboxResource(self)
@@ -705,6 +718,7 @@ def scrape(self) -> AsyncScrapeResource:
@cached_property
def code(self) -> AsyncCodeResource:
+ """Code generation endpoints"""
from .resources.code import AsyncCodeResource
return AsyncCodeResource(self)
@@ -883,6 +897,7 @@ def __init__(self, client: Structify) -> None:
@cached_property
def whitelabel(self) -> whitelabel.WhitelabelResourceWithRawResponse:
+ """Whitelabeled service proxy endpoints"""
from .resources.whitelabel import WhitelabelResourceWithRawResponse
return WhitelabelResourceWithRawResponse(self._client.whitelabel)
@@ -907,12 +922,14 @@ def teams(self) -> teams.TeamsResourceWithRawResponse:
@cached_property
def wiki(self) -> wiki.WikiResourceWithRawResponse:
+ """Team wiki page management endpoints"""
from .resources.wiki import WikiResourceWithRawResponse
return WikiResourceWithRawResponse(self._client.wiki)
@cached_property
def projects(self) -> projects.ProjectsResourceWithRawResponse:
+ """Project management endpoints"""
from .resources.projects import ProjectsResourceWithRawResponse
return ProjectsResourceWithRawResponse(self._client.projects)
@@ -925,12 +942,14 @@ def polars(self) -> polars.PolarsResourceWithRawResponse:
@cached_property
def admin(self) -> admin.AdminResourceWithRawResponse:
+ """Admin endpoints"""
from .resources.admin import AdminResourceWithRawResponse
return AdminResourceWithRawResponse(self._client.admin)
@cached_property
def datasets(self) -> datasets.DatasetsResourceWithRawResponse:
+ """Dataset management endpoints"""
from .resources.datasets import DatasetsResourceWithRawResponse
return DatasetsResourceWithRawResponse(self._client.datasets)
@@ -1003,6 +1022,7 @@ def entities(self) -> entities.EntitiesResourceWithRawResponse:
@cached_property
def sandbox(self) -> sandbox.SandboxResourceWithRawResponse:
+ """Sandbox management endpoints"""
from .resources.sandbox import SandboxResourceWithRawResponse
return SandboxResourceWithRawResponse(self._client.sandbox)
@@ -1015,6 +1035,7 @@ def scrape(self) -> scrape.ScrapeResourceWithRawResponse:
@cached_property
def code(self) -> code.CodeResourceWithRawResponse:
+ """Code generation endpoints"""
from .resources.code import CodeResourceWithRawResponse
return CodeResourceWithRawResponse(self._client.code)
@@ -1052,6 +1073,7 @@ def __init__(self, client: AsyncStructify) -> None:
@cached_property
def whitelabel(self) -> whitelabel.AsyncWhitelabelResourceWithRawResponse:
+ """Whitelabeled service proxy endpoints"""
from .resources.whitelabel import AsyncWhitelabelResourceWithRawResponse
return AsyncWhitelabelResourceWithRawResponse(self._client.whitelabel)
@@ -1076,24 +1098,28 @@ def teams(self) -> teams.AsyncTeamsResourceWithRawResponse:
@cached_property
def wiki(self) -> wiki.AsyncWikiResourceWithRawResponse:
+ """Team wiki page management endpoints"""
from .resources.wiki import AsyncWikiResourceWithRawResponse
return AsyncWikiResourceWithRawResponse(self._client.wiki)
@cached_property
def projects(self) -> projects.AsyncProjectsResourceWithRawResponse:
+ """Project management endpoints"""
from .resources.projects import AsyncProjectsResourceWithRawResponse
return AsyncProjectsResourceWithRawResponse(self._client.projects)
@cached_property
def admin(self) -> admin.AsyncAdminResourceWithRawResponse:
+ """Admin endpoints"""
from .resources.admin import AsyncAdminResourceWithRawResponse
return AsyncAdminResourceWithRawResponse(self._client.admin)
@cached_property
def datasets(self) -> datasets.AsyncDatasetsResourceWithRawResponse:
+ """Dataset management endpoints"""
from .resources.datasets import AsyncDatasetsResourceWithRawResponse
return AsyncDatasetsResourceWithRawResponse(self._client.datasets)
@@ -1166,6 +1192,7 @@ def entities(self) -> entities.AsyncEntitiesResourceWithRawResponse:
@cached_property
def sandbox(self) -> sandbox.AsyncSandboxResourceWithRawResponse:
+ """Sandbox management endpoints"""
from .resources.sandbox import AsyncSandboxResourceWithRawResponse
return AsyncSandboxResourceWithRawResponse(self._client.sandbox)
@@ -1178,6 +1205,7 @@ def scrape(self) -> scrape.AsyncScrapeResourceWithRawResponse:
@cached_property
def code(self) -> code.AsyncCodeResourceWithRawResponse:
+ """Code generation endpoints"""
from .resources.code import AsyncCodeResourceWithRawResponse
return AsyncCodeResourceWithRawResponse(self._client.code)
@@ -1215,6 +1243,7 @@ def __init__(self, client: Structify) -> None:
@cached_property
def whitelabel(self) -> whitelabel.WhitelabelResourceWithStreamingResponse:
+ """Whitelabeled service proxy endpoints"""
from .resources.whitelabel import WhitelabelResourceWithStreamingResponse
return WhitelabelResourceWithStreamingResponse(self._client.whitelabel)
@@ -1239,12 +1268,14 @@ def teams(self) -> teams.TeamsResourceWithStreamingResponse:
@cached_property
def wiki(self) -> wiki.WikiResourceWithStreamingResponse:
+ """Team wiki page management endpoints"""
from .resources.wiki import WikiResourceWithStreamingResponse
return WikiResourceWithStreamingResponse(self._client.wiki)
@cached_property
def projects(self) -> projects.ProjectsResourceWithStreamingResponse:
+ """Project management endpoints"""
from .resources.projects import ProjectsResourceWithStreamingResponse
return ProjectsResourceWithStreamingResponse(self._client.projects)
@@ -1257,12 +1288,14 @@ def polars(self) -> polars.PolarsResourceWithStreamingResponse:
@cached_property
def admin(self) -> admin.AdminResourceWithStreamingResponse:
+ """Admin endpoints"""
from .resources.admin import AdminResourceWithStreamingResponse
return AdminResourceWithStreamingResponse(self._client.admin)
@cached_property
def datasets(self) -> datasets.DatasetsResourceWithStreamingResponse:
+ """Dataset management endpoints"""
from .resources.datasets import DatasetsResourceWithStreamingResponse
return DatasetsResourceWithStreamingResponse(self._client.datasets)
@@ -1335,6 +1368,7 @@ def entities(self) -> entities.EntitiesResourceWithStreamingResponse:
@cached_property
def sandbox(self) -> sandbox.SandboxResourceWithStreamingResponse:
+ """Sandbox management endpoints"""
from .resources.sandbox import SandboxResourceWithStreamingResponse
return SandboxResourceWithStreamingResponse(self._client.sandbox)
@@ -1347,6 +1381,7 @@ def scrape(self) -> scrape.ScrapeResourceWithStreamingResponse:
@cached_property
def code(self) -> code.CodeResourceWithStreamingResponse:
+ """Code generation endpoints"""
from .resources.code import CodeResourceWithStreamingResponse
return CodeResourceWithStreamingResponse(self._client.code)
@@ -1384,6 +1419,7 @@ def __init__(self, client: AsyncStructify) -> None:
@cached_property
def whitelabel(self) -> whitelabel.AsyncWhitelabelResourceWithStreamingResponse:
+ """Whitelabeled service proxy endpoints"""
from .resources.whitelabel import AsyncWhitelabelResourceWithStreamingResponse
return AsyncWhitelabelResourceWithStreamingResponse(self._client.whitelabel)
@@ -1408,24 +1444,28 @@ def teams(self) -> teams.AsyncTeamsResourceWithStreamingResponse:
@cached_property
def wiki(self) -> wiki.AsyncWikiResourceWithStreamingResponse:
+ """Team wiki page management endpoints"""
from .resources.wiki import AsyncWikiResourceWithStreamingResponse
return AsyncWikiResourceWithStreamingResponse(self._client.wiki)
@cached_property
def projects(self) -> projects.AsyncProjectsResourceWithStreamingResponse:
+ """Project management endpoints"""
from .resources.projects import AsyncProjectsResourceWithStreamingResponse
return AsyncProjectsResourceWithStreamingResponse(self._client.projects)
@cached_property
def admin(self) -> admin.AsyncAdminResourceWithStreamingResponse:
+ """Admin endpoints"""
from .resources.admin import AsyncAdminResourceWithStreamingResponse
return AsyncAdminResourceWithStreamingResponse(self._client.admin)
@cached_property
def datasets(self) -> datasets.AsyncDatasetsResourceWithStreamingResponse:
+ """Dataset management endpoints"""
from .resources.datasets import AsyncDatasetsResourceWithStreamingResponse
return AsyncDatasetsResourceWithStreamingResponse(self._client.datasets)
@@ -1498,6 +1538,7 @@ def entities(self) -> entities.AsyncEntitiesResourceWithStreamingResponse:
@cached_property
def sandbox(self) -> sandbox.AsyncSandboxResourceWithStreamingResponse:
+ """Sandbox management endpoints"""
from .resources.sandbox import AsyncSandboxResourceWithStreamingResponse
return AsyncSandboxResourceWithStreamingResponse(self._client.sandbox)
@@ -1510,6 +1551,7 @@ def scrape(self) -> scrape.AsyncScrapeResourceWithStreamingResponse:
@cached_property
def code(self) -> code.AsyncCodeResourceWithStreamingResponse:
+ """Code generation endpoints"""
from .resources.code import AsyncCodeResourceWithStreamingResponse
return AsyncCodeResourceWithStreamingResponse(self._client.code)
diff --git a/src/structify/resources/admin/admin.py b/src/structify/resources/admin/admin.py
index 585fe9825..5b46c5a38 100644
--- a/src/structify/resources/admin/admin.py
+++ b/src/structify/resources/admin/admin.py
@@ -85,36 +85,46 @@
class AdminResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def teams(self) -> TeamsResource:
+ """Admin endpoints"""
return TeamsResource(self._client)
@cached_property
def dataset(self) -> DatasetResource:
+ """Admin endpoints"""
return DatasetResource(self._client)
@cached_property
def jobs(self) -> JobsResource:
+ """Admin endpoints"""
return JobsResource(self._client)
@cached_property
def sandbox(self) -> SandboxResource:
+ """Admin endpoints"""
return SandboxResource(self._client)
@cached_property
def functional_tests(self) -> FunctionalTestsResource:
+ """Admin endpoints"""
return FunctionalTestsResource(self._client)
@cached_property
def users(self) -> UsersResource:
+ """Admin endpoints"""
return UsersResource(self._client)
@cached_property
def chat_templates(self) -> ChatTemplatesResource:
+ """Admin endpoints"""
return ChatTemplatesResource(self._client)
@cached_property
def connector(self) -> ConnectorResource:
+ """Admin endpoints"""
return ConnectorResource(self._client)
@cached_property
@@ -169,36 +179,46 @@ def report_critical(
class AsyncAdminResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def teams(self) -> AsyncTeamsResource:
+ """Admin endpoints"""
return AsyncTeamsResource(self._client)
@cached_property
def dataset(self) -> AsyncDatasetResource:
+ """Admin endpoints"""
return AsyncDatasetResource(self._client)
@cached_property
def jobs(self) -> AsyncJobsResource:
+ """Admin endpoints"""
return AsyncJobsResource(self._client)
@cached_property
def sandbox(self) -> AsyncSandboxResource:
+ """Admin endpoints"""
return AsyncSandboxResource(self._client)
@cached_property
def functional_tests(self) -> AsyncFunctionalTestsResource:
+ """Admin endpoints"""
return AsyncFunctionalTestsResource(self._client)
@cached_property
def users(self) -> AsyncUsersResource:
+ """Admin endpoints"""
return AsyncUsersResource(self._client)
@cached_property
def chat_templates(self) -> AsyncChatTemplatesResource:
+ """Admin endpoints"""
return AsyncChatTemplatesResource(self._client)
@cached_property
def connector(self) -> AsyncConnectorResource:
+ """Admin endpoints"""
return AsyncConnectorResource(self._client)
@cached_property
@@ -264,34 +284,42 @@ def __init__(self, admin: AdminResource) -> None:
@cached_property
def teams(self) -> TeamsResourceWithRawResponse:
+ """Admin endpoints"""
return TeamsResourceWithRawResponse(self._admin.teams)
@cached_property
def dataset(self) -> DatasetResourceWithRawResponse:
+ """Admin endpoints"""
return DatasetResourceWithRawResponse(self._admin.dataset)
@cached_property
def jobs(self) -> JobsResourceWithRawResponse:
+ """Admin endpoints"""
return JobsResourceWithRawResponse(self._admin.jobs)
@cached_property
def sandbox(self) -> SandboxResourceWithRawResponse:
+ """Admin endpoints"""
return SandboxResourceWithRawResponse(self._admin.sandbox)
@cached_property
def functional_tests(self) -> FunctionalTestsResourceWithRawResponse:
+ """Admin endpoints"""
return FunctionalTestsResourceWithRawResponse(self._admin.functional_tests)
@cached_property
def users(self) -> UsersResourceWithRawResponse:
+ """Admin endpoints"""
return UsersResourceWithRawResponse(self._admin.users)
@cached_property
def chat_templates(self) -> ChatTemplatesResourceWithRawResponse:
+ """Admin endpoints"""
return ChatTemplatesResourceWithRawResponse(self._admin.chat_templates)
@cached_property
def connector(self) -> ConnectorResourceWithRawResponse:
+ """Admin endpoints"""
return ConnectorResourceWithRawResponse(self._admin.connector)
@@ -305,34 +333,42 @@ def __init__(self, admin: AsyncAdminResource) -> None:
@cached_property
def teams(self) -> AsyncTeamsResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncTeamsResourceWithRawResponse(self._admin.teams)
@cached_property
def dataset(self) -> AsyncDatasetResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncDatasetResourceWithRawResponse(self._admin.dataset)
@cached_property
def jobs(self) -> AsyncJobsResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncJobsResourceWithRawResponse(self._admin.jobs)
@cached_property
def sandbox(self) -> AsyncSandboxResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncSandboxResourceWithRawResponse(self._admin.sandbox)
@cached_property
def functional_tests(self) -> AsyncFunctionalTestsResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncFunctionalTestsResourceWithRawResponse(self._admin.functional_tests)
@cached_property
def users(self) -> AsyncUsersResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncUsersResourceWithRawResponse(self._admin.users)
@cached_property
def chat_templates(self) -> AsyncChatTemplatesResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncChatTemplatesResourceWithRawResponse(self._admin.chat_templates)
@cached_property
def connector(self) -> AsyncConnectorResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncConnectorResourceWithRawResponse(self._admin.connector)
@@ -346,34 +382,42 @@ def __init__(self, admin: AdminResource) -> None:
@cached_property
def teams(self) -> TeamsResourceWithStreamingResponse:
+ """Admin endpoints"""
return TeamsResourceWithStreamingResponse(self._admin.teams)
@cached_property
def dataset(self) -> DatasetResourceWithStreamingResponse:
+ """Admin endpoints"""
return DatasetResourceWithStreamingResponse(self._admin.dataset)
@cached_property
def jobs(self) -> JobsResourceWithStreamingResponse:
+ """Admin endpoints"""
return JobsResourceWithStreamingResponse(self._admin.jobs)
@cached_property
def sandbox(self) -> SandboxResourceWithStreamingResponse:
+ """Admin endpoints"""
return SandboxResourceWithStreamingResponse(self._admin.sandbox)
@cached_property
def functional_tests(self) -> FunctionalTestsResourceWithStreamingResponse:
+ """Admin endpoints"""
return FunctionalTestsResourceWithStreamingResponse(self._admin.functional_tests)
@cached_property
def users(self) -> UsersResourceWithStreamingResponse:
+ """Admin endpoints"""
return UsersResourceWithStreamingResponse(self._admin.users)
@cached_property
def chat_templates(self) -> ChatTemplatesResourceWithStreamingResponse:
+ """Admin endpoints"""
return ChatTemplatesResourceWithStreamingResponse(self._admin.chat_templates)
@cached_property
def connector(self) -> ConnectorResourceWithStreamingResponse:
+ """Admin endpoints"""
return ConnectorResourceWithStreamingResponse(self._admin.connector)
@@ -387,32 +431,40 @@ def __init__(self, admin: AsyncAdminResource) -> None:
@cached_property
def teams(self) -> AsyncTeamsResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncTeamsResourceWithStreamingResponse(self._admin.teams)
@cached_property
def dataset(self) -> AsyncDatasetResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncDatasetResourceWithStreamingResponse(self._admin.dataset)
@cached_property
def jobs(self) -> AsyncJobsResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncJobsResourceWithStreamingResponse(self._admin.jobs)
@cached_property
def sandbox(self) -> AsyncSandboxResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncSandboxResourceWithStreamingResponse(self._admin.sandbox)
@cached_property
def functional_tests(self) -> AsyncFunctionalTestsResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncFunctionalTestsResourceWithStreamingResponse(self._admin.functional_tests)
@cached_property
def users(self) -> AsyncUsersResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncUsersResourceWithStreamingResponse(self._admin.users)
@cached_property
def chat_templates(self) -> AsyncChatTemplatesResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncChatTemplatesResourceWithStreamingResponse(self._admin.chat_templates)
@cached_property
def connector(self) -> AsyncConnectorResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncConnectorResourceWithStreamingResponse(self._admin.connector)
diff --git a/src/structify/resources/admin/chat_templates.py b/src/structify/resources/admin/chat_templates.py
index 6ecc7daed..8d46ccc44 100644
--- a/src/structify/resources/admin/chat_templates.py
+++ b/src/structify/resources/admin/chat_templates.py
@@ -25,6 +25,8 @@
class ChatTemplatesResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> ChatTemplatesResourceWithRawResponse:
"""
@@ -174,6 +176,8 @@ def list(
class AsyncChatTemplatesResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncChatTemplatesResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/connector.py b/src/structify/resources/admin/connector.py
index 399924bd4..ab8d89fd8 100644
--- a/src/structify/resources/admin/connector.py
+++ b/src/structify/resources/admin/connector.py
@@ -25,6 +25,8 @@
class ConnectorResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> ConnectorResourceWithRawResponse:
"""
@@ -87,6 +89,8 @@ def clone(
class AsyncConnectorResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncConnectorResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/dataset.py b/src/structify/resources/admin/dataset.py
index cf49a6553..aee899163 100644
--- a/src/structify/resources/admin/dataset.py
+++ b/src/structify/resources/admin/dataset.py
@@ -22,6 +22,8 @@
class DatasetResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> DatasetResourceWithRawResponse:
"""
@@ -78,6 +80,8 @@ def get_by_id(
class AsyncDatasetResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncDatasetResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/functional_tests.py b/src/structify/resources/admin/functional_tests.py
index 2cec2b8d0..2497a10df 100644
--- a/src/structify/resources/admin/functional_tests.py
+++ b/src/structify/resources/admin/functional_tests.py
@@ -31,6 +31,8 @@
class FunctionalTestsResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> FunctionalTestsResourceWithRawResponse:
"""
@@ -268,6 +270,8 @@ def update_results(
class AsyncFunctionalTestsResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncFunctionalTestsResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index 91370faf3..16f81550e 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -28,6 +28,8 @@
class JobsResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> JobsResourceWithRawResponse:
"""
@@ -156,6 +158,8 @@ def kill_by_user(
class AsyncJobsResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncJobsResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/sandbox.py b/src/structify/resources/admin/sandbox.py
index 413ec58f5..141c56569 100644
--- a/src/structify/resources/admin/sandbox.py
+++ b/src/structify/resources/admin/sandbox.py
@@ -25,6 +25,8 @@
class SandboxResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> SandboxResourceWithRawResponse:
"""
@@ -87,6 +89,8 @@ def list(
class AsyncSandboxResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncSandboxResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/teams.py b/src/structify/resources/admin/teams.py
index c9c6989fc..3f0befb52 100644
--- a/src/structify/resources/admin/teams.py
+++ b/src/structify/resources/admin/teams.py
@@ -47,6 +47,8 @@
class TeamsResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> TeamsResourceWithRawResponse:
"""
@@ -456,6 +458,8 @@ def update_seats_override(
class AsyncTeamsResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncTeamsResourceWithRawResponse:
"""
diff --git a/src/structify/resources/admin/users.py b/src/structify/resources/admin/users.py
index 7b17e7ff6..8ff3d38cb 100644
--- a/src/structify/resources/admin/users.py
+++ b/src/structify/resources/admin/users.py
@@ -29,6 +29,8 @@
class UsersResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> UsersResourceWithRawResponse:
"""
@@ -206,6 +208,8 @@ def impersonate(
class AsyncUsersResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncUsersResourceWithRawResponse:
"""
diff --git a/src/structify/resources/code.py b/src/structify/resources/code.py
index 8db099382..61b45f3e3 100644
--- a/src/structify/resources/code.py
+++ b/src/structify/resources/code.py
@@ -23,6 +23,8 @@
class CodeResource(SyncAPIResource):
+ """Code generation endpoints"""
+
@cached_property
def with_raw_response(self) -> CodeResourceWithRawResponse:
"""
@@ -138,6 +140,8 @@ def interrupt_generation(
class AsyncCodeResource(AsyncAPIResource):
+ """Code generation endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncCodeResourceWithRawResponse:
"""
diff --git a/src/structify/resources/connector_catalog/admin.py b/src/structify/resources/connector_catalog/admin.py
index 8469388d6..10177d246 100644
--- a/src/structify/resources/connector_catalog/admin.py
+++ b/src/structify/resources/connector_catalog/admin.py
@@ -61,6 +61,8 @@
class AdminResource(SyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AdminResourceWithRawResponse:
"""
@@ -715,6 +717,8 @@ def upload_logo(
class AsyncAdminResource(AsyncAPIResource):
+ """Admin endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncAdminResourceWithRawResponse:
"""
diff --git a/src/structify/resources/connector_catalog/connector_catalog.py b/src/structify/resources/connector_catalog/connector_catalog.py
index 955bd4e15..ce8920a03 100644
--- a/src/structify/resources/connector_catalog/connector_catalog.py
+++ b/src/structify/resources/connector_catalog/connector_catalog.py
@@ -43,6 +43,7 @@
class ConnectorCatalogResource(SyncAPIResource):
@cached_property
def admin(self) -> AdminResource:
+ """Admin endpoints"""
return AdminResource(self._client)
@cached_property
@@ -184,6 +185,7 @@ def get_logo(
class AsyncConnectorCatalogResource(AsyncAPIResource):
@cached_property
def admin(self) -> AsyncAdminResource:
+ """Admin endpoints"""
return AsyncAdminResource(self._client)
@cached_property
@@ -339,6 +341,7 @@ def __init__(self, connector_catalog: ConnectorCatalogResource) -> None:
@cached_property
def admin(self) -> AdminResourceWithRawResponse:
+ """Admin endpoints"""
return AdminResourceWithRawResponse(self._connector_catalog.admin)
@@ -359,6 +362,7 @@ def __init__(self, connector_catalog: AsyncConnectorCatalogResource) -> None:
@cached_property
def admin(self) -> AsyncAdminResourceWithRawResponse:
+ """Admin endpoints"""
return AsyncAdminResourceWithRawResponse(self._connector_catalog.admin)
@@ -379,6 +383,7 @@ def __init__(self, connector_catalog: ConnectorCatalogResource) -> None:
@cached_property
def admin(self) -> AdminResourceWithStreamingResponse:
+ """Admin endpoints"""
return AdminResourceWithStreamingResponse(self._connector_catalog.admin)
@@ -399,4 +404,5 @@ def __init__(self, connector_catalog: AsyncConnectorCatalogResource) -> None:
@cached_property
def admin(self) -> AsyncAdminResourceWithStreamingResponse:
+ """Admin endpoints"""
return AsyncAdminResourceWithStreamingResponse(self._connector_catalog.admin)
diff --git a/src/structify/resources/datasets/datasets.py b/src/structify/resources/datasets/datasets.py
index 3e122b78a..952b89283 100644
--- a/src/structify/resources/datasets/datasets.py
+++ b/src/structify/resources/datasets/datasets.py
@@ -64,6 +64,8 @@
class DatasetsResource(SyncAPIResource):
+ """Dataset management endpoints"""
+
@cached_property
def evaluate(self) -> EvaluateResource:
return EvaluateResource(self._client)
@@ -844,6 +846,8 @@ def view_tables_with_relationships(
class AsyncDatasetsResource(AsyncAPIResource):
+ """Dataset management endpoints"""
+
@cached_property
def evaluate(self) -> AsyncEvaluateResource:
return AsyncEvaluateResource(self._client)
diff --git a/src/structify/resources/projects.py b/src/structify/resources/projects.py
index 658eadbd2..ddbd2488a 100644
--- a/src/structify/resources/projects.py
+++ b/src/structify/resources/projects.py
@@ -28,6 +28,8 @@
class ProjectsResource(SyncAPIResource):
+ """Project management endpoints"""
+
@cached_property
def with_raw_response(self) -> ProjectsResourceWithRawResponse:
"""
@@ -164,6 +166,8 @@ def get(
class AsyncProjectsResource(AsyncAPIResource):
+ """Project management endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncProjectsResourceWithRawResponse:
"""
diff --git a/src/structify/resources/sandbox.py b/src/structify/resources/sandbox.py
index 9a695dcb1..62b8ce497 100644
--- a/src/structify/resources/sandbox.py
+++ b/src/structify/resources/sandbox.py
@@ -26,6 +26,8 @@
class SandboxResource(SyncAPIResource):
+ """Sandbox management endpoints"""
+
@cached_property
def with_raw_response(self) -> SandboxResourceWithRawResponse:
"""
@@ -180,6 +182,8 @@ def update_status(
class AsyncSandboxResource(AsyncAPIResource):
+ """Sandbox management endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncSandboxResourceWithRawResponse:
"""
diff --git a/src/structify/resources/user/api_keys.py b/src/structify/resources/user/api_keys.py
index 6cb18071a..3f22ae0f3 100644
--- a/src/structify/resources/user/api_keys.py
+++ b/src/structify/resources/user/api_keys.py
@@ -27,6 +27,8 @@
class APIKeysResource(SyncAPIResource):
+ """All the accessible information about your account through our API"""
+
@cached_property
def with_raw_response(self) -> APIKeysResourceWithRawResponse:
"""
@@ -168,6 +170,8 @@ def revoke(
class AsyncAPIKeysResource(AsyncAPIResource):
+ """All the accessible information about your account through our API"""
+
@cached_property
def with_raw_response(self) -> AsyncAPIKeysResourceWithRawResponse:
"""
diff --git a/src/structify/resources/user/user.py b/src/structify/resources/user/user.py
index da9af3724..354969852 100644
--- a/src/structify/resources/user/user.py
+++ b/src/structify/resources/user/user.py
@@ -57,6 +57,7 @@ def stripe(self) -> StripeResource:
@cached_property
def api_keys(self) -> APIKeysResource:
+ """All the accessible information about your account through our API"""
return APIKeysResource(self._client)
@cached_property
@@ -303,6 +304,7 @@ def stripe(self) -> AsyncStripeResource:
@cached_property
def api_keys(self) -> AsyncAPIKeysResource:
+ """All the accessible information about your account through our API"""
return AsyncAPIKeysResource(self._client)
@cached_property
@@ -574,6 +576,7 @@ def stripe(self) -> StripeResourceWithRawResponse:
@cached_property
def api_keys(self) -> APIKeysResourceWithRawResponse:
+ """All the accessible information about your account through our API"""
return APIKeysResourceWithRawResponse(self._user.api_keys)
@@ -609,6 +612,7 @@ def stripe(self) -> AsyncStripeResourceWithRawResponse:
@cached_property
def api_keys(self) -> AsyncAPIKeysResourceWithRawResponse:
+ """All the accessible information about your account through our API"""
return AsyncAPIKeysResourceWithRawResponse(self._user.api_keys)
@@ -644,6 +648,7 @@ def stripe(self) -> StripeResourceWithStreamingResponse:
@cached_property
def api_keys(self) -> APIKeysResourceWithStreamingResponse:
+ """All the accessible information about your account through our API"""
return APIKeysResourceWithStreamingResponse(self._user.api_keys)
@@ -679,4 +684,5 @@ def stripe(self) -> AsyncStripeResourceWithStreamingResponse:
@cached_property
def api_keys(self) -> AsyncAPIKeysResourceWithStreamingResponse:
+ """All the accessible information about your account through our API"""
return AsyncAPIKeysResourceWithStreamingResponse(self._user.api_keys)
diff --git a/src/structify/resources/whitelabel.py b/src/structify/resources/whitelabel.py
index 541facb7e..fabecbb6b 100644
--- a/src/structify/resources/whitelabel.py
+++ b/src/structify/resources/whitelabel.py
@@ -20,6 +20,8 @@
class WhitelabelResource(SyncAPIResource):
+ """Whitelabeled service proxy endpoints"""
+
@cached_property
def with_raw_response(self) -> WhitelabelResourceWithRawResponse:
"""
@@ -145,6 +147,8 @@ def proxy_post(
class AsyncWhitelabelResource(AsyncAPIResource):
+ """Whitelabeled service proxy endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncWhitelabelResourceWithRawResponse:
"""
diff --git a/src/structify/resources/wiki.py b/src/structify/resources/wiki.py
index 3288974ea..915b0eb63 100644
--- a/src/structify/resources/wiki.py
+++ b/src/structify/resources/wiki.py
@@ -26,6 +26,8 @@
class WikiResource(SyncAPIResource):
+ """Team wiki page management endpoints"""
+
@cached_property
def with_raw_response(self) -> WikiResourceWithRawResponse:
"""
@@ -234,6 +236,8 @@ def get(
class AsyncWikiResource(AsyncAPIResource):
+ """Team wiki page management endpoints"""
+
@cached_property
def with_raw_response(self) -> AsyncWikiResourceWithRawResponse:
"""
From bb8b31f20614a17e816c2ba850429eb0ed71650e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 3 Mar 2026 16:48:34 +0000
Subject: [PATCH 044/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
api.md | 2 +-
src/structify/resources/chat.py | 9 +++++----
.../chat_copy_node_output_by_code_hash_response.py | 7 +++++--
tests/api_resources/test_chat.py | 13 +++++++------
5 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 73131ed61..6fc4980e3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 241
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-ed3509cffa5c7417ac7329a82bd077e0998bd56f68faed7fb386794ed25c98d6.yml
-openapi_spec_hash: b400292099898ff3aa3af5845f6c3c22
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-153cf17a03b6d5c9664a21dee1a644b76c0fa051e0e97cbd51419e00467ce62e.yml
+openapi_spec_hash: 423edf31c5c9aefc409a57d1d3eaced3
config_hash: ee4e855915a8e241bac39435061fb683
diff --git a/api.md b/api.md
index c162f29aa..4eedc2677 100644
--- a/api.md
+++ b/api.md
@@ -140,7 +140,7 @@ Methods:
- client.chat.add_git_commit(session_id, \*\*params) -> ChatAddGitCommitResponse
- client.chat.admin_issue_found(chat_id, \*\*params) -> AdminIssueFoundResponse
- client.chat.copy(\*\*params) -> ChatSessionWithMessages
-- client.chat.copy_node_output_by_code_hash(session_id, \*\*params) -> str
+- client.chat.copy_node_output_by_code_hash(session_id, \*\*params) -> ChatCopyNodeOutputByCodeHashResponse
- client.chat.create_session(\*\*params) -> CreateChatSessionResponse
- client.chat.delete_input_file(chat_id, \*\*params) -> ChatDeleteInputFileResponse
- client.chat.delete_session(session_id) -> DeleteChatSessionResponse
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 89b73b3e6..43b450e83 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -73,6 +73,7 @@
from ..types.chat_get_partial_chats_response import ChatGetPartialChatsResponse
from ..types.chat_upload_input_file_response import ChatUploadInputFileResponse
from ..types.chat_get_session_timeline_response import ChatGetSessionTimelineResponse
+from ..types.chat_copy_node_output_by_code_hash_response import ChatCopyNodeOutputByCodeHashResponse
__all__ = ["ChatResource", "AsyncChatResource"]
@@ -274,7 +275,7 @@ def copy_node_output_by_code_hash(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> str:
+ ) -> ChatCopyNodeOutputByCodeHashResponse:
"""
Args:
extra_headers: Send extra headers
@@ -299,7 +300,7 @@ def copy_node_output_by_code_hash(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=str,
+ cast_to=ChatCopyNodeOutputByCodeHashResponse,
)
def create_session(
@@ -1384,7 +1385,7 @@ async def copy_node_output_by_code_hash(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> str:
+ ) -> ChatCopyNodeOutputByCodeHashResponse:
"""
Args:
extra_headers: Send extra headers
@@ -1409,7 +1410,7 @@ async def copy_node_output_by_code_hash(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=str,
+ cast_to=ChatCopyNodeOutputByCodeHashResponse,
)
async def create_session(
diff --git a/src/structify/types/chat_copy_node_output_by_code_hash_response.py b/src/structify/types/chat_copy_node_output_by_code_hash_response.py
index ca05ae006..dde2da91d 100644
--- a/src/structify/types/chat_copy_node_output_by_code_hash_response.py
+++ b/src/structify/types/chat_copy_node_output_by_code_hash_response.py
@@ -1,8 +1,11 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import Optional
-from typing_extensions import TypeAlias
+
+from .._models import BaseModel
__all__ = ["ChatCopyNodeOutputByCodeHashResponse"]
-ChatCopyNodeOutputByCodeHashResponse: TypeAlias = Optional[str]
+
+class ChatCopyNodeOutputByCodeHashResponse(BaseModel):
+ cached_node_id: Optional[str] = None
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index b2e5a6069..1c4c8ef63 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -35,6 +35,7 @@
ChatGetPartialChatsResponse,
ChatUploadInputFileResponse,
ChatGetSessionTimelineResponse,
+ ChatCopyNodeOutputByCodeHashResponse,
)
from structify._utils import parse_datetime
from structify._response import (
@@ -239,7 +240,7 @@ def test_method_copy_node_output_by_code_hash(self, client: Structify) -> None:
code_md5_hash="code_md5_hash",
new_node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(str, chat, path=["response"])
+ assert_matches_type(ChatCopyNodeOutputByCodeHashResponse, chat, path=["response"])
@parametrize
def test_raw_response_copy_node_output_by_code_hash(self, client: Structify) -> None:
@@ -252,7 +253,7 @@ def test_raw_response_copy_node_output_by_code_hash(self, client: Structify) ->
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = response.parse()
- assert_matches_type(str, chat, path=["response"])
+ assert_matches_type(ChatCopyNodeOutputByCodeHashResponse, chat, path=["response"])
@parametrize
def test_streaming_response_copy_node_output_by_code_hash(self, client: Structify) -> None:
@@ -265,7 +266,7 @@ def test_streaming_response_copy_node_output_by_code_hash(self, client: Structif
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = response.parse()
- assert_matches_type(str, chat, path=["response"])
+ assert_matches_type(ChatCopyNodeOutputByCodeHashResponse, chat, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -1707,7 +1708,7 @@ async def test_method_copy_node_output_by_code_hash(self, async_client: AsyncStr
code_md5_hash="code_md5_hash",
new_node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(str, chat, path=["response"])
+ assert_matches_type(ChatCopyNodeOutputByCodeHashResponse, chat, path=["response"])
@parametrize
async def test_raw_response_copy_node_output_by_code_hash(self, async_client: AsyncStructify) -> None:
@@ -1720,7 +1721,7 @@ async def test_raw_response_copy_node_output_by_code_hash(self, async_client: As
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = await response.parse()
- assert_matches_type(str, chat, path=["response"])
+ assert_matches_type(ChatCopyNodeOutputByCodeHashResponse, chat, path=["response"])
@parametrize
async def test_streaming_response_copy_node_output_by_code_hash(self, async_client: AsyncStructify) -> None:
@@ -1733,7 +1734,7 @@ async def test_streaming_response_copy_node_output_by_code_hash(self, async_clie
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
chat = await response.parse()
- assert_matches_type(str, chat, path=["response"])
+ assert_matches_type(ChatCopyNodeOutputByCodeHashResponse, chat, path=["response"])
assert cast(Any, response.is_closed) is True
From 761ede84e233b966e824ac0aba9bc27b73567f48 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 3 Mar 2026 23:09:49 +0000
Subject: [PATCH 045/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/connector_with_secrets.py | 2 --
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6fc4980e3..6c007e2ee 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 241
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-153cf17a03b6d5c9664a21dee1a644b76c0fa051e0e97cbd51419e00467ce62e.yml
-openapi_spec_hash: 423edf31c5c9aefc409a57d1d3eaced3
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-94476871d49c14694a1d0eb1abcabaf272929a74cd0bd56860ad0a957d0cf222.yml
+openapi_spec_hash: ad8847ac0ea2f0f93066c116946d0a81
config_hash: ee4e855915a8e241bac39435061fb683
diff --git a/src/structify/types/connector_with_secrets.py b/src/structify/types/connector_with_secrets.py
index 6f471b74d..0e8a26b76 100644
--- a/src/structify/types/connector_with_secrets.py
+++ b/src/structify/types/connector_with_secrets.py
@@ -12,8 +12,6 @@
class ConnectorWithSecretsSecret(BaseModel):
"""Response model for listing secrets (without sensitive data)"""
- id: str
-
created_at: datetime
secret_name: str
From 59a57607f5c573af3639642bfaa20b8bd59f2f8d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 5 Mar 2026 04:37:08 +0000
Subject: [PATCH 046/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/admin/admin_teams_list_response.py | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6c007e2ee..b98f84c17 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 241
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-94476871d49c14694a1d0eb1abcabaf272929a74cd0bd56860ad0a957d0cf222.yml
-openapi_spec_hash: ad8847ac0ea2f0f93066c116946d0a81
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-8eb9c12514088e946ea2b96b6372f7f3c02364d31e0b8210492a4ebc90d0ea61.yml
+openapi_spec_hash: 5e1ece84342aa9889ea156ec903f1869
config_hash: ee4e855915a8e241bac39435061fb683
diff --git a/src/structify/types/admin/admin_teams_list_response.py b/src/structify/types/admin/admin_teams_list_response.py
index 9344a3feb..0f3b7e799 100644
--- a/src/structify/types/admin/admin_teams_list_response.py
+++ b/src/structify/types/admin/admin_teams_list_response.py
@@ -31,6 +31,8 @@ class AdminTeamsListResponseGrant(BaseModel):
starts_at: Optional[datetime] = None
+ stripe_event_id: Optional[str] = None
+
class AdminTeamsListResponseSubscription(BaseModel):
has_active_subscription: bool
From 1df1a867e1490126f24a42ad3c2e16cdc485e92d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 5 Mar 2026 16:22:12 +0000
Subject: [PATCH 047/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 3 +-
src/structify/resources/code.py | 96 ++++++++++++++++++-
src/structify/types/__init__.py | 1 +
.../types/code_apply_manual_edit_params.py | 13 +++
tests/api_resources/test_code.py | 92 ++++++++++++++++++
6 files changed, 207 insertions(+), 6 deletions(-)
create mode 100644 src/structify/types/code_apply_manual_edit_params.py
diff --git a/.stats.yml b/.stats.yml
index b98f84c17..18e0de29d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 241
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-8eb9c12514088e946ea2b96b6372f7f3c02364d31e0b8210492a4ebc90d0ea61.yml
-openapi_spec_hash: 5e1ece84342aa9889ea156ec903f1869
-config_hash: ee4e855915a8e241bac39435061fb683
+configured_endpoints: 242
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9767e9a62aa23e61595e75ac8128328fdd7057f0f16aa7e222becd227fac0f54.yml
+openapi_spec_hash: 513dd383f2bae692c0a031a15eabced3
+config_hash: 77240ce447403d9fd23dea191f796bdf
diff --git a/api.md b/api.md
index 4eedc2677..71298bc1a 100644
--- a/api.md
+++ b/api.md
@@ -930,11 +930,12 @@ Methods:
Types:
```python
-from structify.types import GenerateCodeRequest, InterruptGenerationRequest
+from structify.types import ApplyManualEditRequest, GenerateCodeRequest, InterruptGenerationRequest
```
Methods:
+- client.code.apply_manual_edit(chat_id, \*\*params) -> None
- client.code.generate_code(\*\*params) -> None
- client.code.interrupt_generation(\*\*params) -> None
diff --git a/src/structify/resources/code.py b/src/structify/resources/code.py
index 61b45f3e3..c3ad813b2 100644
--- a/src/structify/resources/code.py
+++ b/src/structify/resources/code.py
@@ -6,7 +6,7 @@
import httpx
-from ..types import code_generate_code_params, code_interrupt_generation_params
+from ..types import code_generate_code_params, code_apply_manual_edit_params, code_interrupt_generation_params
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
@@ -44,6 +44,47 @@ def with_streaming_response(self) -> CodeResourceWithStreamingResponse:
"""
return CodeResourceWithStreamingResponse(self)
+ def apply_manual_edit(
+ self,
+ chat_id: str,
+ *,
+ code: str,
+ filename: str,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return self._post(
+ f"/code/apply-manual-edit/{chat_id}",
+ body=maybe_transform(
+ {
+ "code": code,
+ "filename": filename,
+ },
+ code_apply_manual_edit_params.CodeApplyManualEditParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
def generate_code(
self,
*,
@@ -161,6 +202,47 @@ def with_streaming_response(self) -> AsyncCodeResourceWithStreamingResponse:
"""
return AsyncCodeResourceWithStreamingResponse(self)
+ async def apply_manual_edit(
+ self,
+ chat_id: str,
+ *,
+ code: str,
+ filename: str,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ return await self._post(
+ f"/code/apply-manual-edit/{chat_id}",
+ body=await async_maybe_transform(
+ {
+ "code": code,
+ "filename": filename,
+ },
+ code_apply_manual_edit_params.CodeApplyManualEditParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
async def generate_code(
self,
*,
@@ -260,6 +342,9 @@ class CodeResourceWithRawResponse:
def __init__(self, code: CodeResource) -> None:
self._code = code
+ self.apply_manual_edit = to_raw_response_wrapper(
+ code.apply_manual_edit,
+ )
self.generate_code = to_raw_response_wrapper(
code.generate_code,
)
@@ -272,6 +357,9 @@ class AsyncCodeResourceWithRawResponse:
def __init__(self, code: AsyncCodeResource) -> None:
self._code = code
+ self.apply_manual_edit = async_to_raw_response_wrapper(
+ code.apply_manual_edit,
+ )
self.generate_code = async_to_raw_response_wrapper(
code.generate_code,
)
@@ -284,6 +372,9 @@ class CodeResourceWithStreamingResponse:
def __init__(self, code: CodeResource) -> None:
self._code = code
+ self.apply_manual_edit = to_streamed_response_wrapper(
+ code.apply_manual_edit,
+ )
self.generate_code = to_streamed_response_wrapper(
code.generate_code,
)
@@ -296,6 +387,9 @@ class AsyncCodeResourceWithStreamingResponse:
def __init__(self, code: AsyncCodeResource) -> None:
self._code = code
+ self.apply_manual_edit = async_to_streamed_response_wrapper(
+ code.apply_manual_edit,
+ )
self.generate_code = async_to_streamed_response_wrapper(
code.generate_code,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 1d5c896aa..26e8339ad 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -254,6 +254,7 @@
from .chat_delete_input_file_params import ChatDeleteInputFileParams as ChatDeleteInputFileParams
from .chat_update_visibility_params import ChatUpdateVisibilityParams as ChatUpdateVisibilityParams
from .chat_upload_input_file_params import ChatUploadInputFileParams as ChatUploadInputFileParams
+from .code_apply_manual_edit_params import CodeApplyManualEditParams as CodeApplyManualEditParams
from .connector_catalog_list_params import ConnectorCatalogListParams as ConnectorCatalogListParams
from .connector_table_path_response import ConnectorTablePathResponse as ConnectorTablePathResponse
from .connector_update_table_params import ConnectorUpdateTableParams as ConnectorUpdateTableParams
diff --git a/src/structify/types/code_apply_manual_edit_params.py b/src/structify/types/code_apply_manual_edit_params.py
new file mode 100644
index 000000000..ba00c6880
--- /dev/null
+++ b/src/structify/types/code_apply_manual_edit_params.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["CodeApplyManualEditParams"]
+
+
+class CodeApplyManualEditParams(TypedDict, total=False):
+ code: Required[str]
+
+ filename: Required[str]
diff --git a/tests/api_resources/test_code.py b/tests/api_resources/test_code.py
index ae45f5a7d..ee3fd18c4 100644
--- a/tests/api_resources/test_code.py
+++ b/tests/api_resources/test_code.py
@@ -15,6 +15,52 @@
class TestCode:
parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"])
+ @parametrize
+ def test_method_apply_manual_edit(self, client: Structify) -> None:
+ code = client.code.apply_manual_edit(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ code="code",
+ filename="filename",
+ )
+ assert code is None
+
+ @parametrize
+ def test_raw_response_apply_manual_edit(self, client: Structify) -> None:
+ response = client.code.with_raw_response.apply_manual_edit(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ code="code",
+ filename="filename",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ code = response.parse()
+ assert code is None
+
+ @parametrize
+ def test_streaming_response_apply_manual_edit(self, client: Structify) -> None:
+ with client.code.with_streaming_response.apply_manual_edit(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ code="code",
+ filename="filename",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ code = response.parse()
+ assert code is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_apply_manual_edit(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.code.with_raw_response.apply_manual_edit(
+ chat_id="",
+ code="code",
+ filename="filename",
+ )
+
@parametrize
def test_method_generate_code(self, client: Structify) -> None:
code = client.code.generate_code(
@@ -107,6 +153,52 @@ class TestAsyncCode:
"async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"]
)
+ @parametrize
+ async def test_method_apply_manual_edit(self, async_client: AsyncStructify) -> None:
+ code = await async_client.code.apply_manual_edit(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ code="code",
+ filename="filename",
+ )
+ assert code is None
+
+ @parametrize
+ async def test_raw_response_apply_manual_edit(self, async_client: AsyncStructify) -> None:
+ response = await async_client.code.with_raw_response.apply_manual_edit(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ code="code",
+ filename="filename",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ code = await response.parse()
+ assert code is None
+
+ @parametrize
+ async def test_streaming_response_apply_manual_edit(self, async_client: AsyncStructify) -> None:
+ async with async_client.code.with_streaming_response.apply_manual_edit(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ code="code",
+ filename="filename",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ code = await response.parse()
+ assert code is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_apply_manual_edit(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.code.with_raw_response.apply_manual_edit(
+ chat_id="",
+ code="code",
+ filename="filename",
+ )
+
@parametrize
async def test_method_generate_code(self, async_client: AsyncStructify) -> None:
code = await async_client.code.generate_code(
From 95228adc1fd74e0ebec420fabceed3d133c2f7be Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 5 Mar 2026 20:34:42 +0000
Subject: [PATCH 048/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connector_catalog/admin.py | 8 ++++++++
.../connector_catalog/admin_create_catalog_params.py | 2 ++
.../connector_catalog/admin_update_catalog_params.py | 2 ++
.../types/connector_catalog/connector_catalog.py | 2 ++
tests/api_resources/connector_catalog/test_admin.py | 4 ++++
6 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 18e0de29d..9180bb246 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 242
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-9767e9a62aa23e61595e75ac8128328fdd7057f0f16aa7e222becd227fac0f54.yml
-openapi_spec_hash: 513dd383f2bae692c0a031a15eabced3
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-98072241c1921ecd7babcfe5b5764f001b286ba34fb724eab52b626f16be20fc.yml
+openapi_spec_hash: 3755452052630b531d441400c3d2b28a
config_hash: 77240ce447403d9fd23dea191f796bdf
diff --git a/src/structify/resources/connector_catalog/admin.py b/src/structify/resources/connector_catalog/admin.py
index 10177d246..a2e14c043 100644
--- a/src/structify/resources/connector_catalog/admin.py
+++ b/src/structify/resources/connector_catalog/admin.py
@@ -200,6 +200,7 @@ def create_catalog(
slug: str,
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
+ enterprise_only: bool | Omit = omit,
priority: Optional[int] | 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.
@@ -228,6 +229,7 @@ def create_catalog(
"slug": slug,
"categories": categories,
"description": description,
+ "enterprise_only": enterprise_only,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -537,6 +539,7 @@ def update_catalog(
*,
categories: Optional[SequenceNotStr[str]] | Omit = omit,
description: Optional[str] | Omit = omit,
+ enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
priority: Optional[int] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -566,6 +569,7 @@ def update_catalog(
{
"categories": categories,
"description": description,
+ "enterprise_only": enterprise_only,
"name": name,
"priority": priority,
},
@@ -858,6 +862,7 @@ async def create_catalog(
slug: str,
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
+ enterprise_only: bool | Omit = omit,
priority: Optional[int] | 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.
@@ -886,6 +891,7 @@ async def create_catalog(
"slug": slug,
"categories": categories,
"description": description,
+ "enterprise_only": enterprise_only,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -1195,6 +1201,7 @@ async def update_catalog(
*,
categories: Optional[SequenceNotStr[str]] | Omit = omit,
description: Optional[str] | Omit = omit,
+ enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
priority: Optional[int] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -1224,6 +1231,7 @@ async def update_catalog(
{
"categories": categories,
"description": description,
+ "enterprise_only": enterprise_only,
"name": name,
"priority": priority,
},
diff --git a/src/structify/types/connector_catalog/admin_create_catalog_params.py b/src/structify/types/connector_catalog/admin_create_catalog_params.py
index 3662fcbec..adfb768f8 100644
--- a/src/structify/types/connector_catalog/admin_create_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_create_catalog_params.py
@@ -19,4 +19,6 @@ class AdminCreateCatalogParams(TypedDict, total=False):
description: Optional[str]
+ enterprise_only: bool
+
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/admin_update_catalog_params.py b/src/structify/types/connector_catalog/admin_update_catalog_params.py
index 90f8b2286..784ae5ece 100644
--- a/src/structify/types/connector_catalog/admin_update_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_update_catalog_params.py
@@ -15,6 +15,8 @@ class AdminUpdateCatalogParams(TypedDict, total=False):
description: Optional[str]
+ enterprise_only: Optional[bool]
+
name: Optional[str]
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/connector_catalog.py b/src/structify/types/connector_catalog/connector_catalog.py
index c68249b73..c414d1f49 100644
--- a/src/structify/types/connector_catalog/connector_catalog.py
+++ b/src/structify/types/connector_catalog/connector_catalog.py
@@ -15,6 +15,8 @@ class ConnectorCatalog(BaseModel):
created_at: datetime
+ enterprise_only: bool
+
name: str
slug: str
diff --git a/tests/api_resources/connector_catalog/test_admin.py b/tests/api_resources/connector_catalog/test_admin.py
index a4a9898df..764d2d5ed 100644
--- a/tests/api_resources/connector_catalog/test_admin.py
+++ b/tests/api_resources/connector_catalog/test_admin.py
@@ -194,6 +194,7 @@ def test_method_create_catalog_with_all_params(self, client: Structify) -> None:
slug="slug",
categories=["string"],
description="description",
+ enterprise_only=True,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -558,6 +559,7 @@ def test_method_update_catalog_with_all_params(self, client: Structify) -> None:
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
categories=["string"],
description="description",
+ enterprise_only=True,
name="name",
priority=0,
)
@@ -912,6 +914,7 @@ async def test_method_create_catalog_with_all_params(self, async_client: AsyncSt
slug="slug",
categories=["string"],
description="description",
+ enterprise_only=True,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -1276,6 +1279,7 @@ async def test_method_update_catalog_with_all_params(self, async_client: AsyncSt
id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
categories=["string"],
description="description",
+ enterprise_only=True,
name="name",
priority=0,
)
From 3536c2cb1daa0eadb86d4966210d1a4bbe45c2c9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 5 Mar 2026 23:08:12 +0000
Subject: [PATCH 049/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/chat_event.py | 12 +++++++++++-
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 9180bb246..0a3be8d90 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 242
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-98072241c1921ecd7babcfe5b5764f001b286ba34fb724eab52b626f16be20fc.yml
-openapi_spec_hash: 3755452052630b531d441400c3d2b28a
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-14a1a749e54e0a620c90fcb4ffecd8e496b07ea0b6dbd6e7d09de7417531efca.yml
+openapi_spec_hash: 497659ebfdc55fc406827985af7a1d44
config_hash: 77240ce447403d9fd23dea191f796bdf
diff --git a/src/structify/types/chat_event.py b/src/structify/types/chat_event.py
index 5d4504056..297959dd8 100644
--- a/src/structify/types/chat_event.py
+++ b/src/structify/types/chat_event.py
@@ -1,7 +1,7 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
from typing import List, Union, Optional
-from typing_extensions import TypeAlias
+from typing_extensions import Literal, TypeAlias
from pydantic import Field as FieldInfo
@@ -147,6 +147,16 @@ class Question(BaseModel):
class InternalErrorInternalError(BaseModel):
message: str
+ error_kind: Optional[Literal["unknown", "context_limit", "rate_limited", "timeout", "connection_error"]] = None
+ """
+ Categorizes the kind of internal error that occurred during LLM generation. This
+ allows the frontend to render appropriate error messages without regex matching.
+
+ Classification logic lives in `LlmError::kind()` (in the inference crate) so
+ that errors are categorized at the source. This enum is the serializable
+ representation used in ChatEvent / proto / OpenAPI.
+ """
+
class InternalError(BaseModel):
internal_error: InternalErrorInternalError = FieldInfo(alias="InternalError")
From 1563f48901ebd6545e8eb594370b12019fb47a30 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 6 Mar 2026 13:06:14 +0000
Subject: [PATCH 050/105] chore(test): do not count install time for mock
server timeout
---
scripts/mock | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/scripts/mock b/scripts/mock
index 0b28f6ea2..bcf3b392b 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -21,11 +21,22 @@ echo "==> Starting mock server with URL ${URL}"
# Run prism mock on the given spec
if [ "$1" == "--daemon" ]; then
+ # Pre-install the package so the download doesn't eat into the startup timeout
+ npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version
+
npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log &
- # Wait for server to come online
+ # Wait for server to come online (max 30s)
echo -n "Waiting for server"
+ attempts=0
while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do
+ attempts=$((attempts + 1))
+ if [ "$attempts" -ge 300 ]; then
+ echo
+ echo "Timed out waiting for Prism server to start"
+ cat .prism.log
+ exit 1
+ fi
echo -n "."
sleep 0.1
done
From 4148cb4b20cbe6cf0ca8371d0d4c602a80f5a764 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 6 Mar 2026 19:49:02 +0000
Subject: [PATCH 051/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/sessions.py | 24 +++++++++++++++++++
.../session_upload_node_output_data_params.py | 12 ++++++++++
src/structify/types/workflow_session_node.py | 12 ++++++++++
tests/api_resources/test_sessions.py | 12 ++++++++++
5 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 0a3be8d90..c1d4beebf 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 242
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-14a1a749e54e0a620c90fcb4ffecd8e496b07ea0b6dbd6e7d09de7417531efca.yml
-openapi_spec_hash: 497659ebfdc55fc406827985af7a1d44
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-157a11f78a8e41691e4ecc1b81e5c2b3f0b3b083cd4a633ee3b013afb78a06db.yml
+openapi_spec_hash: 41db8193b41627a7db7d266b5d8d22dd
config_hash: 77240ce447403d9fd23dea191f796bdf
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 38180878e..2d8697f05 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -691,6 +691,12 @@ def upload_node_output_data(
node_id: str,
*,
content: FileTypes,
+ cache_final_rows: Optional[int] | Omit = omit,
+ cache_final_size_bytes: Optional[int] | Omit = omit,
+ cache_max_bytes: Optional[int] | Omit = omit,
+ cache_original_rows: Optional[int] | Omit = omit,
+ cache_original_size_bytes: Optional[int] | Omit = omit,
+ cache_truncated: Optional[bool] | Omit = omit,
output_schema: 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.
@@ -714,6 +720,12 @@ def upload_node_output_data(
body = deepcopy_minimal(
{
"content": content,
+ "cache_final_rows": cache_final_rows,
+ "cache_final_size_bytes": cache_final_size_bytes,
+ "cache_max_bytes": cache_max_bytes,
+ "cache_original_rows": cache_original_rows,
+ "cache_original_size_bytes": cache_original_size_bytes,
+ "cache_truncated": cache_truncated,
"output_schema": output_schema,
}
)
@@ -1401,6 +1413,12 @@ async def upload_node_output_data(
node_id: str,
*,
content: FileTypes,
+ cache_final_rows: Optional[int] | Omit = omit,
+ cache_final_size_bytes: Optional[int] | Omit = omit,
+ cache_max_bytes: Optional[int] | Omit = omit,
+ cache_original_rows: Optional[int] | Omit = omit,
+ cache_original_size_bytes: Optional[int] | Omit = omit,
+ cache_truncated: Optional[bool] | Omit = omit,
output_schema: 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.
@@ -1424,6 +1442,12 @@ async def upload_node_output_data(
body = deepcopy_minimal(
{
"content": content,
+ "cache_final_rows": cache_final_rows,
+ "cache_final_size_bytes": cache_final_size_bytes,
+ "cache_max_bytes": cache_max_bytes,
+ "cache_original_rows": cache_original_rows,
+ "cache_original_size_bytes": cache_original_size_bytes,
+ "cache_truncated": cache_truncated,
"output_schema": output_schema,
}
)
diff --git a/src/structify/types/session_upload_node_output_data_params.py b/src/structify/types/session_upload_node_output_data_params.py
index 35ee81397..dcc0b284c 100644
--- a/src/structify/types/session_upload_node_output_data_params.py
+++ b/src/structify/types/session_upload_node_output_data_params.py
@@ -13,4 +13,16 @@
class SessionUploadNodeOutputDataParams(TypedDict, total=False):
content: Required[FileTypes]
+ cache_final_rows: Optional[int]
+
+ cache_final_size_bytes: Optional[int]
+
+ cache_max_bytes: Optional[int]
+
+ cache_original_rows: Optional[int]
+
+ cache_original_size_bytes: Optional[int]
+
+ cache_truncated: Optional[bool]
+
output_schema: Optional[str]
diff --git a/src/structify/types/workflow_session_node.py b/src/structify/types/workflow_session_node.py
index a790119d5..0f93d2b48 100644
--- a/src/structify/types/workflow_session_node.py
+++ b/src/structify/types/workflow_session_node.py
@@ -30,6 +30,18 @@ class WorkflowSessionNode(BaseModel):
updated_at: datetime
+ cache_final_rows: Optional[int] = None
+
+ cache_final_size_bytes: Optional[int] = None
+
+ cache_max_bytes: Optional[int] = None
+
+ cache_original_rows: Optional[int] = None
+
+ cache_original_size_bytes: Optional[int] = None
+
+ cache_truncated: Optional[bool] = None
+
code: Optional[str] = None
confirmation_status: Optional[str] = None
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 17189af95..ec5542a58 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -998,6 +998,12 @@ def test_method_upload_node_output_data_with_all_params(self, client: Structify)
session = client.sessions.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
content=b"raw file contents",
+ cache_final_rows=0,
+ cache_final_size_bytes=0,
+ cache_max_bytes=0,
+ cache_original_rows=0,
+ cache_original_size_bytes=0,
+ cache_truncated=True,
output_schema="output_schema",
)
assert_matches_type(WorkflowSessionNode, session, path=["response"])
@@ -2050,6 +2056,12 @@ async def test_method_upload_node_output_data_with_all_params(self, async_client
session = await async_client.sessions.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
content=b"raw file contents",
+ cache_final_rows=0,
+ cache_final_size_bytes=0,
+ cache_max_bytes=0,
+ cache_original_rows=0,
+ cache_original_size_bytes=0,
+ cache_truncated=True,
output_schema="output_schema",
)
assert_matches_type(WorkflowSessionNode, session, path=["response"])
From c4ccd37bdf1803dfceb77762fb2c50a960ec4e27 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 7 Mar 2026 01:42:49 +0000
Subject: [PATCH 052/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 18 +
src/structify/resources/chat.py | 98 +++++
src/structify/resources/sessions.py | 100 ++++-
src/structify/types/__init__.py | 31 ++
.../types/chat_list_dashboards_params.py | 13 +
src/structify/types/dashboard_item.py | 13 +
src/structify/types/dashboard_spec.py | 26 ++
src/structify/types/dashboard_spec_param.py | 28 ++
.../types/list_dashboards_response.py | 16 +
.../session_upload_dashboard_layout_params.py | 21 +-
.../upload_dashboard_layout_request_param.py | 32 ++
src/structify/types/viz_boolean_control.py | 12 +
.../types/viz_boolean_control_param.py | 15 +
.../types/viz_boolean_control_type.py | 7 +
src/structify/types/viz_control_option.py | 11 +
.../types/viz_control_option_param.py | 13 +
src/structify/types/viz_date_control.py | 12 +
src/structify/types/viz_date_control_param.py | 15 +
src/structify/types/viz_date_control_type.py | 7 +
src/structify/types/viz_figure.py | 20 +
src/structify/types/viz_figure_definition.py | 12 +
.../types/viz_figure_definition_param.py | 15 +
src/structify/types/viz_figure_kind.py | 7 +
src/structify/types/viz_figure_param.py | 21 ++
src/structify/types/viz_number_control.py | 20 +
.../types/viz_number_control_param.py | 21 ++
.../types/viz_number_control_type.py | 7 +
src/structify/types/viz_param.py | 48 +++
src/structify/types/viz_param_param.py | 48 +++
src/structify/types/viz_query.py | 11 +
src/structify/types/viz_query_param.py | 13 +
src/structify/types/viz_string_control.py | 17 +
.../types/viz_string_control_param.py | 19 +
.../types/viz_string_control_type.py | 7 +
tests/api_resources/test_chat.py | 93 +++++
tests/api_resources/test_sessions.py | 354 +++++++++++++++++-
37 files changed, 1208 insertions(+), 21 deletions(-)
create mode 100644 src/structify/types/chat_list_dashboards_params.py
create mode 100644 src/structify/types/dashboard_item.py
create mode 100644 src/structify/types/dashboard_spec.py
create mode 100644 src/structify/types/dashboard_spec_param.py
create mode 100644 src/structify/types/list_dashboards_response.py
create mode 100644 src/structify/types/upload_dashboard_layout_request_param.py
create mode 100644 src/structify/types/viz_boolean_control.py
create mode 100644 src/structify/types/viz_boolean_control_param.py
create mode 100644 src/structify/types/viz_boolean_control_type.py
create mode 100644 src/structify/types/viz_control_option.py
create mode 100644 src/structify/types/viz_control_option_param.py
create mode 100644 src/structify/types/viz_date_control.py
create mode 100644 src/structify/types/viz_date_control_param.py
create mode 100644 src/structify/types/viz_date_control_type.py
create mode 100644 src/structify/types/viz_figure.py
create mode 100644 src/structify/types/viz_figure_definition.py
create mode 100644 src/structify/types/viz_figure_definition_param.py
create mode 100644 src/structify/types/viz_figure_kind.py
create mode 100644 src/structify/types/viz_figure_param.py
create mode 100644 src/structify/types/viz_number_control.py
create mode 100644 src/structify/types/viz_number_control_param.py
create mode 100644 src/structify/types/viz_number_control_type.py
create mode 100644 src/structify/types/viz_param.py
create mode 100644 src/structify/types/viz_param_param.py
create mode 100644 src/structify/types/viz_query.py
create mode 100644 src/structify/types/viz_query_param.py
create mode 100644 src/structify/types/viz_string_control.py
create mode 100644 src/structify/types/viz_string_control_param.py
create mode 100644 src/structify/types/viz_string_control_type.py
diff --git a/.stats.yml b/.stats.yml
index c1d4beebf..36d25337c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 242
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-157a11f78a8e41691e4ecc1b81e5c2b3f0b3b083cd4a633ee3b013afb78a06db.yml
-openapi_spec_hash: 41db8193b41627a7db7d266b5d8d22dd
-config_hash: 77240ce447403d9fd23dea191f796bdf
+configured_endpoints: 243
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-5eb7f5d41cc9870f690042a3450fac21134c487fde82bf87bf6691157a337d5c.yml
+openapi_spec_hash: bc853c7c7ffc2f6df3aabd883308df61
+config_hash: a9e2da657c35219124ded3c60964a7b0
diff --git a/api.md b/api.md
index 71298bc1a..e9fd3744e 100644
--- a/api.md
+++ b/api.md
@@ -103,6 +103,7 @@ from structify.types import (
CopyChatSessionRequest,
CreateChatSessionRequest,
CreateChatSessionResponse,
+ DashboardItem,
DeleteChatSessionResponse,
ErrorResponse,
GetChatSessionResponse,
@@ -110,6 +111,7 @@ from structify.types import (
GrantAdminAccessRequest,
ListChatSessionsResponse,
ListCollaboratorsResponse,
+ ListDashboardsResponse,
Message,
SimulatePromptRequest,
SimulatePromptResponse,
@@ -151,6 +153,7 @@ Methods:
- client.chat.get_session_timeline(session_id) -> ChatGetSessionTimelineResponse
- client.chat.grant_admin_override(chat_id, \*\*params) -> AdminGrantAccessResponse
- client.chat.list_collaborators(chat_id) -> ListCollaboratorsResponse
+- client.chat.list_dashboards(chat_id, \*\*params) -> ListDashboardsResponse
- client.chat.list_input_files(chat_id) -> ChatListInputFilesResponse
- client.chat.list_sessions(\*\*params) -> ListChatSessionsResponse
- client.chat.list_templates() -> ChatListTemplatesResponse
@@ -570,6 +573,7 @@ from structify.types import (
Dashboard,
DashboardComponent,
DashboardPage,
+ DashboardSpec,
EdgeSpec,
EditNodeOutputRequest,
FinalizeDagRequest,
@@ -585,6 +589,20 @@ from structify.types import (
UpdateWorkflowNodeRequest,
UploadDashboardLayoutRequest,
UploadNodeVisualizationOutputRequest,
+ VizBooleanControl,
+ VizBooleanControlType,
+ VizControlOption,
+ VizDateControl,
+ VizDateControlType,
+ VizFigure,
+ VizFigureDefinition,
+ VizFigureKind,
+ VizNumberControl,
+ VizNumberControlType,
+ VizParam,
+ VizQuery,
+ VizStringControl,
+ VizStringControlType,
WorkflowDag,
WorkflowNodeExecutionStatus,
WorkflowNodeLog,
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 43b450e83..4b32bf576 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -16,6 +16,7 @@
chat_add_git_commit_params,
chat_create_session_params,
chat_update_session_params,
+ chat_list_dashboards_params,
chat_simulate_prompt_params,
chat_add_collaborator_params,
chat_load_input_files_params,
@@ -52,6 +53,7 @@
from ..types.chat_prompt_param import ChatPromptParam
from ..types.chat_session_role import ChatSessionRole
from ..types.chat_load_files_response import ChatLoadFilesResponse
+from ..types.list_dashboards_response import ListDashboardsResponse
from ..types.simulate_prompt_response import SimulatePromptResponse
from ..types.get_chat_session_response import GetChatSessionResponse
from ..types.get_dependencies_response import GetDependenciesResponse
@@ -661,6 +663,48 @@ def list_collaborators(
cast_to=ListCollaboratorsResponse,
)
+ def list_dashboards(
+ self,
+ chat_id: str,
+ *,
+ commit_hash: 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,
+ ) -> ListDashboardsResponse:
+ """
+ List dashboard specs for a chat session at a specific commit hash.
+
+ Args:
+ commit_hash: Optional commit hash. If omitted, uses the chat session latest commit.
+
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ return self._get(
+ f"/chat/sessions/{chat_id}/dashboards",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"commit_hash": commit_hash}, chat_list_dashboards_params.ChatListDashboardsParams
+ ),
+ ),
+ cast_to=ListDashboardsResponse,
+ )
+
def list_input_files(
self,
chat_id: str,
@@ -1773,6 +1817,48 @@ async def list_collaborators(
cast_to=ListCollaboratorsResponse,
)
+ async def list_dashboards(
+ self,
+ chat_id: str,
+ *,
+ commit_hash: 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,
+ ) -> ListDashboardsResponse:
+ """
+ List dashboard specs for a chat session at a specific commit hash.
+
+ Args:
+ commit_hash: Optional commit hash. If omitted, uses the chat session latest commit.
+
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ return await self._get(
+ f"/chat/sessions/{chat_id}/dashboards",
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"commit_hash": commit_hash}, chat_list_dashboards_params.ChatListDashboardsParams
+ ),
+ ),
+ cast_to=ListDashboardsResponse,
+ )
+
async def list_input_files(
self,
chat_id: str,
@@ -2355,6 +2441,9 @@ def __init__(self, chat: ChatResource) -> None:
self.list_collaborators = to_raw_response_wrapper(
chat.list_collaborators,
)
+ self.list_dashboards = to_raw_response_wrapper(
+ chat.list_dashboards,
+ )
self.list_input_files = to_raw_response_wrapper(
chat.list_input_files,
)
@@ -2449,6 +2538,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.list_collaborators = async_to_raw_response_wrapper(
chat.list_collaborators,
)
+ self.list_dashboards = async_to_raw_response_wrapper(
+ chat.list_dashboards,
+ )
self.list_input_files = async_to_raw_response_wrapper(
chat.list_input_files,
)
@@ -2543,6 +2635,9 @@ def __init__(self, chat: ChatResource) -> None:
self.list_collaborators = to_streamed_response_wrapper(
chat.list_collaborators,
)
+ self.list_dashboards = to_streamed_response_wrapper(
+ chat.list_dashboards,
+ )
self.list_input_files = to_streamed_response_wrapper(
chat.list_input_files,
)
@@ -2637,6 +2732,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.list_collaborators = async_to_streamed_response_wrapper(
chat.list_collaborators,
)
+ self.list_dashboards = async_to_streamed_response_wrapper(
+ chat.list_dashboards,
+ )
self.list_input_files = async_to_streamed_response_wrapper(
chat.list_input_files,
)
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 2d8697f05..8ac4a64a4 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Dict, Mapping, Iterable, Optional, cast
-from typing_extensions import Literal
+from typing_extensions import Literal, overload
import httpx
@@ -25,7 +25,7 @@
session_upload_node_visualization_output_params,
)
from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -648,6 +648,7 @@ def update_node_progress(
cast_to=WorkflowSessionNode,
)
+ @overload
def upload_dashboard_layout(
self,
session_id: str,
@@ -673,12 +674,57 @@ def upload_dashboard_layout(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ ...
+
+ @overload
+ def upload_dashboard_layout(
+ self,
+ session_id: str,
+ *,
+ dashboard_specs: Iterable[session_upload_dashboard_layout_params.Variant1DashboardSpec],
+ # 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,
+ ) -> WorkflowSession:
+ """
+ Args:
+ 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
+ """
+ ...
+
+ @required_args(["layout"], ["dashboard_specs"])
+ def upload_dashboard_layout(
+ self,
+ session_id: str,
+ *,
+ layout: DashboardParam | Omit = omit,
+ dashboard_specs: Iterable[session_upload_dashboard_layout_params.Variant1DashboardSpec] | 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,
+ ) -> WorkflowSession:
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
f"/sessions/{session_id}/dashboard_layout",
body=maybe_transform(
- {"layout": layout}, session_upload_dashboard_layout_params.SessionUploadDashboardLayoutParams
+ {
+ "layout": layout,
+ "dashboard_specs": dashboard_specs,
+ },
+ session_upload_dashboard_layout_params.SessionUploadDashboardLayoutParams,
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -1370,6 +1416,7 @@ async def update_node_progress(
cast_to=WorkflowSessionNode,
)
+ @overload
async def upload_dashboard_layout(
self,
session_id: str,
@@ -1395,12 +1442,57 @@ async def upload_dashboard_layout(
timeout: Override the client-level default timeout for this request, in seconds
"""
+ ...
+
+ @overload
+ async def upload_dashboard_layout(
+ self,
+ session_id: str,
+ *,
+ dashboard_specs: Iterable[session_upload_dashboard_layout_params.Variant1DashboardSpec],
+ # 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,
+ ) -> WorkflowSession:
+ """
+ Args:
+ 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
+ """
+ ...
+
+ @required_args(["layout"], ["dashboard_specs"])
+ async def upload_dashboard_layout(
+ self,
+ session_id: str,
+ *,
+ layout: DashboardParam | Omit = omit,
+ dashboard_specs: Iterable[session_upload_dashboard_layout_params.Variant1DashboardSpec] | 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,
+ ) -> WorkflowSession:
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
f"/sessions/{session_id}/dashboard_layout",
body=await async_maybe_transform(
- {"layout": layout}, session_upload_dashboard_layout_params.SessionUploadDashboardLayoutParams
+ {
+ "layout": layout,
+ "dashboard_specs": dashboard_specs,
+ },
+ session_upload_dashboard_layout_params.SessionUploadDashboardLayoutParams,
),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 26e8339ad..23bbee3b1 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -15,8 +15,11 @@
from .dashboard import Dashboard as Dashboard
from .team_role import TeamRole as TeamRole
from .user_info import UserInfo as UserInfo
+from .viz_param import VizParam as VizParam
+from .viz_query import VizQuery as VizQuery
from .wiki_page import WikiPage as WikiPage
from .chat_event import ChatEvent as ChatEvent
+from .viz_figure import VizFigure as VizFigure
from .chat_prompt import ChatPrompt as ChatPrompt
from .granularity import Granularity as Granularity
from .table_param import TableParam as TableParam
@@ -32,7 +35,9 @@
from .message_param import MessageParam as MessageParam
from .property_type import PropertyType as PropertyType
from .tool_metadata import ToolMetadata as ToolMetadata
+from .dashboard_item import DashboardItem as DashboardItem
from .dashboard_page import DashboardPage as DashboardPage
+from .dashboard_spec import DashboardSpec as DashboardSpec
from .job_event_body import JobEventBody as JobEventBody
from .project_member import ProjectMember as ProjectMember
from .strategy_param import StrategyParam as StrategyParam
@@ -50,9 +55,14 @@
from .node_spec_param import NodeSpecParam as NodeSpecParam
from .tool_invocation import ToolInvocation as ToolInvocation
from .usage_group_key import UsageGroupKey as UsageGroupKey
+from .viz_figure_kind import VizFigureKind as VizFigureKind
+from .viz_param_param import VizParamParam as VizParamParam
+from .viz_query_param import VizQueryParam as VizQueryParam
from .chat_copy_params import ChatCopyParams as ChatCopyParams
from .job_get_response import JobGetResponse as JobGetResponse
from .save_requirement import SaveRequirement as SaveRequirement
+from .viz_date_control import VizDateControl as VizDateControl
+from .viz_figure_param import VizFigureParam as VizFigureParam
from .workflow_session import WorkflowSession as WorkflowSession
from .chat_prompt_param import ChatPromptParam as ChatPromptParam
from .chat_session_role import ChatSessionRole as ChatSessionRole
@@ -84,6 +94,9 @@
from .team_update_params import TeamUpdateParams as TeamUpdateParams
from .user_enrich_params import UserEnrichParams as UserEnrichParams
from .user_update_params import UserUpdateParams as UserUpdateParams
+from .viz_control_option import VizControlOption as VizControlOption
+from .viz_number_control import VizNumberControl as VizNumberControl
+from .viz_string_control import VizStringControl as VizStringControl
from .wiki_create_params import WikiCreateParams as WikiCreateParams
from .wiki_list_response import WikiListResponse as WikiListResponse
from .wiki_update_params import WikiUpdateParams as WikiUpdateParams
@@ -100,10 +113,12 @@
from .tool_metadata_param import ToolMetadataParam as ToolMetadataParam
from .user_refresh_params import UserRefreshParams as UserRefreshParams
from .user_usage_response import UserUsageResponse as UserUsageResponse
+from .viz_boolean_control import VizBooleanControl as VizBooleanControl
from .workflow_run_params import WorkflowRunParams as WorkflowRunParams
from .connector_table_info import ConnectorTableInfo as ConnectorTableInfo
from .create_team_response import CreateTeamResponse as CreateTeamResponse
from .dashboard_page_param import DashboardPageParam as DashboardPageParam
+from .dashboard_spec_param import DashboardSpecParam as DashboardSpecParam
from .dataset_get_response import DatasetGetResponse as DatasetGetResponse
from .dataset_match_params import DatasetMatchParams as DatasetMatchParams
from .document_list_params import DocumentListParams as DocumentListParams
@@ -135,6 +150,8 @@
from .project_update_params import ProjectUpdateParams as ProjectUpdateParams
from .sandbox_list_response import SandboxListResponse as SandboxListResponse
from .update_table_response import UpdateTableResponse as UpdateTableResponse
+from .viz_date_control_type import VizDateControlType as VizDateControlType
+from .viz_figure_definition import VizFigureDefinition as VizFigureDefinition
from .workflow_session_edge import WorkflowSessionEdge as WorkflowSessionEdge
from .workflow_session_node import WorkflowSessionNode as WorkflowSessionNode
from .chat_load_files_params import ChatLoadFilesParams as ChatLoadFilesParams
@@ -157,6 +174,7 @@
from .scrape_scrape_response import ScrapeScrapeResponse as ScrapeScrapeResponse
from .structure_pdf_response import StructurePdfResponse as StructurePdfResponse
from .team_add_member_params import TeamAddMemberParams as TeamAddMemberParams
+from .viz_date_control_param import VizDateControlParam as VizDateControlParam
from .workflow_schedule_info import WorkflowScheduleInfo as WorkflowScheduleInfo
from .connector_create_params import ConnectorCreateParams as ConnectorCreateParams
from .connector_explorer_chat import ConnectorExplorerChat as ConnectorExplorerChat
@@ -169,6 +187,8 @@
from .entity_summarize_params import EntitySummarizeParams as EntitySummarizeParams
from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
+from .viz_number_control_type import VizNumberControlType as VizNumberControlType
+from .viz_string_control_type import VizStringControlType as VizStringControlType
from .chat_load_files_response import ChatLoadFilesResponse as ChatLoadFilesResponse
from .connector_explore_params import ConnectorExploreParams as ConnectorExploreParams
from .connector_store_response import ConnectorStoreResponse as ConnectorStoreResponse
@@ -176,11 +196,16 @@
from .document_download_params import DocumentDownloadParams as DocumentDownloadParams
from .entity_derive_all_params import EntityDeriveAllParams as EntityDeriveAllParams
from .entity_get_merges_params import EntityGetMergesParams as EntityGetMergesParams
+from .list_dashboards_response import ListDashboardsResponse as ListDashboardsResponse
from .match_create_jobs_params import MatchCreateJobsParams as MatchCreateJobsParams
from .refresh_session_response import RefreshSessionResponse as RefreshSessionResponse
from .session_kill_jobs_params import SessionKillJobsParams as SessionKillJobsParams
from .simulate_prompt_response import SimulatePromptResponse as SimulatePromptResponse
from .team_subscription_status import TeamSubscriptionStatus as TeamSubscriptionStatus
+from .viz_boolean_control_type import VizBooleanControlType as VizBooleanControlType
+from .viz_control_option_param import VizControlOptionParam as VizControlOptionParam
+from .viz_number_control_param import VizNumberControlParam as VizNumberControlParam
+from .viz_string_control_param import VizStringControlParam as VizStringControlParam
from .wiki_connector_reference import WikiConnectorReference as WikiConnectorReference
from .chat_list_sessions_params import ChatListSessionsParams as ChatListSessionsParams
from .code_generate_code_params import CodeGenerateCodeParams as CodeGenerateCodeParams
@@ -197,6 +222,7 @@
from .slack_event_payload_param import SlackEventPayloadParam as SlackEventPayloadParam
from .team_credits_usage_params import TeamCreditsUsageParams as TeamCreditsUsageParams
from .user_survey_submit_params import UserSurveySubmitParams as UserSurveySubmitParams
+from .viz_boolean_control_param import VizBooleanControlParam as VizBooleanControlParam
from .wiki_page_with_references import WikiPageWithReferences as WikiPageWithReferences
from .accept_invitation_response import AcceptInvitationResponse as AcceptInvitationResponse
from .admin_issue_found_response import AdminIssueFoundResponse as AdminIssueFoundResponse
@@ -218,6 +244,7 @@
from .update_visibility_response import UpdateVisibilityResponse as UpdateVisibilityResponse
from .user_transactions_response import UserTransactionsResponse as UserTransactionsResponse
from .admin_grant_access_response import AdminGrantAccessResponse as AdminGrantAccessResponse
+from .chat_list_dashboards_params import ChatListDashboardsParams as ChatListDashboardsParams
from .chat_simulate_prompt_params import ChatSimulatePromptParams as ChatSimulatePromptParams
from .dataset_add_property_params import DatasetAddPropertyParams as DatasetAddPropertyParams
from .dataset_view_table_response import DatasetViewTableResponse as DatasetViewTableResponse
@@ -234,6 +261,7 @@
from .source_delete_entity_params import SourceDeleteEntityParams as SourceDeleteEntityParams
from .structure_job_status_params import StructureJobStatusParams as StructureJobStatusParams
from .update_member_role_response import UpdateMemberRoleResponse as UpdateMemberRoleResponse
+from .viz_figure_definition_param import VizFigureDefinitionParam as VizFigureDefinitionParam
from .admin_report_critical_params import AdminReportCriticalParams as AdminReportCriticalParams
from .chat_add_collaborator_params import ChatAddCollaboratorParams as ChatAddCollaboratorParams
from .chat_add_git_commit_response import ChatAddGitCommitResponse as ChatAddGitCommitResponse
@@ -337,6 +365,9 @@
from .structure_enhance_relationship_params import (
StructureEnhanceRelationshipParams as StructureEnhanceRelationshipParams,
)
+from .upload_dashboard_layout_request_param import (
+ UploadDashboardLayoutRequestParam as UploadDashboardLayoutRequestParam,
+)
from .workflow_schedule_get_sessions_params import (
WorkflowScheduleGetSessionsParams as WorkflowScheduleGetSessionsParams,
)
diff --git a/src/structify/types/chat_list_dashboards_params.py b/src/structify/types/chat_list_dashboards_params.py
new file mode 100644
index 000000000..bb0dadd3e
--- /dev/null
+++ b/src/structify/types/chat_list_dashboards_params.py
@@ -0,0 +1,13 @@
+# 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__ = ["ChatListDashboardsParams"]
+
+
+class ChatListDashboardsParams(TypedDict, total=False):
+ commit_hash: Optional[str]
+ """Optional commit hash. If omitted, uses the chat session latest commit."""
diff --git a/src/structify/types/dashboard_item.py b/src/structify/types/dashboard_item.py
new file mode 100644
index 000000000..586b4755c
--- /dev/null
+++ b/src/structify/types/dashboard_item.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .dashboard_spec import DashboardSpec
+
+__all__ = ["DashboardItem"]
+
+
+class DashboardItem(BaseModel):
+ file_name: str
+ """File path relative to repository root."""
+
+ spec: DashboardSpec
diff --git a/src/structify/types/dashboard_spec.py b/src/structify/types/dashboard_spec.py
new file mode 100644
index 000000000..5bc8dbc38
--- /dev/null
+++ b/src/structify/types/dashboard_spec.py
@@ -0,0 +1,26 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict, List
+
+from .._models import BaseModel
+from .viz_param import VizParam
+from .viz_query import VizQuery
+from .viz_figure import VizFigure
+
+__all__ = ["DashboardSpec"]
+
+
+class DashboardSpec(BaseModel):
+ dataset: str
+
+ description: str
+
+ figures: List[VizFigure]
+
+ params: Dict[str, VizParam]
+
+ queries: List[VizQuery]
+
+ title: str
+
+ version: str
diff --git a/src/structify/types/dashboard_spec_param.py b/src/structify/types/dashboard_spec_param.py
new file mode 100644
index 000000000..baa9907f6
--- /dev/null
+++ b/src/structify/types/dashboard_spec_param.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict, Iterable
+from typing_extensions import Required, TypedDict
+
+from .viz_param_param import VizParamParam
+from .viz_query_param import VizQueryParam
+from .viz_figure_param import VizFigureParam
+
+__all__ = ["DashboardSpecParam"]
+
+
+class DashboardSpecParam(TypedDict, total=False):
+ dataset: Required[str]
+
+ description: Required[str]
+
+ figures: Required[Iterable[VizFigureParam]]
+
+ params: Required[Dict[str, VizParamParam]]
+
+ queries: Required[Iterable[VizQueryParam]]
+
+ title: Required[str]
+
+ version: Required[str]
diff --git a/src/structify/types/list_dashboards_response.py b/src/structify/types/list_dashboards_response.py
new file mode 100644
index 000000000..b25e00c74
--- /dev/null
+++ b/src/structify/types/list_dashboards_response.py
@@ -0,0 +1,16 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .dashboard_item import DashboardItem
+
+__all__ = ["ListDashboardsResponse"]
+
+
+class ListDashboardsResponse(BaseModel):
+ commit_hash: str
+ """Commit hash used to load dashboard specs."""
+
+ dashboards: List[DashboardItem]
+ """All dashboard specs in src/visualizations/\\**.viz.json."""
diff --git a/src/structify/types/session_upload_dashboard_layout_params.py b/src/structify/types/session_upload_dashboard_layout_params.py
index 039ff7441..9404afd61 100644
--- a/src/structify/types/session_upload_dashboard_layout_params.py
+++ b/src/structify/types/session_upload_dashboard_layout_params.py
@@ -2,16 +2,31 @@
from __future__ import annotations
-from typing_extensions import Required, TypedDict
+from typing import Union, Iterable
+from typing_extensions import Required, TypeAlias, TypedDict
from .dashboard_param import DashboardParam
+from .dashboard_spec_param import DashboardSpecParam
-__all__ = ["SessionUploadDashboardLayoutParams"]
+__all__ = ["SessionUploadDashboardLayoutParams", "Variant0", "Variant1", "Variant1DashboardSpec"]
-class SessionUploadDashboardLayoutParams(TypedDict, total=False):
+class Variant0(TypedDict, total=False):
layout: Required[DashboardParam]
"""
A page is the top-level container with title/description Can contain multiple
dashboards with different datasets
"""
+
+
+class Variant1(TypedDict, total=False):
+ dashboard_specs: Required[Iterable[Variant1DashboardSpec]]
+
+
+class Variant1DashboardSpec(TypedDict, total=False):
+ file_name: Required[str]
+
+ spec: Required[DashboardSpecParam]
+
+
+SessionUploadDashboardLayoutParams: TypeAlias = Union[Variant0, Variant1]
diff --git a/src/structify/types/upload_dashboard_layout_request_param.py b/src/structify/types/upload_dashboard_layout_request_param.py
new file mode 100644
index 000000000..972cd55ed
--- /dev/null
+++ b/src/structify/types/upload_dashboard_layout_request_param.py
@@ -0,0 +1,32 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union, Iterable
+from typing_extensions import Required, TypeAlias, TypedDict
+
+from .dashboard_param import DashboardParam
+from .dashboard_spec_param import DashboardSpecParam
+
+__all__ = ["UploadDashboardLayoutRequestParam", "Layout", "DashboardSpecs", "DashboardSpecsDashboardSpec"]
+
+
+class Layout(TypedDict, total=False):
+ layout: Required[DashboardParam]
+ """
+ A page is the top-level container with title/description Can contain multiple
+ dashboards with different datasets
+ """
+
+
+class DashboardSpecsDashboardSpec(TypedDict, total=False):
+ file_name: Required[str]
+
+ spec: Required[DashboardSpecParam]
+
+
+class DashboardSpecs(TypedDict, total=False):
+ dashboard_specs: Required[Iterable[DashboardSpecsDashboardSpec]]
+
+
+UploadDashboardLayoutRequestParam: TypeAlias = Union[Layout, DashboardSpecs]
diff --git a/src/structify/types/viz_boolean_control.py b/src/structify/types/viz_boolean_control.py
new file mode 100644
index 000000000..7b217fd44
--- /dev/null
+++ b/src/structify/types/viz_boolean_control.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .viz_boolean_control_type import VizBooleanControlType
+
+__all__ = ["VizBooleanControl"]
+
+
+class VizBooleanControl(BaseModel):
+ label: str
+
+ type: VizBooleanControlType
diff --git a/src/structify/types/viz_boolean_control_param.py b/src/structify/types/viz_boolean_control_param.py
new file mode 100644
index 000000000..866601613
--- /dev/null
+++ b/src/structify/types/viz_boolean_control_param.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .viz_boolean_control_type import VizBooleanControlType
+
+__all__ = ["VizBooleanControlParam"]
+
+
+class VizBooleanControlParam(TypedDict, total=False):
+ label: Required[str]
+
+ type: Required[VizBooleanControlType]
diff --git a/src/structify/types/viz_boolean_control_type.py b/src/structify/types/viz_boolean_control_type.py
new file mode 100644
index 000000000..be767552e
--- /dev/null
+++ b/src/structify/types/viz_boolean_control_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["VizBooleanControlType"]
+
+VizBooleanControlType: TypeAlias = Literal["checkbox"]
diff --git a/src/structify/types/viz_control_option.py b/src/structify/types/viz_control_option.py
new file mode 100644
index 000000000..dfe26755e
--- /dev/null
+++ b/src/structify/types/viz_control_option.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["VizControlOption"]
+
+
+class VizControlOption(BaseModel):
+ label: str
+
+ value: str
diff --git a/src/structify/types/viz_control_option_param.py b/src/structify/types/viz_control_option_param.py
new file mode 100644
index 000000000..b6edd6bc1
--- /dev/null
+++ b/src/structify/types/viz_control_option_param.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["VizControlOptionParam"]
+
+
+class VizControlOptionParam(TypedDict, total=False):
+ label: Required[str]
+
+ value: Required[str]
diff --git a/src/structify/types/viz_date_control.py b/src/structify/types/viz_date_control.py
new file mode 100644
index 000000000..397dbe4a5
--- /dev/null
+++ b/src/structify/types/viz_date_control.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .viz_date_control_type import VizDateControlType
+
+__all__ = ["VizDateControl"]
+
+
+class VizDateControl(BaseModel):
+ label: str
+
+ type: VizDateControlType
diff --git a/src/structify/types/viz_date_control_param.py b/src/structify/types/viz_date_control_param.py
new file mode 100644
index 000000000..32ed102e4
--- /dev/null
+++ b/src/structify/types/viz_date_control_param.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .viz_date_control_type import VizDateControlType
+
+__all__ = ["VizDateControlParam"]
+
+
+class VizDateControlParam(TypedDict, total=False):
+ label: Required[str]
+
+ type: Required[VizDateControlType]
diff --git a/src/structify/types/viz_date_control_type.py b/src/structify/types/viz_date_control_type.py
new file mode 100644
index 000000000..a24b3f95c
--- /dev/null
+++ b/src/structify/types/viz_date_control_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["VizDateControlType"]
+
+VizDateControlType: TypeAlias = Literal["date"]
diff --git a/src/structify/types/viz_figure.py b/src/structify/types/viz_figure.py
new file mode 100644
index 000000000..dab6b01c6
--- /dev/null
+++ b/src/structify/types/viz_figure.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+from .viz_figure_definition import VizFigureDefinition
+
+__all__ = ["VizFigure"]
+
+
+class VizFigure(BaseModel):
+ id: str
+
+ figure: VizFigureDefinition
+
+ description: Optional[str] = None
+
+ span: Optional[int] = None
+
+ title: Optional[str] = None
diff --git a/src/structify/types/viz_figure_definition.py b/src/structify/types/viz_figure_definition.py
new file mode 100644
index 000000000..9928e4e8a
--- /dev/null
+++ b/src/structify/types/viz_figure_definition.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .viz_figure_kind import VizFigureKind
+
+__all__ = ["VizFigureDefinition"]
+
+
+class VizFigureDefinition(BaseModel):
+ expression: str
+
+ kind: VizFigureKind
diff --git a/src/structify/types/viz_figure_definition_param.py b/src/structify/types/viz_figure_definition_param.py
new file mode 100644
index 000000000..1f26b349a
--- /dev/null
+++ b/src/structify/types/viz_figure_definition_param.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .viz_figure_kind import VizFigureKind
+
+__all__ = ["VizFigureDefinitionParam"]
+
+
+class VizFigureDefinitionParam(TypedDict, total=False):
+ expression: Required[str]
+
+ kind: Required[VizFigureKind]
diff --git a/src/structify/types/viz_figure_kind.py b/src/structify/types/viz_figure_kind.py
new file mode 100644
index 000000000..32d895e43
--- /dev/null
+++ b/src/structify/types/viz_figure_kind.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["VizFigureKind"]
+
+VizFigureKind: TypeAlias = Literal["js", "vega-lite"]
diff --git a/src/structify/types/viz_figure_param.py b/src/structify/types/viz_figure_param.py
new file mode 100644
index 000000000..e76dd3968
--- /dev/null
+++ b/src/structify/types/viz_figure_param.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .viz_figure_definition_param import VizFigureDefinitionParam
+
+__all__ = ["VizFigureParam"]
+
+
+class VizFigureParam(TypedDict, total=False):
+ id: Required[str]
+
+ figure: Required[VizFigureDefinitionParam]
+
+ description: str
+
+ span: int
+
+ title: str
diff --git a/src/structify/types/viz_number_control.py b/src/structify/types/viz_number_control.py
new file mode 100644
index 000000000..efdc9d22e
--- /dev/null
+++ b/src/structify/types/viz_number_control.py
@@ -0,0 +1,20 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+
+from .._models import BaseModel
+from .viz_number_control_type import VizNumberControlType
+
+__all__ = ["VizNumberControl"]
+
+
+class VizNumberControl(BaseModel):
+ label: str
+
+ max: float
+
+ min: float
+
+ type: VizNumberControlType
+
+ step: Optional[float] = None
diff --git a/src/structify/types/viz_number_control_param.py b/src/structify/types/viz_number_control_param.py
new file mode 100644
index 000000000..2d511b586
--- /dev/null
+++ b/src/structify/types/viz_number_control_param.py
@@ -0,0 +1,21 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .viz_number_control_type import VizNumberControlType
+
+__all__ = ["VizNumberControlParam"]
+
+
+class VizNumberControlParam(TypedDict, total=False):
+ label: Required[str]
+
+ max: Required[float]
+
+ min: Required[float]
+
+ type: Required[VizNumberControlType]
+
+ step: float
diff --git a/src/structify/types/viz_number_control_type.py b/src/structify/types/viz_number_control_type.py
new file mode 100644
index 000000000..30ffa1301
--- /dev/null
+++ b/src/structify/types/viz_number_control_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["VizNumberControlType"]
+
+VizNumberControlType: TypeAlias = Literal["range"]
diff --git a/src/structify/types/viz_param.py b/src/structify/types/viz_param.py
new file mode 100644
index 000000000..83e779bb8
--- /dev/null
+++ b/src/structify/types/viz_param.py
@@ -0,0 +1,48 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Union, Optional
+from typing_extensions import Literal, Annotated, TypeAlias
+
+from .._utils import PropertyInfo
+from .._models import BaseModel
+from .viz_date_control import VizDateControl
+from .viz_number_control import VizNumberControl
+from .viz_string_control import VizStringControl
+from .viz_boolean_control import VizBooleanControl
+
+__all__ = ["VizParam", "String", "Number", "Boolean", "Date"]
+
+
+class String(BaseModel):
+ type: Literal["string"]
+
+ value: str
+
+ control: Optional[VizStringControl] = None
+
+
+class Number(BaseModel):
+ type: Literal["number"]
+
+ value: float
+
+ control: Optional[VizNumberControl] = None
+
+
+class Boolean(BaseModel):
+ type: Literal["boolean"]
+
+ value: bool
+
+ control: Optional[VizBooleanControl] = None
+
+
+class Date(BaseModel):
+ type: Literal["date"]
+
+ value: str
+
+ control: Optional[VizDateControl] = None
+
+
+VizParam: TypeAlias = Annotated[Union[String, Number, Boolean, Date], PropertyInfo(discriminator="type")]
diff --git a/src/structify/types/viz_param_param.py b/src/structify/types/viz_param_param.py
new file mode 100644
index 000000000..ca0d8f6a1
--- /dev/null
+++ b/src/structify/types/viz_param_param.py
@@ -0,0 +1,48 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Union
+from typing_extensions import Literal, Required, TypeAlias, TypedDict
+
+from .viz_date_control_param import VizDateControlParam
+from .viz_number_control_param import VizNumberControlParam
+from .viz_string_control_param import VizStringControlParam
+from .viz_boolean_control_param import VizBooleanControlParam
+
+__all__ = ["VizParamParam", "String", "Number", "Boolean", "Date"]
+
+
+class String(TypedDict, total=False):
+ type: Required[Literal["string"]]
+
+ value: Required[str]
+
+ control: VizStringControlParam
+
+
+class Number(TypedDict, total=False):
+ type: Required[Literal["number"]]
+
+ value: Required[float]
+
+ control: VizNumberControlParam
+
+
+class Boolean(TypedDict, total=False):
+ type: Required[Literal["boolean"]]
+
+ value: Required[bool]
+
+ control: VizBooleanControlParam
+
+
+class Date(TypedDict, total=False):
+ type: Required[Literal["date"]]
+
+ value: Required[str]
+
+ control: VizDateControlParam
+
+
+VizParamParam: TypeAlias = Union[String, Number, Boolean, Date]
diff --git a/src/structify/types/viz_query.py b/src/structify/types/viz_query.py
new file mode 100644
index 000000000..e6c751625
--- /dev/null
+++ b/src/structify/types/viz_query.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["VizQuery"]
+
+
+class VizQuery(BaseModel):
+ id: str
+
+ sql: str
diff --git a/src/structify/types/viz_query_param.py b/src/structify/types/viz_query_param.py
new file mode 100644
index 000000000..71aad068a
--- /dev/null
+++ b/src/structify/types/viz_query_param.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+__all__ = ["VizQueryParam"]
+
+
+class VizQueryParam(TypedDict, total=False):
+ id: Required[str]
+
+ sql: Required[str]
diff --git a/src/structify/types/viz_string_control.py b/src/structify/types/viz_string_control.py
new file mode 100644
index 000000000..fbb70d640
--- /dev/null
+++ b/src/structify/types/viz_string_control.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from .._models import BaseModel
+from .viz_control_option import VizControlOption
+from .viz_string_control_type import VizStringControlType
+
+__all__ = ["VizStringControl"]
+
+
+class VizStringControl(BaseModel):
+ label: str
+
+ options: List[VizControlOption]
+
+ type: VizStringControlType
diff --git a/src/structify/types/viz_string_control_param.py b/src/structify/types/viz_string_control_param.py
new file mode 100644
index 000000000..f01adeb0d
--- /dev/null
+++ b/src/structify/types/viz_string_control_param.py
@@ -0,0 +1,19 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Iterable
+from typing_extensions import Required, TypedDict
+
+from .viz_string_control_type import VizStringControlType
+from .viz_control_option_param import VizControlOptionParam
+
+__all__ = ["VizStringControlParam"]
+
+
+class VizStringControlParam(TypedDict, total=False):
+ label: Required[str]
+
+ options: Required[Iterable[VizControlOptionParam]]
+
+ type: Required[VizStringControlType]
diff --git a/src/structify/types/viz_string_control_type.py b/src/structify/types/viz_string_control_type.py
new file mode 100644
index 000000000..fa2b28c76
--- /dev/null
+++ b/src/structify/types/viz_string_control_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["VizStringControlType"]
+
+VizStringControlType: TypeAlias = Literal["dropdown"]
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 1c4c8ef63..96e578994 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -15,6 +15,7 @@
ChatSession,
ChatLoadFilesResponse,
GetChatSessionResponse,
+ ListDashboardsResponse,
SimulatePromptResponse,
AdminIssueFoundResponse,
ChatSessionWithMessages,
@@ -690,6 +691,52 @@ def test_path_params_list_collaborators(self, client: Structify) -> None:
"",
)
+ @parametrize
+ def test_method_list_dashboards(self, client: Structify) -> None:
+ chat = client.chat.list_dashboards(
+ chat_id="chat_id",
+ )
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ @parametrize
+ def test_method_list_dashboards_with_all_params(self, client: Structify) -> None:
+ chat = client.chat.list_dashboards(
+ chat_id="chat_id",
+ commit_hash="commit_hash",
+ )
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_list_dashboards(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.list_dashboards(
+ chat_id="chat_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list_dashboards(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.list_dashboards(
+ chat_id="chat_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list_dashboards(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.chat.with_raw_response.list_dashboards(
+ chat_id="",
+ )
+
@parametrize
def test_method_list_input_files(self, client: Structify) -> None:
chat = client.chat.list_input_files(
@@ -2158,6 +2205,52 @@ async def test_path_params_list_collaborators(self, async_client: AsyncStructify
"",
)
+ @parametrize
+ async def test_method_list_dashboards(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.list_dashboards(
+ chat_id="chat_id",
+ )
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_method_list_dashboards_with_all_params(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.list_dashboards(
+ chat_id="chat_id",
+ commit_hash="commit_hash",
+ )
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list_dashboards(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.list_dashboards(
+ chat_id="chat_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list_dashboards(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.list_dashboards(
+ chat_id="chat_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ListDashboardsResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list_dashboards(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.chat.with_raw_response.list_dashboards(
+ chat_id="",
+ )
+
@parametrize
async def test_method_list_input_files(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.list_input_files(
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index ec5542a58..e0e912d1b 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -855,7 +855,7 @@ def test_path_params_update_node_progress(self, client: Structify) -> None:
)
@parametrize
- def test_method_upload_dashboard_layout(self, client: Structify) -> None:
+ def test_method_upload_dashboard_layout_overload_1(self, client: Structify) -> None:
session = client.sessions.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -875,7 +875,7 @@ def test_method_upload_dashboard_layout(self, client: Structify) -> None:
assert_matches_type(WorkflowSession, session, path=["response"])
@parametrize
- def test_method_upload_dashboard_layout_with_all_params(self, client: Structify) -> None:
+ def test_method_upload_dashboard_layout_with_all_params_overload_1(self, client: Structify) -> None:
session = client.sessions.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -916,7 +916,7 @@ def test_method_upload_dashboard_layout_with_all_params(self, client: Structify)
assert_matches_type(WorkflowSession, session, path=["response"])
@parametrize
- def test_raw_response_upload_dashboard_layout(self, client: Structify) -> None:
+ def test_raw_response_upload_dashboard_layout_overload_1(self, client: Structify) -> None:
response = client.sessions.with_raw_response.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -940,7 +940,7 @@ def test_raw_response_upload_dashboard_layout(self, client: Structify) -> None:
assert_matches_type(WorkflowSession, session, path=["response"])
@parametrize
- def test_streaming_response_upload_dashboard_layout(self, client: Structify) -> None:
+ def test_streaming_response_upload_dashboard_layout_overload_1(self, client: Structify) -> None:
with client.sessions.with_streaming_response.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -966,7 +966,7 @@ def test_streaming_response_upload_dashboard_layout(self, client: Structify) ->
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_upload_dashboard_layout(self, client: Structify) -> None:
+ def test_path_params_upload_dashboard_layout_overload_1(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
client.sessions.with_raw_response.upload_dashboard_layout(
session_id="",
@@ -985,6 +985,172 @@ def test_path_params_upload_dashboard_layout(self, client: Structify) -> None:
},
)
+ @parametrize
+ def test_method_upload_dashboard_layout_overload_2(self, client: Structify) -> None:
+ session = client.sessions.upload_dashboard_layout(
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ )
+ assert_matches_type(WorkflowSession, session, path=["response"])
+
+ @parametrize
+ def test_raw_response_upload_dashboard_layout_overload_2(self, client: Structify) -> None:
+ response = client.sessions.with_raw_response.upload_dashboard_layout(
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = response.parse()
+ assert_matches_type(WorkflowSession, session, path=["response"])
+
+ @parametrize
+ def test_streaming_response_upload_dashboard_layout_overload_2(self, client: Structify) -> None:
+ with client.sessions.with_streaming_response.upload_dashboard_layout(
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = response.parse()
+ assert_matches_type(WorkflowSession, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_dashboard_layout_overload_2(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ client.sessions.with_raw_response.upload_dashboard_layout(
+ session_id="",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ )
+
@parametrize
def test_method_upload_node_output_data(self, client: Structify) -> None:
session = client.sessions.upload_node_output_data(
@@ -1913,7 +2079,7 @@ async def test_path_params_update_node_progress(self, async_client: AsyncStructi
)
@parametrize
- async def test_method_upload_dashboard_layout(self, async_client: AsyncStructify) -> None:
+ async def test_method_upload_dashboard_layout_overload_1(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -1933,7 +2099,9 @@ async def test_method_upload_dashboard_layout(self, async_client: AsyncStructify
assert_matches_type(WorkflowSession, session, path=["response"])
@parametrize
- async def test_method_upload_dashboard_layout_with_all_params(self, async_client: AsyncStructify) -> None:
+ async def test_method_upload_dashboard_layout_with_all_params_overload_1(
+ self, async_client: AsyncStructify
+ ) -> None:
session = await async_client.sessions.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -1974,7 +2142,7 @@ async def test_method_upload_dashboard_layout_with_all_params(self, async_client
assert_matches_type(WorkflowSession, session, path=["response"])
@parametrize
- async def test_raw_response_upload_dashboard_layout(self, async_client: AsyncStructify) -> None:
+ async def test_raw_response_upload_dashboard_layout_overload_1(self, async_client: AsyncStructify) -> None:
response = await async_client.sessions.with_raw_response.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -1998,7 +2166,7 @@ async def test_raw_response_upload_dashboard_layout(self, async_client: AsyncStr
assert_matches_type(WorkflowSession, session, path=["response"])
@parametrize
- async def test_streaming_response_upload_dashboard_layout(self, async_client: AsyncStructify) -> None:
+ async def test_streaming_response_upload_dashboard_layout_overload_1(self, async_client: AsyncStructify) -> None:
async with async_client.sessions.with_streaming_response.upload_dashboard_layout(
session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
layout={
@@ -2024,7 +2192,7 @@ async def test_streaming_response_upload_dashboard_layout(self, async_client: As
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_upload_dashboard_layout(self, async_client: AsyncStructify) -> None:
+ async def test_path_params_upload_dashboard_layout_overload_1(self, async_client: AsyncStructify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
await async_client.sessions.with_raw_response.upload_dashboard_layout(
session_id="",
@@ -2043,6 +2211,172 @@ async def test_path_params_upload_dashboard_layout(self, async_client: AsyncStru
},
)
+ @parametrize
+ async def test_method_upload_dashboard_layout_overload_2(self, async_client: AsyncStructify) -> None:
+ session = await async_client.sessions.upload_dashboard_layout(
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ )
+ assert_matches_type(WorkflowSession, session, path=["response"])
+
+ @parametrize
+ async def test_raw_response_upload_dashboard_layout_overload_2(self, async_client: AsyncStructify) -> None:
+ response = await async_client.sessions.with_raw_response.upload_dashboard_layout(
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = await response.parse()
+ assert_matches_type(WorkflowSession, session, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_upload_dashboard_layout_overload_2(self, async_client: AsyncStructify) -> None:
+ async with async_client.sessions.with_streaming_response.upload_dashboard_layout(
+ session_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = await response.parse()
+ assert_matches_type(WorkflowSession, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_dashboard_layout_overload_2(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ await async_client.sessions.with_raw_response.upload_dashboard_layout(
+ session_id="",
+ dashboard_specs=[
+ {
+ "file_name": "file_name",
+ "spec": {
+ "dataset": "dataset",
+ "description": "description",
+ "figures": [
+ {
+ "id": "id",
+ "figure": {
+ "expression": "expression",
+ "kind": "js",
+ },
+ }
+ ],
+ "params": {
+ "foo": {
+ "type": "string",
+ "value": "value",
+ }
+ },
+ "queries": [
+ {
+ "id": "id",
+ "sql": "sql",
+ }
+ ],
+ "title": "title",
+ "version": "version",
+ },
+ }
+ ],
+ )
+
@parametrize
async def test_method_upload_node_output_data(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.upload_node_output_data(
From e426d6bf94f57c72581cd3289faf17a8dcd4538e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 7 Mar 2026 19:01:55 +0000
Subject: [PATCH 053/105] chore(ci): skip uploading artifacts on
stainless-internal branches
---
.github/workflows/ci.yml | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bf85fadee..61b6d6e00 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -61,14 +61,18 @@ jobs:
run: rye build
- name: Get GitHub OIDC Token
- if: github.repository == 'stainless-sdks/structify-python'
+ if: |-
+ github.repository == 'stainless-sdks/structify-python' &&
+ !startsWith(github.ref, 'refs/heads/stl/')
id: github-oidc
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());
- name: Upload tarball
- if: github.repository == 'stainless-sdks/structify-python'
+ if: |-
+ github.repository == 'stainless-sdks/structify-python' &&
+ !startsWith(github.ref, 'refs/heads/stl/')
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
From cfb1da44851a3714a7096d23413a09abae1ecfc5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 7 Mar 2026 19:03:29 +0000
Subject: [PATCH 054/105] chore: update placeholder string
---
.../connector_catalog/test_admin.py | 16 +++++-----
tests/api_resources/test_chat.py | 16 +++++-----
tests/api_resources/test_documents.py | 32 +++++++++----------
tests/api_resources/test_entities.py | 16 +++++-----
tests/api_resources/test_sessions.py | 20 ++++++------
5 files changed, 50 insertions(+), 50 deletions(-)
diff --git a/tests/api_resources/connector_catalog/test_admin.py b/tests/api_resources/connector_catalog/test_admin.py
index 764d2d5ed..224b67a19 100644
--- a/tests/api_resources/connector_catalog/test_admin.py
+++ b/tests/api_resources/connector_catalog/test_admin.py
@@ -702,7 +702,7 @@ def test_path_params_update_scope(self, client: Structify) -> None:
def test_method_upload_logo(self, client: Structify) -> None:
admin = client.connector_catalog.admin.upload_logo(
slug="slug",
- file=b"raw file contents",
+ file=b"Example data",
)
assert_matches_type(UploadLogoResponse, admin, path=["response"])
@@ -710,7 +710,7 @@ def test_method_upload_logo(self, client: Structify) -> None:
def test_raw_response_upload_logo(self, client: Structify) -> None:
response = client.connector_catalog.admin.with_raw_response.upload_logo(
slug="slug",
- file=b"raw file contents",
+ file=b"Example data",
)
assert response.is_closed is True
@@ -722,7 +722,7 @@ def test_raw_response_upload_logo(self, client: Structify) -> None:
def test_streaming_response_upload_logo(self, client: Structify) -> None:
with client.connector_catalog.admin.with_streaming_response.upload_logo(
slug="slug",
- file=b"raw file contents",
+ file=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -737,7 +737,7 @@ def test_path_params_upload_logo(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `slug` but received ''"):
client.connector_catalog.admin.with_raw_response.upload_logo(
slug="",
- file=b"raw file contents",
+ file=b"Example data",
)
@@ -1422,7 +1422,7 @@ async def test_path_params_update_scope(self, async_client: AsyncStructify) -> N
async def test_method_upload_logo(self, async_client: AsyncStructify) -> None:
admin = await async_client.connector_catalog.admin.upload_logo(
slug="slug",
- file=b"raw file contents",
+ file=b"Example data",
)
assert_matches_type(UploadLogoResponse, admin, path=["response"])
@@ -1430,7 +1430,7 @@ async def test_method_upload_logo(self, async_client: AsyncStructify) -> None:
async def test_raw_response_upload_logo(self, async_client: AsyncStructify) -> None:
response = await async_client.connector_catalog.admin.with_raw_response.upload_logo(
slug="slug",
- file=b"raw file contents",
+ file=b"Example data",
)
assert response.is_closed is True
@@ -1442,7 +1442,7 @@ async def test_raw_response_upload_logo(self, async_client: AsyncStructify) -> N
async def test_streaming_response_upload_logo(self, async_client: AsyncStructify) -> None:
async with async_client.connector_catalog.admin.with_streaming_response.upload_logo(
slug="slug",
- file=b"raw file contents",
+ file=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1457,5 +1457,5 @@ async def test_path_params_upload_logo(self, async_client: AsyncStructify) -> No
with pytest.raises(ValueError, match=r"Expected a non-empty value for `slug` but received ''"):
await async_client.connector_catalog.admin.with_raw_response.upload_logo(
slug="",
- file=b"raw file contents",
+ file=b"Example data",
)
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 96e578994..e35b110ce 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -1514,7 +1514,7 @@ def test_path_params_update_visibility(self, client: Structify) -> None:
def test_method_upload_input_file(self, client: Structify) -> None:
chat = client.chat.upload_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
)
@@ -1524,7 +1524,7 @@ def test_method_upload_input_file(self, client: Structify) -> None:
def test_raw_response_upload_input_file(self, client: Structify) -> None:
response = client.chat.with_raw_response.upload_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
)
@@ -1538,7 +1538,7 @@ def test_raw_response_upload_input_file(self, client: Structify) -> None:
def test_streaming_response_upload_input_file(self, client: Structify) -> None:
with client.chat.with_streaming_response.upload_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
) as response:
@@ -1555,7 +1555,7 @@ def test_path_params_upload_input_file(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
client.chat.with_raw_response.upload_input_file(
chat_id="",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
)
@@ -3030,7 +3030,7 @@ async def test_path_params_update_visibility(self, async_client: AsyncStructify)
async def test_method_upload_input_file(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.upload_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
)
@@ -3040,7 +3040,7 @@ async def test_method_upload_input_file(self, async_client: AsyncStructify) -> N
async def test_raw_response_upload_input_file(self, async_client: AsyncStructify) -> None:
response = await async_client.chat.with_raw_response.upload_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
)
@@ -3054,7 +3054,7 @@ async def test_raw_response_upload_input_file(self, async_client: AsyncStructify
async def test_streaming_response_upload_input_file(self, async_client: AsyncStructify) -> None:
async with async_client.chat.with_streaming_response.upload_input_file(
chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
) as response:
@@ -3071,7 +3071,7 @@ async def test_path_params_upload_input_file(self, async_client: AsyncStructify)
with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
await async_client.chat.with_raw_response.upload_input_file(
chat_id="",
- content=b"raw file contents",
+ content=b"Example data",
content_type="content_type",
file_name="file_name",
)
diff --git a/tests/api_resources/test_documents.py b/tests/api_resources/test_documents.py
index 0882dfaf9..6562d8463 100644
--- a/tests/api_resources/test_documents.py
+++ b/tests/api_resources/test_documents.py
@@ -118,18 +118,18 @@ def test_streaming_response_download(self, client: Structify) -> None:
@parametrize
def test_method_upload(self, client: Structify) -> None:
document = client.documents.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
)
assert document is None
@parametrize
def test_method_upload_with_all_params(self, client: Structify) -> None:
document = client.documents.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
dataset="dataset",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -138,9 +138,9 @@ def test_method_upload_with_all_params(self, client: Structify) -> None:
@parametrize
def test_raw_response_upload(self, client: Structify) -> None:
response = client.documents.with_raw_response.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
)
assert response.is_closed is True
@@ -151,9 +151,9 @@ def test_raw_response_upload(self, client: Structify) -> None:
@parametrize
def test_streaming_response_upload(self, client: Structify) -> None:
with client.documents.with_streaming_response.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -267,18 +267,18 @@ async def test_streaming_response_download(self, async_client: AsyncStructify) -
@parametrize
async def test_method_upload(self, async_client: AsyncStructify) -> None:
document = await async_client.documents.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
)
assert document is None
@parametrize
async def test_method_upload_with_all_params(self, async_client: AsyncStructify) -> None:
document = await async_client.documents.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
dataset="dataset",
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -287,9 +287,9 @@ async def test_method_upload_with_all_params(self, async_client: AsyncStructify)
@parametrize
async def test_raw_response_upload(self, async_client: AsyncStructify) -> None:
response = await async_client.documents.with_raw_response.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
)
assert response.is_closed is True
@@ -300,9 +300,9 @@ async def test_raw_response_upload(self, async_client: AsyncStructify) -> None:
@parametrize
async def test_streaming_response_upload(self, async_client: AsyncStructify) -> None:
async with async_client.documents.with_streaming_response.upload(
- content=b"raw file contents",
+ content=b"Example data",
file_type="Text",
- path=b"raw file contents",
+ path=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_entities.py b/tests/api_resources/test_entities.py
index 0e408f166..0db32a661 100644
--- a/tests/api_resources/test_entities.py
+++ b/tests/api_resources/test_entities.py
@@ -819,7 +819,7 @@ def test_method_upload_parquet(self, client: Structify) -> None:
entity = client.entities.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
)
assert entity is None
@@ -828,7 +828,7 @@ def test_method_upload_parquet_with_all_params(self, client: Structify) -> None:
entity = client.entities.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
start_embedding=True,
)
assert entity is None
@@ -838,7 +838,7 @@ def test_raw_response_upload_parquet(self, client: Structify) -> None:
response = client.entities.with_raw_response.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
)
assert response.is_closed is True
@@ -851,7 +851,7 @@ def test_streaming_response_upload_parquet(self, client: Structify) -> None:
with client.entities.with_streaming_response.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1773,7 +1773,7 @@ async def test_method_upload_parquet(self, async_client: AsyncStructify) -> None
entity = await async_client.entities.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
)
assert entity is None
@@ -1782,7 +1782,7 @@ async def test_method_upload_parquet_with_all_params(self, async_client: AsyncSt
entity = await async_client.entities.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
start_embedding=True,
)
assert entity is None
@@ -1792,7 +1792,7 @@ async def test_raw_response_upload_parquet(self, async_client: AsyncStructify) -
response = await async_client.entities.with_raw_response.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
)
assert response.is_closed is True
@@ -1805,7 +1805,7 @@ async def test_streaming_response_upload_parquet(self, async_client: AsyncStruct
async with async_client.entities.with_streaming_response.upload_parquet(
dataset="dataset",
table_name="table_name",
- content=b"raw file contents",
+ content=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index e0e912d1b..0e50193bc 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -1155,7 +1155,7 @@ def test_path_params_upload_dashboard_layout_overload_2(self, client: Structify)
def test_method_upload_node_output_data(self, client: Structify) -> None:
session = client.sessions.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
)
assert_matches_type(WorkflowSessionNode, session, path=["response"])
@@ -1163,7 +1163,7 @@ def test_method_upload_node_output_data(self, client: Structify) -> None:
def test_method_upload_node_output_data_with_all_params(self, client: Structify) -> None:
session = client.sessions.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
cache_final_rows=0,
cache_final_size_bytes=0,
cache_max_bytes=0,
@@ -1178,7 +1178,7 @@ def test_method_upload_node_output_data_with_all_params(self, client: Structify)
def test_raw_response_upload_node_output_data(self, client: Structify) -> None:
response = client.sessions.with_raw_response.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
)
assert response.is_closed is True
@@ -1190,7 +1190,7 @@ def test_raw_response_upload_node_output_data(self, client: Structify) -> None:
def test_streaming_response_upload_node_output_data(self, client: Structify) -> None:
with client.sessions.with_streaming_response.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1205,7 +1205,7 @@ def test_path_params_upload_node_output_data(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `node_id` but received ''"):
client.sessions.with_raw_response.upload_node_output_data(
node_id="",
- content=b"raw file contents",
+ content=b"Example data",
)
@parametrize
@@ -2381,7 +2381,7 @@ async def test_path_params_upload_dashboard_layout_overload_2(self, async_client
async def test_method_upload_node_output_data(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
)
assert_matches_type(WorkflowSessionNode, session, path=["response"])
@@ -2389,7 +2389,7 @@ async def test_method_upload_node_output_data(self, async_client: AsyncStructify
async def test_method_upload_node_output_data_with_all_params(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
cache_final_rows=0,
cache_final_size_bytes=0,
cache_max_bytes=0,
@@ -2404,7 +2404,7 @@ async def test_method_upload_node_output_data_with_all_params(self, async_client
async def test_raw_response_upload_node_output_data(self, async_client: AsyncStructify) -> None:
response = await async_client.sessions.with_raw_response.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
)
assert response.is_closed is True
@@ -2416,7 +2416,7 @@ async def test_raw_response_upload_node_output_data(self, async_client: AsyncStr
async def test_streaming_response_upload_node_output_data(self, async_client: AsyncStructify) -> None:
async with async_client.sessions.with_streaming_response.upload_node_output_data(
node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"raw file contents",
+ content=b"Example data",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2431,7 +2431,7 @@ async def test_path_params_upload_node_output_data(self, async_client: AsyncStru
with pytest.raises(ValueError, match=r"Expected a non-empty value for `node_id` but received ''"):
await async_client.sessions.with_raw_response.upload_node_output_data(
node_id="",
- content=b"raw file contents",
+ content=b"Example data",
)
@parametrize
From e348c2a7b58b48e7c5655757a098bea70033b2b9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 10 Mar 2026 00:26:15 +0000
Subject: [PATCH 055/105] feat: Update from Structify backend changes
---
.stats.yml | 6 +--
api.md | 1 -
src/structify/types/__init__.py | 2 -
src/structify/types/chat_prompt.py | 3 --
src/structify/types/chat_prompt_param.py | 3 --
src/structify/types/tool_metadata.py | 47 ------------------
src/structify/types/tool_metadata_param.py | 49 -------------------
tests/api_resources/test_chat.py | 56 ----------------------
8 files changed, 3 insertions(+), 164 deletions(-)
delete mode 100644 src/structify/types/tool_metadata.py
delete mode 100644 src/structify/types/tool_metadata_param.py
diff --git a/.stats.yml b/.stats.yml
index 36d25337c..ade911ca0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-5eb7f5d41cc9870f690042a3450fac21134c487fde82bf87bf6691157a337d5c.yml
-openapi_spec_hash: bc853c7c7ffc2f6df3aabd883308df61
-config_hash: a9e2da657c35219124ded3c60964a7b0
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-425092b9e637344a8a3be67ac1a45ecf760938b4160e30d7d7bdd2d7435c70e6.yml
+openapi_spec_hash: 55e53242c50c16e2aeaee5058ee19df2
+config_hash: a5e36f7fd04afb3cbc1a5378beea704e
diff --git a/api.md b/api.md
index e9fd3744e..9012c971e 100644
--- a/api.md
+++ b/api.md
@@ -965,7 +965,6 @@ Types:
from structify.types import (
ChatPrompt,
SaveRequirement,
- ToolMetadata,
StructureEnhancePropertyResponse,
StructureEnhanceRelationshipResponse,
StructureFindRelationshipResponse,
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 23bbee3b1..9a36eb1cf 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -34,7 +34,6 @@
from .chat_template import ChatTemplate as ChatTemplate
from .message_param import MessageParam as MessageParam
from .property_type import PropertyType as PropertyType
-from .tool_metadata import ToolMetadata as ToolMetadata
from .dashboard_item import DashboardItem as DashboardItem
from .dashboard_page import DashboardPage as DashboardPage
from .dashboard_spec import DashboardSpec as DashboardSpec
@@ -110,7 +109,6 @@
from .list_teams_response import ListTeamsResponse as ListTeamsResponse
from .property_type_param import PropertyTypeParam as PropertyTypeParam
from .slack_events_params import SlackEventsParams as SlackEventsParams
-from .tool_metadata_param import ToolMetadataParam as ToolMetadataParam
from .user_refresh_params import UserRefreshParams as UserRefreshParams
from .user_usage_response import UserUsageResponse as UserUsageResponse
from .viz_boolean_control import VizBooleanControl as VizBooleanControl
diff --git a/src/structify/types/chat_prompt.py b/src/structify/types/chat_prompt.py
index 04c7a1fba..e89b2d303 100644
--- a/src/structify/types/chat_prompt.py
+++ b/src/structify/types/chat_prompt.py
@@ -7,7 +7,6 @@
from .message import Message
from .._models import BaseModel
-from .tool_metadata import ToolMetadata
from .knowledge_graph import KnowledgeGraph
from .save_requirement import SaveRequirement
from .dataset_descriptor import DatasetDescriptor
@@ -238,8 +237,6 @@ class Metadata(BaseModel):
formatter_specific: MetadataFormatterSpecific
- tool_metadata: List[ToolMetadata]
-
qa_potentially_sus_response: Optional[str] = None
diff --git a/src/structify/types/chat_prompt_param.py b/src/structify/types/chat_prompt_param.py
index d7817d346..10d188a3b 100644
--- a/src/structify/types/chat_prompt_param.py
+++ b/src/structify/types/chat_prompt_param.py
@@ -8,7 +8,6 @@
from .._types import FileTypes, SequenceNotStr
from .._utils import PropertyInfo
from .message_param import MessageParam
-from .tool_metadata_param import ToolMetadataParam
from .knowledge_graph_param import KnowledgeGraphParam
from .save_requirement_param import SaveRequirementParam
from .dataset_descriptor_param import DatasetDescriptorParam
@@ -243,8 +242,6 @@ class Metadata(TypedDict, total=False):
formatter_specific: Required[MetadataFormatterSpecific]
- tool_metadata: Required[Iterable[ToolMetadataParam]]
-
qa_potentially_sus_response: Optional[str]
diff --git a/src/structify/types/tool_metadata.py b/src/structify/types/tool_metadata.py
deleted file mode 100644
index 776b58e24..000000000
--- a/src/structify/types/tool_metadata.py
+++ /dev/null
@@ -1,47 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal
-
-from .._models import BaseModel
-
-__all__ = ["ToolMetadata"]
-
-
-class ToolMetadata(BaseModel):
- description: str
-
- name: Literal[
- "WebSearch",
- "WebNavigate",
- "ViewPage",
- "Save",
- "SaveEntities",
- "Exit",
- "ApiExecute",
- "Javascript",
- "NavigateToIFrame",
- "InfiniteScroll",
- "InspectStep",
- "ReadNodeLogs",
- "DeleteFile",
- "MoveFile",
- "ApplyPatch",
- "RunBash",
- "RunPython",
- "IssueFound",
- "SaveDatabase",
- "SaveSchema",
- "SaveTable",
- "SaveColumn",
- "SaveApiResource",
- "SaveMemory",
- "SearchConnectorTables",
- "RequestClarification",
- "AddDependency",
- "SelectData",
- "CreateConnector",
- "SearchConnectorTypes",
- "PinPreviousTool",
- ]
-
- regex_validator: str
diff --git a/src/structify/types/tool_metadata_param.py b/src/structify/types/tool_metadata_param.py
deleted file mode 100644
index 6b3f77eed..000000000
--- a/src/structify/types/tool_metadata_param.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Literal, Required, TypedDict
-
-__all__ = ["ToolMetadataParam"]
-
-
-class ToolMetadataParam(TypedDict, total=False):
- description: Required[str]
-
- name: Required[
- Literal[
- "WebSearch",
- "WebNavigate",
- "ViewPage",
- "Save",
- "SaveEntities",
- "Exit",
- "ApiExecute",
- "Javascript",
- "NavigateToIFrame",
- "InfiniteScroll",
- "InspectStep",
- "ReadNodeLogs",
- "DeleteFile",
- "MoveFile",
- "ApplyPatch",
- "RunBash",
- "RunPython",
- "IssueFound",
- "SaveDatabase",
- "SaveSchema",
- "SaveTable",
- "SaveColumn",
- "SaveApiResource",
- "SaveMemory",
- "SearchConnectorTables",
- "RequestClarification",
- "AddDependency",
- "SelectData",
- "CreateConnector",
- "SearchConnectorTypes",
- "PinPreviousTool",
- ]
- ]
-
- regex_validator: Required[str]
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index e35b110ce..b9534bbda 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -1169,13 +1169,6 @@ def test_method_simulate_prompt(self, client: Structify) -> None:
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
)
@@ -1231,13 +1224,6 @@ def test_raw_response_simulate_prompt(self, client: Structify) -> None:
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
)
@@ -1297,13 +1283,6 @@ def test_streaming_response_simulate_prompt(self, client: Structify) -> None:
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
) as response:
@@ -1366,13 +1345,6 @@ def test_path_params_simulate_prompt(self, client: Structify) -> None:
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
)
@@ -2685,13 +2657,6 @@ async def test_method_simulate_prompt(self, async_client: AsyncStructify) -> Non
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
)
@@ -2747,13 +2712,6 @@ async def test_raw_response_simulate_prompt(self, async_client: AsyncStructify)
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
)
@@ -2813,13 +2771,6 @@ async def test_streaming_response_simulate_prompt(self, async_client: AsyncStruc
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
) as response:
@@ -2882,13 +2833,6 @@ async def test_path_params_simulate_prompt(self, async_client: AsyncStructify) -
],
"extraction_criteria": [{"relationship_name": "relationship_name"}],
"formatter_specific": {"image_meta": {"image": "image"}},
- "tool_metadata": [
- {
- "description": "description",
- "name": "WebSearch",
- "regex_validator": "regex_validator",
- }
- ],
},
},
)
From 9f876676e531c57f0133d2a413bf739d3f7f93cc Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 11 Mar 2026 00:08:46 +0000
Subject: [PATCH 056/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/chat_event.py | 4 ----
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index ade911ca0..ae01d43f6 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-425092b9e637344a8a3be67ac1a45ecf760938b4160e30d7d7bdd2d7435c70e6.yml
-openapi_spec_hash: 55e53242c50c16e2aeaee5058ee19df2
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-76a9e1969d4771131c0193bf3f0181fcb5aa02980537e47f030c77c73ba29859.yml
+openapi_spec_hash: ace96e0ce4920f0449870644a3753f50
config_hash: a5e36f7fd04afb3cbc1a5378beea704e
diff --git a/src/structify/types/chat_event.py b/src/structify/types/chat_event.py
index 297959dd8..c6da66729 100644
--- a/src/structify/types/chat_event.py
+++ b/src/structify/types/chat_event.py
@@ -151,10 +151,6 @@ class InternalErrorInternalError(BaseModel):
"""
Categorizes the kind of internal error that occurred during LLM generation. This
allows the frontend to render appropriate error messages without regex matching.
-
- Classification logic lives in `LlmError::kind()` (in the inference crate) so
- that errors are categorized at the source. This enum is the serializable
- representation used in ChatEvent / proto / OpenAPI.
"""
From 74d1eadcaade7a9bf4f43a968b34a69441647b47 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Mar 2026 21:58:41 +0000
Subject: [PATCH 057/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/tool_invocation.py | 13 +++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index ae01d43f6..76cbb7bf2 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-76a9e1969d4771131c0193bf3f0181fcb5aa02980537e47f030c77c73ba29859.yml
-openapi_spec_hash: ace96e0ce4920f0449870644a3753f50
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-41bb5097c6756e5e41de5f1125227c3d88a0ad4b060d0a87f682288c9d7e7419.yml
+openapi_spec_hash: 423b55f409f2521afb7d5fbbcc1709d8
config_hash: a5e36f7fd04afb3cbc1a5378beea704e
diff --git a/src/structify/types/tool_invocation.py b/src/structify/types/tool_invocation.py
index 00ce844d4..b5d8146c4 100644
--- a/src/structify/types/tool_invocation.py
+++ b/src/structify/types/tool_invocation.py
@@ -71,6 +71,8 @@
"SearchConnectorTypesInput",
"PinPreviousTool",
"PinPreviousToolInput",
+ "RunPipeline",
+ "RunPipelineInput",
]
@@ -467,6 +469,16 @@ class PinPreviousTool(BaseModel):
name: Literal["PinPreviousTool"]
+class RunPipelineInput(BaseModel):
+ rerun_all_steps: Optional[bool] = None
+
+
+class RunPipeline(BaseModel):
+ input: RunPipelineInput
+
+ name: Literal["RunPipeline"]
+
+
ToolInvocation: TypeAlias = Annotated[
Union[
WebSearch,
@@ -500,6 +512,7 @@ class PinPreviousTool(BaseModel):
CreateConnector,
SearchConnectorTypes,
PinPreviousTool,
+ RunPipeline,
],
PropertyInfo(discriminator="name"),
]
From ec36375820077853cb8faa683432b1c9c34788be Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 12 Mar 2026 22:37:54 +0000
Subject: [PATCH 058/105] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 76cbb7bf2..4720c1ebf 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-41bb5097c6756e5e41de5f1125227c3d88a0ad4b060d0a87f682288c9d7e7419.yml
-openapi_spec_hash: 423b55f409f2521afb7d5fbbcc1709d8
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-789e1e6e129ac80b380c6387f61955583cbdfd8d2b824910a67933c44794ce76.yml
+openapi_spec_hash: 452ae5d0ca948e3f1dc1e5fdad97b260
config_hash: a5e36f7fd04afb3cbc1a5378beea704e
From 38e454b00abe1dbd46adcbcf73e01f0babae4faa Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 00:19:51 +0000
Subject: [PATCH 059/105] feat: Update from Structify backend changes
---
.stats.yml | 6 +++---
api.md | 1 +
src/structify/types/chat_create_session_params.py | 1 +
src/structify/types/code_generate_code_params.py | 1 +
src/structify/types/workflow_dag.py | 3 +++
5 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 4720c1ebf..635cb0f7c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-789e1e6e129ac80b380c6387f61955583cbdfd8d2b824910a67933c44794ce76.yml
-openapi_spec_hash: 452ae5d0ca948e3f1dc1e5fdad97b260
-config_hash: a5e36f7fd04afb3cbc1a5378beea704e
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-b005d6ec8e7f20eab35dbe8b6c136dd99d61df0ae1a4eaa242ea9673ba4e15e6.yml
+openapi_spec_hash: d353f1acbb6efd45ebe02f5928626669
+config_hash: f074085b31bcb53bfc522f0f977f735f
diff --git a/api.md b/api.md
index 9012c971e..614d9f853 100644
--- a/api.md
+++ b/api.md
@@ -604,6 +604,7 @@ from structify.types import (
VizStringControl,
VizStringControlType,
WorkflowDag,
+ WorkflowDashboardItem,
WorkflowNodeExecutionStatus,
WorkflowNodeLog,
WorkflowSession,
diff --git a/src/structify/types/chat_create_session_params.py b/src/structify/types/chat_create_session_params.py
index da5dc01a8..835fa23ac 100644
--- a/src/structify/types/chat_create_session_params.py
+++ b/src/structify/types/chat_create_session_params.py
@@ -48,6 +48,7 @@ class Config(TypedDict, total=False):
"gemini.gemini-2.5-flash",
"gemini.gemini-3-pro-preview",
"gemini.gemini-3-flash-preview",
+ "gemini.gemini-3.1-flash-lite-preview",
"vertex_anthropic.claude-sonnet-4-5-vertex",
]
]
diff --git a/src/structify/types/code_generate_code_params.py b/src/structify/types/code_generate_code_params.py
index c93a743bc..23ffbc170 100644
--- a/src/structify/types/code_generate_code_params.py
+++ b/src/structify/types/code_generate_code_params.py
@@ -61,6 +61,7 @@ class Config(TypedDict, total=False):
"gemini.gemini-2.5-flash",
"gemini.gemini-3-pro-preview",
"gemini.gemini-3-flash-preview",
+ "gemini.gemini-3.1-flash-lite-preview",
"vertex_anthropic.claude-sonnet-4-5-vertex",
]
]
diff --git a/src/structify/types/workflow_dag.py b/src/structify/types/workflow_dag.py
index 2a0f0470f..d896e6210 100644
--- a/src/structify/types/workflow_dag.py
+++ b/src/structify/types/workflow_dag.py
@@ -5,6 +5,7 @@
from .._models import BaseModel
from .dashboard import Dashboard
+from .dashboard_item import DashboardItem
from .workflow_session_edge import WorkflowSessionEdge
from .workflow_session_node import WorkflowSessionNode
@@ -14,6 +15,8 @@
class WorkflowDag(BaseModel):
aborted: bool
+ dashboard_specs: List[DashboardItem]
+
edges: List[WorkflowSessionEdge]
is_ready: bool
From ea00e09a4b072323f1f13c2825773257f638c462 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 02:20:56 +0000
Subject: [PATCH 060/105] fix(pydantic): do not pass `by_alias` unless set
---
src/structify/_compat.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/structify/_compat.py b/src/structify/_compat.py
index 786ff42ad..e6690a4f2 100644
--- a/src/structify/_compat.py
+++ b/src/structify/_compat.py
@@ -2,7 +2,7 @@
from typing import TYPE_CHECKING, Any, Union, Generic, TypeVar, Callable, cast, overload
from datetime import date, datetime
-from typing_extensions import Self, Literal
+from typing_extensions import Self, Literal, TypedDict
import pydantic
from pydantic.fields import FieldInfo
@@ -131,6 +131,10 @@ def model_json(model: pydantic.BaseModel, *, indent: int | None = None) -> str:
return model.model_dump_json(indent=indent)
+class _ModelDumpKwargs(TypedDict, total=False):
+ by_alias: bool
+
+
def model_dump(
model: pydantic.BaseModel,
*,
@@ -142,6 +146,9 @@ def model_dump(
by_alias: bool | None = None,
) -> dict[str, Any]:
if (not PYDANTIC_V1) or hasattr(model, "model_dump"):
+ kwargs: _ModelDumpKwargs = {}
+ if by_alias is not None:
+ kwargs["by_alias"] = by_alias
return model.model_dump(
mode=mode,
exclude=exclude,
@@ -149,7 +156,7 @@ def model_dump(
exclude_defaults=exclude_defaults,
# warnings are not supported in Pydantic v1
warnings=True if PYDANTIC_V1 else warnings,
- by_alias=by_alias,
+ **kwargs,
)
return cast(
"dict[str, Any]",
From e948f171a34d73a5b6e5f6b334a86b6b98180d4d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 02:27:22 +0000
Subject: [PATCH 061/105] fix(deps): bump minimum typing-extensions version
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 985ed4b25..b7b294339 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ authors = [
dependencies = [
"httpx>=0.23.0, <1",
"pydantic>=1.9.0, <3",
- "typing-extensions>=4.10, <5",
+ "typing-extensions>=4.14, <5",
"anyio>=3.5.0, <5",
"distro>=1.7.0, <2",
"sniffio",
From 20ef4cf65fbf656dec67a065725fc4931a224912 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 02:31:59 +0000
Subject: [PATCH 062/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/admin/user.py | 2 --
src/structify/types/user_info.py | 2 --
src/structify/types/user_update_params.py | 2 --
tests/api_resources/test_user.py | 2 --
5 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 635cb0f7c..5740fdbb8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-b005d6ec8e7f20eab35dbe8b6c136dd99d61df0ae1a4eaa242ea9673ba4e15e6.yml
-openapi_spec_hash: d353f1acbb6efd45ebe02f5928626669
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-26e219376d21d589f7756457bd691a1ea39b0d19d4f55d6eb1ca6151aff9e4c2.yml
+openapi_spec_hash: 1ec1e990acd42642c6c5c8d581025a30
config_hash: f074085b31bcb53bfc522f0f977f735f
diff --git a/src/structify/types/admin/user.py b/src/structify/types/admin/user.py
index 75eccf6b7..cc3fb4d99 100644
--- a/src/structify/types/admin/user.py
+++ b/src/structify/types/admin/user.py
@@ -40,8 +40,6 @@ class User(BaseModel):
full_name: str
- is_developer: bool
-
notify_for_interaction: bool
permissions: List[Optional[Literal["labeler", "qa_labeler", "debug", "human_llm", "none"]]]
diff --git a/src/structify/types/user_info.py b/src/structify/types/user_info.py
index 2977019ec..7532590e7 100644
--- a/src/structify/types/user_info.py
+++ b/src/structify/types/user_info.py
@@ -34,8 +34,6 @@ class UserInfo(BaseModel):
full_name: str
- is_developer: bool
-
notify_for_interaction: bool
permissions: List[Literal["labeler", "qa_labeler", "debug", "human_llm", "none"]]
diff --git a/src/structify/types/user_update_params.py b/src/structify/types/user_update_params.py
index a7c787dc4..9c1616109 100644
--- a/src/structify/types/user_update_params.py
+++ b/src/structify/types/user_update_params.py
@@ -54,8 +54,6 @@ class Updates(TypedDict, total=False):
full_name: Optional[str]
- is_developer: Optional[bool]
-
job_title: Optional[str]
last_selected_team_id: Optional[str]
diff --git a/tests/api_resources/test_user.py b/tests/api_resources/test_user.py
index a236b9144..57a4dcc64 100644
--- a/tests/api_resources/test_user.py
+++ b/tests/api_resources/test_user.py
@@ -45,7 +45,6 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
"feature_flags": ["functional_test"],
"feature_overrides": {},
"full_name": "full_name",
- "is_developer": True,
"job_title": "job_title",
"last_selected_team_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
"linkedin_url": "linkedin_url",
@@ -292,7 +291,6 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
"feature_flags": ["functional_test"],
"feature_overrides": {},
"full_name": "full_name",
- "is_developer": True,
"job_title": "job_title",
"last_selected_team_id": "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
"linkedin_url": "linkedin_url",
From 92ed8ac799e16266310bc9e66cb8bbcff3e681aa Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 02:41:04 +0000
Subject: [PATCH 063/105] chore(internal): tweak CI branches
---
.github/workflows/ci.yml | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 61b6d6e00..d0fd5d668 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,12 +1,14 @@
name: CI
on:
push:
- branches-ignore:
- - 'generated'
- - 'codegen/**'
- - 'integrated/**'
- - 'stl-preview-head/**'
- - 'stl-preview-base/**'
+ branches:
+ - '**'
+ - '!integrated/**'
+ - '!stl-preview-head/**'
+ - '!stl-preview-base/**'
+ - '!generated'
+ - '!codegen/**'
+ - 'codegen/stl/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
From 6cdb36ba947a077d7a4ea24ec416da65d2cf4c3f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 03:54:27 +0000
Subject: [PATCH 064/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/tool_invocation.py | 4 ----
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 5740fdbb8..c065e1b8d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-26e219376d21d589f7756457bd691a1ea39b0d19d4f55d6eb1ca6151aff9e4c2.yml
-openapi_spec_hash: 1ec1e990acd42642c6c5c8d581025a30
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-da6077ef51ea35a25a28cec6760627b7f37c12ba9009936666545d879fd03503.yml
+openapi_spec_hash: 077c2532b878259c535b97afb2cbfc55
config_hash: f074085b31bcb53bfc522f0f977f735f
diff --git a/src/structify/types/tool_invocation.py b/src/structify/types/tool_invocation.py
index b5d8146c4..53388f030 100644
--- a/src/structify/types/tool_invocation.py
+++ b/src/structify/types/tool_invocation.py
@@ -198,12 +198,8 @@ class InspectStep(BaseModel):
class ReadNodeLogsInput(BaseModel):
- end_line: int
-
node_function_name: str
- start_line: int
-
log_type: Optional[str] = None
From aa264524de4459f4977103f5884778d5b3e5200f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 04:06:43 +0000
Subject: [PATCH 065/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +--
api.md | 2 +
.../resources/connectors/connectors.py | 49 ++++++++++++++++++
src/structify/types/__init__.py | 1 +
.../types/connector_list_stores_response.py | 10 ++++
tests/api_resources/test_connectors.py | 51 +++++++++++++++++++
6 files changed, 117 insertions(+), 4 deletions(-)
create mode 100644 src/structify/types/connector_list_stores_response.py
diff --git a/.stats.yml b/.stats.yml
index c065e1b8d..d5db12590 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 243
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-da6077ef51ea35a25a28cec6760627b7f37c12ba9009936666545d879fd03503.yml
-openapi_spec_hash: 077c2532b878259c535b97afb2cbfc55
-config_hash: f074085b31bcb53bfc522f0f977f735f
+configured_endpoints: 244
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-dacbc09d24ac8a4b46091e6a70ca20564e0abbafbfda8104e7fa42640eb82108.yml
+openapi_spec_hash: 64a90006c49167de28dc53926fc56927
+config_hash: 57e9672c594f991b310af96a4a3d315f
diff --git a/api.md b/api.md
index 614d9f853..a593bda5e 100644
--- a/api.md
+++ b/api.md
@@ -714,6 +714,7 @@ from structify.types import (
ConnectorAddSchemaObjectResponse,
ConnectorGetResponse,
ConnectorGetClarificationRequestsResponse,
+ ConnectorListStoresResponse,
ConnectorListWithSnippetsResponse,
ConnectorSearchTablesResponse,
ConnectorSummariesResponse,
@@ -738,6 +739,7 @@ Methods:
- client.connectors.get_explorer_chat(connector_id, \*\*params) -> ExplorerChatResponse
- client.connectors.get_store(connector_id) -> ConnectorStoreResponse
- client.connectors.get_table_path(table_id) -> ConnectorTablePathResponse
+- client.connectors.list_stores() -> ConnectorListStoresResponse
- client.connectors.list_tables(connector_id) -> ListTablesResponse
- client.connectors.list_with_snippets() -> ConnectorListWithSnippetsResponse
- client.connectors.resolve_clarification(clarification_id) -> None
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 6326c8ceb..6a2301e83 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -55,6 +55,7 @@
from ...types.connector_summaries_response import ConnectorSummariesResponse
from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
+from ...types.connector_list_stores_response import ConnectorListStoresResponse
from ...types.connector_search_tables_response import ConnectorSearchTablesResponse
from ...types.connector_add_schema_object_response import ConnectorAddSchemaObjectResponse
from ...types.connector_list_with_snippets_response import ConnectorListWithSnippetsResponse
@@ -928,6 +929,24 @@ def get_table_path(
cast_to=ConnectorTablePathResponse,
)
+ def list_stores(
+ self,
+ *,
+ # 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,
+ ) -> ConnectorListStoresResponse:
+ return self._get(
+ "/connectors/stores",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ConnectorListStoresResponse,
+ )
+
def list_tables(
self,
connector_id: str,
@@ -2033,6 +2052,24 @@ async def get_table_path(
cast_to=ConnectorTablePathResponse,
)
+ async def list_stores(
+ self,
+ *,
+ # 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,
+ ) -> ConnectorListStoresResponse:
+ return await self._get(
+ "/connectors/stores",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ConnectorListStoresResponse,
+ )
+
async def list_tables(
self,
connector_id: str,
@@ -2329,6 +2366,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_table_path = to_raw_response_wrapper(
connectors.get_table_path,
)
+ self.list_stores = to_raw_response_wrapper(
+ connectors.list_stores,
+ )
self.list_tables = to_raw_response_wrapper(
connectors.list_tables,
)
@@ -2408,6 +2448,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_table_path = async_to_raw_response_wrapper(
connectors.get_table_path,
)
+ self.list_stores = async_to_raw_response_wrapper(
+ connectors.list_stores,
+ )
self.list_tables = async_to_raw_response_wrapper(
connectors.list_tables,
)
@@ -2487,6 +2530,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_table_path = to_streamed_response_wrapper(
connectors.get_table_path,
)
+ self.list_stores = to_streamed_response_wrapper(
+ connectors.list_stores,
+ )
self.list_tables = to_streamed_response_wrapper(
connectors.list_tables,
)
@@ -2566,6 +2612,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_table_path = async_to_streamed_response_wrapper(
connectors.get_table_path,
)
+ self.list_stores = async_to_streamed_response_wrapper(
+ connectors.list_stores,
+ )
self.list_tables = async_to_streamed_response_wrapper(
connectors.list_tables,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 9a36eb1cf..1e106b746 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -298,6 +298,7 @@
from .chat_revert_to_commit_response import ChatRevertToCommitResponse as ChatRevertToCommitResponse
from .connector_catalog_with_methods import ConnectorCatalogWithMethods as ConnectorCatalogWithMethods
from .connector_create_secret_params import ConnectorCreateSecretParams as ConnectorCreateSecretParams
+from .connector_list_stores_response import ConnectorListStoresResponse as ConnectorListStoresResponse
from .connector_search_tables_params import ConnectorSearchTablesParams as ConnectorSearchTablesParams
from .connector_update_column_params import ConnectorUpdateColumnParams as ConnectorUpdateColumnParams
from .credits_usage_timeseries_point import CreditsUsageTimeseriesPoint as CreditsUsageTimeseriesPoint
diff --git a/src/structify/types/connector_list_stores_response.py b/src/structify/types/connector_list_stores_response.py
new file mode 100644
index 000000000..f2675f159
--- /dev/null
+++ b/src/structify/types/connector_list_stores_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict
+from typing_extensions import TypeAlias
+
+from .llm_information_store import LlmInformationStore
+
+__all__ = ["ConnectorListStoresResponse"]
+
+ConnectorListStoresResponse: TypeAlias = Dict[str, LlmInformationStore]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index f265f270b..d07a07258 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -22,6 +22,7 @@
ConnectorSummariesResponse,
ConnectorTablePathResponse,
DeleteSchemaObjectResponse,
+ ConnectorListStoresResponse,
ConnectorSearchTablesResponse,
ConnectorAddSchemaObjectResponse,
ConnectorListWithSnippetsResponse,
@@ -1052,6 +1053,31 @@ def test_path_params_get_table_path(self, client: Structify) -> None:
"",
)
+ @parametrize
+ def test_method_list_stores(self, client: Structify) -> None:
+ connector = client.connectors.list_stores()
+ assert_matches_type(ConnectorListStoresResponse, connector, path=["response"])
+
+ @parametrize
+ def test_raw_response_list_stores(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.list_stores()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert_matches_type(ConnectorListStoresResponse, connector, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list_stores(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.list_stores() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert_matches_type(ConnectorListStoresResponse, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_list_tables(self, client: Structify) -> None:
connector = client.connectors.list_tables(
@@ -2334,6 +2360,31 @@ async def test_path_params_get_table_path(self, async_client: AsyncStructify) ->
"",
)
+ @parametrize
+ async def test_method_list_stores(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.list_stores()
+ assert_matches_type(ConnectorListStoresResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list_stores(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.list_stores()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert_matches_type(ConnectorListStoresResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list_stores(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.list_stores() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert_matches_type(ConnectorListStoresResponse, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_list_tables(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.list_tables(
From 2d67a154e0b37a1a29e35e21678b059a8cfe1e85 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 17 Mar 2026 17:37:46 +0000
Subject: [PATCH 066/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 +
.../resources/admin/chat_templates.py | 11 ++-
src/structify/resources/chat.py | 79 +++++++++++++++++++
src/structify/types/__init__.py | 2 +
.../admin/chat_template_create_params.py | 5 ++
.../admin/chat_template_update_params.py | 6 +-
src/structify/types/chat_copy_params.py | 2 +
src/structify/types/chat_session.py | 2 +
.../types/chat_session_with_messages.py | 4 +
src/structify/types/chat_template.py | 4 +
.../types/get_chat_session_response.py | 4 +
src/structify/types/template_question.py | 13 +++
.../types/template_question_param.py | 16 ++++
.../admin/test_chat_templates.py | 18 +++++
tests/api_resources/test_chat.py | 79 +++++++++++++++++++
16 files changed, 249 insertions(+), 6 deletions(-)
create mode 100644 src/structify/types/template_question.py
create mode 100644 src/structify/types/template_question_param.py
diff --git a/.stats.yml b/.stats.yml
index d5db12590..c0607966f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 244
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-dacbc09d24ac8a4b46091e6a70ca20564e0abbafbfda8104e7fa42640eb82108.yml
-openapi_spec_hash: 64a90006c49167de28dc53926fc56927
-config_hash: 57e9672c594f991b310af96a4a3d315f
+configured_endpoints: 245
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-df245a5c88858fff3ca4a8ad14e9fed7c5e99b5c1e4e12e8894c4da82c52ec5a.yml
+openapi_spec_hash: 41b3d0f34c1b6ab251aa369805351bee
+config_hash: e980645ca957a31830a363a9806cf754
diff --git a/api.md b/api.md
index a593bda5e..2d6979d0d 100644
--- a/api.md
+++ b/api.md
@@ -115,6 +115,7 @@ from structify.types import (
Message,
SimulatePromptRequest,
SimulatePromptResponse,
+ TemplateQuestion,
ToolInvocation,
ToolResult,
UpdateChatSessionFavoriteRequest,
@@ -151,6 +152,7 @@ Methods:
- client.chat.get_partial_chats(chat_session_id) -> ChatGetPartialChatsResponse
- client.chat.get_session(session_id) -> GetChatSessionResponse
- client.chat.get_session_timeline(session_id) -> ChatGetSessionTimelineResponse
+- client.chat.get_template(template_id) -> ChatTemplate
- client.chat.grant_admin_override(chat_id, \*\*params) -> AdminGrantAccessResponse
- client.chat.list_collaborators(chat_id) -> ListCollaboratorsResponse
- client.chat.list_dashboards(chat_id, \*\*params) -> ListDashboardsResponse
diff --git a/src/structify/resources/admin/chat_templates.py b/src/structify/resources/admin/chat_templates.py
index 8d46ccc44..8304e38f4 100644
--- a/src/structify/resources/admin/chat_templates.py
+++ b/src/structify/resources/admin/chat_templates.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Optional
+from typing import Iterable, Optional
import httpx
@@ -19,6 +19,7 @@
from ...types.admin import chat_template_list_params, chat_template_create_params, chat_template_update_params
from ..._base_client import make_request_options
from ...types.chat_template import ChatTemplate
+from ...types.template_question_param import TemplateQuestionParam
from ...types.admin.chat_template_list_response import ChatTemplateListResponse
__all__ = ["ChatTemplatesResource", "AsyncChatTemplatesResource"]
@@ -54,6 +55,7 @@ def create(
display_order: int,
image_url: str,
is_active: bool,
+ questions: Iterable[TemplateQuestionParam],
title: str,
# 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.
@@ -81,6 +83,7 @@ def create(
"display_order": display_order,
"image_url": image_url,
"is_active": is_active,
+ "questions": questions,
"title": title,
},
chat_template_create_params.ChatTemplateCreateParams,
@@ -99,6 +102,7 @@ def update(
display_order: Optional[int] | Omit = omit,
image_url: Optional[str] | Omit = omit,
is_active: Optional[bool] | Omit = omit,
+ questions: Optional[Iterable[TemplateQuestionParam]] | Omit = omit,
title: Optional[str] | Omit = omit,
updated_by: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -128,6 +132,7 @@ def update(
"display_order": display_order,
"image_url": image_url,
"is_active": is_active,
+ "questions": questions,
"title": title,
"updated_by": updated_by,
},
@@ -205,6 +210,7 @@ async def create(
display_order: int,
image_url: str,
is_active: bool,
+ questions: Iterable[TemplateQuestionParam],
title: str,
# 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.
@@ -232,6 +238,7 @@ async def create(
"display_order": display_order,
"image_url": image_url,
"is_active": is_active,
+ "questions": questions,
"title": title,
},
chat_template_create_params.ChatTemplateCreateParams,
@@ -250,6 +257,7 @@ async def update(
display_order: Optional[int] | Omit = omit,
image_url: Optional[str] | Omit = omit,
is_active: Optional[bool] | Omit = omit,
+ questions: Optional[Iterable[TemplateQuestionParam]] | Omit = omit,
title: Optional[str] | Omit = omit,
updated_by: Optional[str] | Omit = omit,
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
@@ -279,6 +287,7 @@ async def update(
"display_order": display_order,
"image_url": image_url,
"is_active": is_active,
+ "questions": questions,
"title": title,
"updated_by": updated_by,
},
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 4b32bf576..a365b1d5b 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -49,6 +49,7 @@
)
from .._base_client import make_request_options
from ..types.chat_session import ChatSession
+from ..types.chat_template import ChatTemplate
from ..types.chat_visibility import ChatVisibility
from ..types.chat_prompt_param import ChatPromptParam
from ..types.chat_session_role import ChatSessionRole
@@ -228,6 +229,7 @@ def copy(
team_id: str,
copy_inputs: bool | Omit = omit,
project_id: Optional[str] | Omit = omit,
+ template_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -256,6 +258,7 @@ def copy(
"team_id": team_id,
"copy_inputs": copy_inputs,
"project_id": project_id,
+ "template_id": template_id,
},
chat_copy_params.ChatCopyParams,
),
@@ -586,6 +589,37 @@ def get_session_timeline(
cast_to=ChatGetSessionTimelineResponse,
)
+ def get_template(
+ self,
+ template_id: str,
+ *,
+ # 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,
+ ) -> ChatTemplate:
+ """
+ Args:
+ 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
+ """
+ if not template_id:
+ raise ValueError(f"Expected a non-empty value for `template_id` but received {template_id!r}")
+ return self._get(
+ f"/chat/templates/{template_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatTemplate,
+ )
+
def grant_admin_override(
self,
chat_id: str,
@@ -1380,6 +1414,7 @@ async def copy(
team_id: str,
copy_inputs: bool | Omit = omit,
project_id: Optional[str] | Omit = omit,
+ template_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -1408,6 +1443,7 @@ async def copy(
"team_id": team_id,
"copy_inputs": copy_inputs,
"project_id": project_id,
+ "template_id": template_id,
},
chat_copy_params.ChatCopyParams,
),
@@ -1740,6 +1776,37 @@ async def get_session_timeline(
cast_to=ChatGetSessionTimelineResponse,
)
+ async def get_template(
+ self,
+ template_id: str,
+ *,
+ # 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,
+ ) -> ChatTemplate:
+ """
+ Args:
+ 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
+ """
+ if not template_id:
+ raise ValueError(f"Expected a non-empty value for `template_id` but received {template_id!r}")
+ return await self._get(
+ f"/chat/templates/{template_id}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatTemplate,
+ )
+
async def grant_admin_override(
self,
chat_id: str,
@@ -2435,6 +2502,9 @@ def __init__(self, chat: ChatResource) -> None:
self.get_session_timeline = to_raw_response_wrapper(
chat.get_session_timeline,
)
+ self.get_template = to_raw_response_wrapper(
+ chat.get_template,
+ )
self.grant_admin_override = to_raw_response_wrapper(
chat.grant_admin_override,
)
@@ -2532,6 +2602,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.get_session_timeline = async_to_raw_response_wrapper(
chat.get_session_timeline,
)
+ self.get_template = async_to_raw_response_wrapper(
+ chat.get_template,
+ )
self.grant_admin_override = async_to_raw_response_wrapper(
chat.grant_admin_override,
)
@@ -2629,6 +2702,9 @@ def __init__(self, chat: ChatResource) -> None:
self.get_session_timeline = to_streamed_response_wrapper(
chat.get_session_timeline,
)
+ self.get_template = to_streamed_response_wrapper(
+ chat.get_template,
+ )
self.grant_admin_override = to_streamed_response_wrapper(
chat.grant_admin_override,
)
@@ -2726,6 +2802,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.get_session_timeline = async_to_streamed_response_wrapper(
chat.get_session_timeline,
)
+ self.get_template = async_to_streamed_response_wrapper(
+ chat.get_template,
+ )
self.grant_admin_override = async_to_streamed_response_wrapper(
chat.grant_admin_override,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 1e106b746..a64e3fe6b 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -73,6 +73,7 @@
from .get_team_response import GetTeamResponse as GetTeamResponse
from .job_list_response import JobListResponse as JobListResponse
from .job_status_params import JobStatusParams as JobStatusParams
+from .template_question import TemplateQuestion as TemplateQuestion
from .user_usage_params import UserUsageParams as UserUsageParams
from .workflow_node_log import WorkflowNodeLog as WorkflowNodeLog
from .connector_category import ConnectorCategory as ConnectorCategory
@@ -185,6 +186,7 @@
from .entity_summarize_params import EntitySummarizeParams as EntitySummarizeParams
from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
+from .template_question_param import TemplateQuestionParam as TemplateQuestionParam
from .viz_number_control_type import VizNumberControlType as VizNumberControlType
from .viz_string_control_type import VizStringControlType as VizStringControlType
from .chat_load_files_response import ChatLoadFilesResponse as ChatLoadFilesResponse
diff --git a/src/structify/types/admin/chat_template_create_params.py b/src/structify/types/admin/chat_template_create_params.py
index 9856cd691..5d4472c9c 100644
--- a/src/structify/types/admin/chat_template_create_params.py
+++ b/src/structify/types/admin/chat_template_create_params.py
@@ -2,8 +2,11 @@
from __future__ import annotations
+from typing import Iterable
from typing_extensions import Required, TypedDict
+from ..template_question_param import TemplateQuestionParam
+
__all__ = ["ChatTemplateCreateParams"]
@@ -18,4 +21,6 @@ class ChatTemplateCreateParams(TypedDict, total=False):
is_active: Required[bool]
+ questions: Required[Iterable[TemplateQuestionParam]]
+
title: Required[str]
diff --git a/src/structify/types/admin/chat_template_update_params.py b/src/structify/types/admin/chat_template_update_params.py
index 2b807aa4c..7129486a6 100644
--- a/src/structify/types/admin/chat_template_update_params.py
+++ b/src/structify/types/admin/chat_template_update_params.py
@@ -2,9 +2,11 @@
from __future__ import annotations
-from typing import Optional
+from typing import Iterable, Optional
from typing_extensions import TypedDict
+from ..template_question_param import TemplateQuestionParam
+
__all__ = ["ChatTemplateUpdateParams"]
@@ -17,6 +19,8 @@ class ChatTemplateUpdateParams(TypedDict, total=False):
is_active: Optional[bool]
+ questions: Optional[Iterable[TemplateQuestionParam]]
+
title: Optional[str]
updated_by: Optional[str]
diff --git a/src/structify/types/chat_copy_params.py b/src/structify/types/chat_copy_params.py
index 9e0070cb4..686312b2a 100644
--- a/src/structify/types/chat_copy_params.py
+++ b/src/structify/types/chat_copy_params.py
@@ -18,3 +18,5 @@ class ChatCopyParams(TypedDict, total=False):
copy_inputs: bool
project_id: Optional[str]
+
+ template_id: Optional[str]
diff --git a/src/structify/types/chat_session.py b/src/structify/types/chat_session.py
index faa486f01..70c8d9dfd 100644
--- a/src/structify/types/chat_session.py
+++ b/src/structify/types/chat_session.py
@@ -36,6 +36,8 @@ class ChatSession(BaseModel):
config_proto: Optional[object] = None
+ instantiated_from_template_id: Optional[str] = None
+
message_head: Optional[str] = None
name: Optional[str] = None
diff --git a/src/structify/types/chat_session_with_messages.py b/src/structify/types/chat_session_with_messages.py
index c7e989c41..7820f2e7c 100644
--- a/src/structify/types/chat_session_with_messages.py
+++ b/src/structify/types/chat_session_with_messages.py
@@ -69,6 +69,8 @@ class ChatSessionWithMessages(BaseModel):
created_at: datetime
+ ephemeral: bool
+
git_application_token: str
is_favorite: bool
@@ -87,6 +89,8 @@ class ChatSessionWithMessages(BaseModel):
visibility: ChatVisibility
+ instantiated_from_template_id: Optional[str] = None
+
latest_workflow_session_id: Optional[str] = None
message_head: Optional[str] = None
diff --git a/src/structify/types/chat_template.py b/src/structify/types/chat_template.py
index c7c96474d..1c93c1eab 100644
--- a/src/structify/types/chat_template.py
+++ b/src/structify/types/chat_template.py
@@ -1,8 +1,10 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing import List
from datetime import datetime
from .._models import BaseModel
+from .template_question import TemplateQuestion
__all__ = ["ChatTemplate"]
@@ -24,6 +26,8 @@ class ChatTemplate(BaseModel):
is_active: bool
+ questions: List[TemplateQuestion]
+
title: str
updated_at: datetime
diff --git a/src/structify/types/get_chat_session_response.py b/src/structify/types/get_chat_session_response.py
index 827dd24b3..3a31d94ed 100644
--- a/src/structify/types/get_chat_session_response.py
+++ b/src/structify/types/get_chat_session_response.py
@@ -50,6 +50,8 @@ class Session(BaseModel):
created_at: datetime
+ ephemeral: bool
+
git_application_token: str
is_favorite: bool
@@ -70,6 +72,8 @@ class Session(BaseModel):
workflow_sessions: List[WorkflowSession]
+ instantiated_from_template_id: Optional[str] = None
+
latest_workflow_session_id: Optional[str] = None
message_head: Optional[str] = None
diff --git a/src/structify/types/template_question.py b/src/structify/types/template_question.py
new file mode 100644
index 000000000..356e55278
--- /dev/null
+++ b/src/structify/types/template_question.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+
+__all__ = ["TemplateQuestion"]
+
+
+class TemplateQuestion(BaseModel):
+ prompt: str
+
+ options: Optional[List[str]] = None
diff --git a/src/structify/types/template_question_param.py b/src/structify/types/template_question_param.py
new file mode 100644
index 000000000..65cc0a2e2
--- /dev/null
+++ b/src/structify/types/template_question_param.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 Required, TypedDict
+
+from .._types import SequenceNotStr
+
+__all__ = ["TemplateQuestionParam"]
+
+
+class TemplateQuestionParam(TypedDict, total=False):
+ prompt: Required[str]
+
+ options: Optional[SequenceNotStr[str]]
diff --git a/tests/api_resources/admin/test_chat_templates.py b/tests/api_resources/admin/test_chat_templates.py
index e33d109bf..8d8115368 100644
--- a/tests/api_resources/admin/test_chat_templates.py
+++ b/tests/api_resources/admin/test_chat_templates.py
@@ -28,6 +28,7 @@ def test_method_create(self, client: Structify) -> None:
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[{"prompt": "prompt"}],
title="title",
)
assert_matches_type(ChatTemplate, chat_template, path=["response"])
@@ -40,6 +41,7 @@ def test_raw_response_create(self, client: Structify) -> None:
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[{"prompt": "prompt"}],
title="title",
)
@@ -56,6 +58,7 @@ def test_streaming_response_create(self, client: Structify) -> None:
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[{"prompt": "prompt"}],
title="title",
) as response:
assert not response.is_closed
@@ -81,6 +84,12 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[
+ {
+ "prompt": "prompt",
+ "options": ["string"],
+ }
+ ],
title="title",
updated_by="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@@ -163,6 +172,7 @@ async def test_method_create(self, async_client: AsyncStructify) -> None:
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[{"prompt": "prompt"}],
title="title",
)
assert_matches_type(ChatTemplate, chat_template, path=["response"])
@@ -175,6 +185,7 @@ async def test_raw_response_create(self, async_client: AsyncStructify) -> None:
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[{"prompt": "prompt"}],
title="title",
)
@@ -191,6 +202,7 @@ async def test_streaming_response_create(self, async_client: AsyncStructify) ->
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[{"prompt": "prompt"}],
title="title",
) as response:
assert not response.is_closed
@@ -216,6 +228,12 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
display_order=0,
image_url="image_url",
is_active=True,
+ questions=[
+ {
+ "prompt": "prompt",
+ "options": ["string"],
+ }
+ ],
title="title",
updated_by="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index b9534bbda..cd70a4cc2 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -13,6 +13,7 @@
from tests.utils import assert_matches_type
from structify.types import (
ChatSession,
+ ChatTemplate,
ChatLoadFilesResponse,
GetChatSessionResponse,
ListDashboardsResponse,
@@ -203,6 +204,7 @@ def test_method_copy_with_all_params(self, client: Structify) -> None:
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
copy_inputs=True,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ template_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ChatSessionWithMessages, chat, path=["response"])
@@ -607,6 +609,44 @@ def test_path_params_get_session_timeline(self, client: Structify) -> None:
"",
)
+ @parametrize
+ def test_method_get_template(self, client: Structify) -> None:
+ chat = client.chat.get_template(
+ "template_id",
+ )
+ assert_matches_type(ChatTemplate, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_template(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.get_template(
+ "template_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatTemplate, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_template(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.get_template(
+ "template_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatTemplate, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get_template(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `template_id` but received ''"):
+ client.chat.with_raw_response.get_template(
+ "",
+ )
+
@parametrize
def test_method_grant_admin_override(self, client: Structify) -> None:
chat = client.chat.grant_admin_override(
@@ -1689,6 +1729,7 @@ async def test_method_copy_with_all_params(self, async_client: AsyncStructify) -
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
copy_inputs=True,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ template_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ChatSessionWithMessages, chat, path=["response"])
@@ -2093,6 +2134,44 @@ async def test_path_params_get_session_timeline(self, async_client: AsyncStructi
"",
)
+ @parametrize
+ async def test_method_get_template(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.get_template(
+ "template_id",
+ )
+ assert_matches_type(ChatTemplate, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_template(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.get_template(
+ "template_id",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatTemplate, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_template(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.get_template(
+ "template_id",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatTemplate, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get_template(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `template_id` but received ''"):
+ await async_client.chat.with_raw_response.get_template(
+ "",
+ )
+
@parametrize
async def test_method_grant_admin_override(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.grant_admin_override(
From e8fa6c0eee8eef620bd297933c4bbff1da13b798 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Mar 2026 05:01:16 +0000
Subject: [PATCH 067/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 +
src/structify/resources/chat.py | 8 ++
src/structify/resources/sessions.py | 75 ++++++++++++++++++
src/structify/types/__init__.py | 1 +
.../types/chat_list_sessions_params.py | 3 +
.../types/list_chat_sessions_response.py | 3 +
.../types/trigger_review_response.py | 9 +++
tests/api_resources/test_chat.py | 2 +
tests/api_resources/test_sessions.py | 77 +++++++++++++++++++
10 files changed, 184 insertions(+), 4 deletions(-)
create mode 100644 src/structify/types/trigger_review_response.py
diff --git a/.stats.yml b/.stats.yml
index c0607966f..db658348f 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 245
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-df245a5c88858fff3ca4a8ad14e9fed7c5e99b5c1e4e12e8894c4da82c52ec5a.yml
-openapi_spec_hash: 41b3d0f34c1b6ab251aa369805351bee
-config_hash: e980645ca957a31830a363a9806cf754
+configured_endpoints: 246
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-3215afee3692b2cef56f97de912c4aa040339664813bd3d3d1e7b6f957882223.yml
+openapi_spec_hash: d878b64cfda7172a934f070cd40ebbfd
+config_hash: 6c301c61ddc3ede8e6bd85d2ef513747
diff --git a/api.md b/api.md
index 2d6979d0d..5cf65a761 100644
--- a/api.md
+++ b/api.md
@@ -587,6 +587,7 @@ from structify.types import (
NodeSpec,
ParquetEdit,
RequestConfirmationRequest,
+ TriggerReviewResponse,
UpdateWorkflowNodeProgressRequest,
UpdateWorkflowNodeRequest,
UploadDashboardLayoutRequest,
@@ -634,6 +635,7 @@ Methods:
- client.sessions.kill_jobs(session_id, \*\*params) -> SessionKillJobsResponse
- client.sessions.mark_errored(session_id, \*\*params) -> WorkflowSession
- client.sessions.request_confirmation(node_id, \*\*params) -> WorkflowSessionNode
+- client.sessions.trigger_review(session_id) -> TriggerReviewResponse
- client.sessions.update_node(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.update_node_progress(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.upload_dashboard_layout(session_id, \*\*params) -> WorkflowSession
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index a365b1d5b..9d421ce65 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -777,6 +777,7 @@ def list_sessions(
*,
team_id: str,
limit: Optional[int] | Omit = omit,
+ offset: Optional[int] | Omit = omit,
project_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -794,6 +795,8 @@ def list_sessions(
limit: Maximum number of sessions to return (default: 50)
+ offset: Number of sessions to skip (default: 0)
+
project_id: Project ID to filter chat sessions
extra_headers: Send extra headers
@@ -815,6 +818,7 @@ def list_sessions(
{
"team_id": team_id,
"limit": limit,
+ "offset": offset,
"project_id": project_id,
},
chat_list_sessions_params.ChatListSessionsParams,
@@ -1964,6 +1968,7 @@ async def list_sessions(
*,
team_id: str,
limit: Optional[int] | Omit = omit,
+ offset: Optional[int] | Omit = omit,
project_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1981,6 +1986,8 @@ async def list_sessions(
limit: Maximum number of sessions to return (default: 50)
+ offset: Number of sessions to skip (default: 0)
+
project_id: Project ID to filter chat sessions
extra_headers: Send extra headers
@@ -2002,6 +2009,7 @@ async def list_sessions(
{
"team_id": team_id,
"limit": limit,
+ "offset": offset,
"project_id": project_id,
},
chat_list_sessions_params.ChatListSessionsParams,
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 8ac4a64a4..19cea9a1e 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -54,6 +54,7 @@
from ..types.finalize_dag_response import FinalizeDagResponse
from ..types.workflow_session_node import WorkflowSessionNode
from ..types.get_node_logs_response import GetNodeLogsResponse
+from ..types.trigger_review_response import TriggerReviewResponse
from ..types.session_kill_jobs_response import SessionKillJobsResponse
from ..types.session_get_events_response import SessionGetEventsResponse
from ..types.workflow_node_execution_status import WorkflowNodeExecutionStatus
@@ -560,6 +561,37 @@ def request_confirmation(
cast_to=WorkflowSessionNode,
)
+ def trigger_review(
+ self,
+ session_id: str,
+ *,
+ # 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,
+ ) -> TriggerReviewResponse:
+ """
+ Args:
+ 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
+ """
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return self._post(
+ f"/sessions/{session_id}/trigger_review",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerReviewResponse,
+ )
+
def update_node(
self,
node_id: str,
@@ -1328,6 +1360,37 @@ async def request_confirmation(
cast_to=WorkflowSessionNode,
)
+ async def trigger_review(
+ self,
+ session_id: str,
+ *,
+ # 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,
+ ) -> TriggerReviewResponse:
+ """
+ Args:
+ 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
+ """
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return await self._post(
+ f"/sessions/{session_id}/trigger_review",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=TriggerReviewResponse,
+ )
+
async def update_node(
self,
node_id: str,
@@ -1641,6 +1704,9 @@ def __init__(self, sessions: SessionsResource) -> None:
self.request_confirmation = to_raw_response_wrapper(
sessions.request_confirmation,
)
+ self.trigger_review = to_raw_response_wrapper(
+ sessions.trigger_review,
+ )
self.update_node = to_raw_response_wrapper(
sessions.update_node,
)
@@ -1702,6 +1768,9 @@ def __init__(self, sessions: AsyncSessionsResource) -> None:
self.request_confirmation = async_to_raw_response_wrapper(
sessions.request_confirmation,
)
+ self.trigger_review = async_to_raw_response_wrapper(
+ sessions.trigger_review,
+ )
self.update_node = async_to_raw_response_wrapper(
sessions.update_node,
)
@@ -1763,6 +1832,9 @@ def __init__(self, sessions: SessionsResource) -> None:
self.request_confirmation = to_streamed_response_wrapper(
sessions.request_confirmation,
)
+ self.trigger_review = to_streamed_response_wrapper(
+ sessions.trigger_review,
+ )
self.update_node = to_streamed_response_wrapper(
sessions.update_node,
)
@@ -1824,6 +1896,9 @@ def __init__(self, sessions: AsyncSessionsResource) -> None:
self.request_confirmation = async_to_streamed_response_wrapper(
sessions.request_confirmation,
)
+ self.trigger_review = async_to_streamed_response_wrapper(
+ sessions.trigger_review,
+ )
self.update_node = async_to_streamed_response_wrapper(
sessions.update_node,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index a64e3fe6b..99a5f6d3d 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -187,6 +187,7 @@
from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
from .template_question_param import TemplateQuestionParam as TemplateQuestionParam
+from .trigger_review_response import TriggerReviewResponse as TriggerReviewResponse
from .viz_number_control_type import VizNumberControlType as VizNumberControlType
from .viz_string_control_type import VizStringControlType as VizStringControlType
from .chat_load_files_response import ChatLoadFilesResponse as ChatLoadFilesResponse
diff --git a/src/structify/types/chat_list_sessions_params.py b/src/structify/types/chat_list_sessions_params.py
index ad0ab10d6..2237d1bfb 100644
--- a/src/structify/types/chat_list_sessions_params.py
+++ b/src/structify/types/chat_list_sessions_params.py
@@ -15,5 +15,8 @@ class ChatListSessionsParams(TypedDict, total=False):
limit: Optional[int]
"""Maximum number of sessions to return (default: 50)"""
+ offset: Optional[int]
+ """Number of sessions to skip (default: 0)"""
+
project_id: Optional[str]
"""Project ID to filter chat sessions"""
diff --git a/src/structify/types/list_chat_sessions_response.py b/src/structify/types/list_chat_sessions_response.py
index a62d7c050..edc5395de 100644
--- a/src/structify/types/list_chat_sessions_response.py
+++ b/src/structify/types/list_chat_sessions_response.py
@@ -44,3 +44,6 @@ class ListChatSessionsResponse(BaseModel):
"""Response for listing chat sessions"""
sessions: List[Session]
+
+ total_count: int
+ """Total number of chat sessions matching the query (for pagination)"""
diff --git a/src/structify/types/trigger_review_response.py b/src/structify/types/trigger_review_response.py
new file mode 100644
index 000000000..af114c75f
--- /dev/null
+++ b/src/structify/types/trigger_review_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["TriggerReviewResponse"]
+
+
+class TriggerReviewResponse(BaseModel):
+ triggered: bool
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index cd70a4cc2..384ef17ae 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -827,6 +827,7 @@ def test_method_list_sessions_with_all_params(self, client: Structify) -> None:
chat = client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
+ offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ListChatSessionsResponse, chat, path=["response"])
@@ -2352,6 +2353,7 @@ async def test_method_list_sessions_with_all_params(self, async_client: AsyncStr
chat = await async_client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
+ offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ListChatSessionsResponse, chat, path=["response"])
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 0e50193bc..f960c82df 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -18,6 +18,7 @@
FinalizeDagResponse,
GetNodeLogsResponse,
WorkflowSessionNode,
+ TriggerReviewResponse,
SessionKillJobsResponse,
SessionGetEventsResponse,
SessionEditNodeOutputResponse,
@@ -740,6 +741,44 @@ def test_path_params_request_confirmation(self, client: Structify) -> None:
row_count=0,
)
+ @parametrize
+ def test_method_trigger_review(self, client: Structify) -> None:
+ session = client.sessions.trigger_review(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerReviewResponse, session, path=["response"])
+
+ @parametrize
+ def test_raw_response_trigger_review(self, client: Structify) -> None:
+ response = client.sessions.with_raw_response.trigger_review(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = response.parse()
+ assert_matches_type(TriggerReviewResponse, session, path=["response"])
+
+ @parametrize
+ def test_streaming_response_trigger_review(self, client: Structify) -> None:
+ with client.sessions.with_streaming_response.trigger_review(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = response.parse()
+ assert_matches_type(TriggerReviewResponse, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_trigger_review(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ client.sessions.with_raw_response.trigger_review(
+ "",
+ )
+
@parametrize
def test_method_update_node(self, client: Structify) -> None:
session = client.sessions.update_node(
@@ -1964,6 +2003,44 @@ async def test_path_params_request_confirmation(self, async_client: AsyncStructi
row_count=0,
)
+ @parametrize
+ async def test_method_trigger_review(self, async_client: AsyncStructify) -> None:
+ session = await async_client.sessions.trigger_review(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(TriggerReviewResponse, session, path=["response"])
+
+ @parametrize
+ async def test_raw_response_trigger_review(self, async_client: AsyncStructify) -> None:
+ response = await async_client.sessions.with_raw_response.trigger_review(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = await response.parse()
+ assert_matches_type(TriggerReviewResponse, session, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_trigger_review(self, async_client: AsyncStructify) -> None:
+ async with async_client.sessions.with_streaming_response.trigger_review(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = await response.parse()
+ assert_matches_type(TriggerReviewResponse, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_trigger_review(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ await async_client.sessions.with_raw_response.trigger_review(
+ "",
+ )
+
@parametrize
async def test_method_update_node(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.update_node(
From 0175b62731b9c9e7cc3a2069b32ed44fae801df2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Mar 2026 17:43:55 +0000
Subject: [PATCH 068/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 +
src/structify/resources/admin/jobs.py | 6 +-
src/structify/resources/chat.py | 8 -
.../resources/connectors/connectors.py | 226 +++++++++++++++-
src/structify/resources/jobs.py | 6 +-
src/structify/types/__init__.py | 3 +
src/structify/types/admin/job_list_params.py | 2 +-
.../types/admin/job_list_response.py | 38 ++-
.../types/chat_list_sessions_params.py | 3 -
.../types/connector_explore_params.py | 8 +-
...onnector_upload_datahub_artifact_params.py | 15 ++
.../types/entity_list_jobs_response.py | 6 +-
src/structify/types/job_cancel_response.py | 6 +-
src/structify/types/job_event_body.py | 12 +
src/structify/types/job_get_response.py | 40 ++-
src/structify/types/job_list_params.py | 2 +-
src/structify/types/job_list_response.py | 38 ++-
.../types/list_chat_sessions_response.py | 3 -
tests/api_resources/test_chat.py | 2 -
tests/api_resources/test_connectors.py | 254 +++++++++++++++++-
21 files changed, 605 insertions(+), 83 deletions(-)
create mode 100644 src/structify/types/connector_upload_datahub_artifact_params.py
diff --git a/.stats.yml b/.stats.yml
index db658348f..839481225 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 246
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-3215afee3692b2cef56f97de912c4aa040339664813bd3d3d1e7b6f957882223.yml
-openapi_spec_hash: d878b64cfda7172a934f070cd40ebbfd
-config_hash: 6c301c61ddc3ede8e6bd85d2ef513747
+configured_endpoints: 248
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-7e3bb1c810ee9c928220474b3b5d423d00eb5eff978c24d879a9d8947ccaf8ca.yml
+openapi_spec_hash: 795960913b5f4da29f171b45cfe19824
+config_hash: ab5291af3bd5919aecf1f8e41eb363b8
diff --git a/api.md b/api.md
index 5cf65a761..4547079d0 100644
--- a/api.md
+++ b/api.md
@@ -735,6 +735,7 @@ Methods:
- client.connectors.create_secret(connector_id, \*\*params) -> None
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
+- client.connectors.download_datahub_artifact(kind, \*, connector_id) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
@@ -751,6 +752,7 @@ Methods:
- client.connectors.summaries(\*\*params) -> ConnectorSummariesResponse
- client.connectors.update_column(column_id, \*\*params) -> None
- client.connectors.update_table(table_id, \*\*params) -> UpdateTableResponse
+- client.connectors.upload_datahub_artifact(kind, \*, connector_id, \*\*params) -> None
## TypeSnippets
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index 16f81550e..c95c5fb48 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -52,7 +52,8 @@ def with_streaming_response(self) -> JobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
@@ -182,7 +183,8 @@ def with_streaming_response(self) -> AsyncJobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 9d421ce65..a365b1d5b 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -777,7 +777,6 @@ def list_sessions(
*,
team_id: str,
limit: Optional[int] | Omit = omit,
- offset: Optional[int] | Omit = omit,
project_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -795,8 +794,6 @@ def list_sessions(
limit: Maximum number of sessions to return (default: 50)
- offset: Number of sessions to skip (default: 0)
-
project_id: Project ID to filter chat sessions
extra_headers: Send extra headers
@@ -818,7 +815,6 @@ def list_sessions(
{
"team_id": team_id,
"limit": limit,
- "offset": offset,
"project_id": project_id,
},
chat_list_sessions_params.ChatListSessionsParams,
@@ -1968,7 +1964,6 @@ async def list_sessions(
*,
team_id: str,
limit: Optional[int] | Omit = omit,
- offset: Optional[int] | Omit = omit,
project_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1986,8 +1981,6 @@ async def list_sessions(
limit: Maximum number of sessions to return (default: 50)
- offset: Number of sessions to skip (default: 0)
-
project_id: Project ID to filter chat sessions
extra_headers: Send extra headers
@@ -2009,7 +2002,6 @@ async def list_sessions(
{
"team_id": team_id,
"limit": limit,
- "offset": offset,
"project_id": project_id,
},
chat_list_sessions_params.ChatListSessionsParams,
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 6a2301e83..579013d49 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Dict, Optional, cast
+from typing import Any, Dict, Mapping, Optional, cast
from typing_extensions import Literal, overload
import httpx
@@ -21,16 +21,36 @@
connector_add_schema_object_params,
connector_get_explorer_chat_params,
connector_delete_schema_object_params,
+ connector_upload_datahub_artifact_params,
)
-from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import required_args, maybe_transform, async_maybe_transform
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NoneType,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
+ to_custom_raw_response_wrapper,
async_to_streamed_response_wrapper,
+ to_custom_streamed_response_wrapper,
+ async_to_custom_raw_response_wrapper,
+ async_to_custom_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
from .type_snippets import (
@@ -649,13 +669,48 @@ def delete_secret(
cast_to=NoneType,
)
+ def download_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> BinaryAPIResponse:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return self._get(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BinaryAPIResponse,
+ )
+
def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
+ only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
- stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -666,7 +721,7 @@ def explore(
) -> None:
"""
Args:
- stage: Which exploration stage to run
+ only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
extra_headers: Send extra headers
@@ -684,8 +739,8 @@ def explore(
body=maybe_transform(
{
"database_id": database_id,
+ "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
- "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -1186,6 +1241,50 @@ def update_table(
cast_to=UpdateTableResponse,
)
+ def upload_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ file: FileTypes,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ body = deepcopy_minimal({"file": file})
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return self._put(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ body=maybe_transform(body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class AsyncConnectorsResource(AsyncAPIResource):
@cached_property
@@ -1772,13 +1871,48 @@ async def delete_secret(
cast_to=NoneType,
)
+ async def download_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> AsyncBinaryAPIResponse:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return await self._get(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AsyncBinaryAPIResponse,
+ )
+
async def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
+ only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
- stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1789,7 +1923,7 @@ async def explore(
) -> None:
"""
Args:
- stage: Which exploration stage to run
+ only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
extra_headers: Send extra headers
@@ -1807,8 +1941,8 @@ async def explore(
body=await async_maybe_transform(
{
"database_id": database_id,
+ "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
- "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -2313,6 +2447,52 @@ async def update_table(
cast_to=UpdateTableResponse,
)
+ async def upload_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ file: FileTypes,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ body = deepcopy_minimal({"file": file})
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return await self._put(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ body=await async_maybe_transform(
+ body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams
+ ),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class ConnectorsResourceWithRawResponse:
def __init__(self, connectors: ConnectorsResource) -> None:
@@ -2342,6 +2522,10 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_raw_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = to_custom_raw_response_wrapper(
+ connectors.download_datahub_artifact,
+ BinaryAPIResponse,
+ )
self.explore = to_raw_response_wrapper(
connectors.explore,
)
@@ -2390,6 +2574,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_raw_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = to_raw_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithRawResponse:
@@ -2424,6 +2611,10 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_raw_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = async_to_custom_raw_response_wrapper(
+ connectors.download_datahub_artifact,
+ AsyncBinaryAPIResponse,
+ )
self.explore = async_to_raw_response_wrapper(
connectors.explore,
)
@@ -2472,6 +2663,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_raw_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = async_to_raw_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithRawResponse:
@@ -2506,6 +2700,10 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_streamed_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = to_custom_streamed_response_wrapper(
+ connectors.download_datahub_artifact,
+ StreamedBinaryAPIResponse,
+ )
self.explore = to_streamed_response_wrapper(
connectors.explore,
)
@@ -2554,6 +2752,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_streamed_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = to_streamed_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithStreamingResponse:
@@ -2588,6 +2789,10 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_streamed_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = async_to_custom_streamed_response_wrapper(
+ connectors.download_datahub_artifact,
+ AsyncStreamedBinaryAPIResponse,
+ )
self.explore = async_to_streamed_response_wrapper(
connectors.explore,
)
@@ -2636,6 +2841,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_streamed_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = async_to_streamed_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithStreamingResponse:
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index 377bd22a2..a67a9b441 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -56,7 +56,8 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
@@ -374,7 +375,8 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 99a5f6d3d..7c324f7e2 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -388,6 +388,9 @@
from .structure_enhance_relationship_response import (
StructureEnhanceRelationshipResponse as StructureEnhanceRelationshipResponse,
)
+from .connector_upload_datahub_artifact_params import (
+ ConnectorUploadDatahubArtifactParams as ConnectorUploadDatahubArtifactParams,
+)
from .chat_copy_node_output_by_code_hash_params import (
ChatCopyNodeOutputByCodeHashParams as ChatCopyNodeOutputByCodeHashParams,
)
diff --git a/src/structify/types/admin/job_list_params.py b/src/structify/types/admin/job_list_params.py
index cb290ca95..62f040440 100644
--- a/src/structify/types/admin/job_list_params.py
+++ b/src/structify/types/admin/job_list_params.py
@@ -9,7 +9,7 @@
class JobListParams(TypedDict, total=False):
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
limit: int
diff --git a/src/structify/types/admin/job_list_response.py b/src/structify/types/admin/job_list_response.py
index d494541eb..523c2310d 100644
--- a/src/structify/types/admin/job_list_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -26,6 +26,8 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
+ "ParametersStructuringInputDatahubIngestion",
+ "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -95,6 +97,18 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class ParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
+
+
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -107,8 +121,7 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -122,6 +135,7 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
+ ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -131,33 +145,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: ParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/chat_list_sessions_params.py b/src/structify/types/chat_list_sessions_params.py
index 2237d1bfb..ad0ab10d6 100644
--- a/src/structify/types/chat_list_sessions_params.py
+++ b/src/structify/types/chat_list_sessions_params.py
@@ -15,8 +15,5 @@ class ChatListSessionsParams(TypedDict, total=False):
limit: Optional[int]
"""Maximum number of sessions to return (default: 50)"""
- offset: Optional[int]
- """Number of sessions to skip (default: 0)"""
-
project_id: Optional[str]
"""Project ID to filter chat sessions"""
diff --git a/src/structify/types/connector_explore_params.py b/src/structify/types/connector_explore_params.py
index d4b23d4b9..4d94d5501 100644
--- a/src/structify/types/connector_explore_params.py
+++ b/src/structify/types/connector_explore_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import TypedDict
__all__ = ["ConnectorExploreParams"]
@@ -11,9 +11,9 @@
class ConnectorExploreParams(TypedDict, total=False):
database_id: Optional[str]
- schema_id: Optional[str]
+ only_do_datahub: Optional[bool]
+ """If true, run only DataHub ingestion without queuing Diego annotation jobs."""
- stage: Optional[Literal["both", "ingestion", "annotation"]]
- """Which exploration stage to run"""
+ schema_id: Optional[str]
table_id: Optional[str]
diff --git a/src/structify/types/connector_upload_datahub_artifact_params.py b/src/structify/types/connector_upload_datahub_artifact_params.py
new file mode 100644
index 000000000..09dfc77e7
--- /dev/null
+++ b/src/structify/types/connector_upload_datahub_artifact_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ConnectorUploadDatahubArtifactParams"]
+
+
+class ConnectorUploadDatahubArtifactParams(TypedDict, total=False):
+ connector_id: Required[str]
+
+ file: Required[FileTypes]
diff --git a/src/structify/types/entity_list_jobs_response.py b/src/structify/types/entity_list_jobs_response.py
index 1bcedcda2..31808d0c5 100644
--- a/src/structify/types/entity_list_jobs_response.py
+++ b/src/structify/types/entity_list_jobs_response.py
@@ -14,9 +14,7 @@ class EntityListJobsResponseItem(BaseModel):
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
max_steps_without_save: int
@@ -30,6 +28,8 @@ class EntityListJobsResponseItem(BaseModel):
user_id: str
+ dataset_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_cancel_response.py b/src/structify/types/job_cancel_response.py
index 640fcf079..75a5f4673 100644
--- a/src/structify/types/job_cancel_response.py
+++ b/src/structify/types/job_cancel_response.py
@@ -14,9 +14,7 @@ class JobCancelResponse(BaseModel):
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
max_steps_without_save: int
@@ -30,6 +28,8 @@ class JobCancelResponse(BaseModel):
user_id: str
+ dataset_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_event_body.py b/src/structify/types/job_event_body.py
index 85f1e3f9f..8820bff9d 100644
--- a/src/structify/types/job_event_body.py
+++ b/src/structify/types/job_event_body.py
@@ -24,6 +24,7 @@
"DatahubDatabasesCreated",
"DatahubSchemasCreated",
"DatahubTablesProcessed",
+ "DatahubAnnotationsQueued",
"DatahubEmbeddingBatch",
"ViewedPdfPage",
]
@@ -167,9 +168,19 @@ class DatahubTablesProcessed(BaseModel):
tables_failed: int
+ tables_removed: int
+
tables_updated: int
+class DatahubAnnotationsQueued(BaseModel):
+ diff_annotations_queued: int
+
+ event_type: Literal["datahub_annotations_queued"]
+
+ full_annotations_queued: int
+
+
class DatahubEmbeddingBatch(BaseModel):
batch_num: int
@@ -203,6 +214,7 @@ class ViewedPdfPage(BaseModel):
DatahubDatabasesCreated,
DatahubSchemasCreated,
DatahubTablesProcessed,
+ DatahubAnnotationsQueued,
DatahubEmbeddingBatch,
ViewedPdfPage,
],
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
index c51109bea..82961dcbf 100644
--- a/src/structify/types/job_get_response.py
+++ b/src/structify/types/job_get_response.py
@@ -32,6 +32,8 @@
"InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"InfoParametersStructuringInputScrapeURL",
"InfoParametersStructuringInputScrapeURLScrapeURL",
+ "InfoParametersStructuringInputDatahubIngestion",
+ "InfoParametersStructuringInputDatahubIngestionDatahubIngestion",
"InfoParametersStructuringInputConnectorExploration",
"InfoParametersStructuringInputConnectorExplorationConnectorExploration",
"Saved",
@@ -135,6 +137,20 @@ class InfoParametersStructuringInputScrapeURL(BaseModel):
scrape_url: InfoParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class InfoParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class InfoParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: InfoParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(
+ alias="DatahubIngestion"
+ )
+
+
class InfoParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -147,8 +163,7 @@ class InfoParametersStructuringInputConnectorExplorationConnectorExploration(Bas
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class InfoParametersStructuringInputConnectorExploration(BaseModel):
@@ -162,6 +177,7 @@ class InfoParametersStructuringInputConnectorExploration(BaseModel):
InfoParametersStructuringInputTransformationPrompt,
InfoParametersStructuringInputScrapeFromURLProperty,
InfoParametersStructuringInputScrapeURL,
+ InfoParametersStructuringInputDatahubIngestion,
InfoParametersStructuringInputConnectorExploration,
]
@@ -171,33 +187,33 @@ class InfoParameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: InfoParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class Info(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[InfoParameters] = None
diff --git a/src/structify/types/job_list_params.py b/src/structify/types/job_list_params.py
index e13064899..d93b17726 100644
--- a/src/structify/types/job_list_params.py
+++ b/src/structify/types/job_list_params.py
@@ -15,7 +15,7 @@ class JobListParams(TypedDict, total=False):
dataset: Optional[str]
"""Dataset name to optionally filter jobs by"""
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
"""Type of job to optionally filter jobs by"""
limit: int
diff --git a/src/structify/types/job_list_response.py b/src/structify/types/job_list_response.py
index d6567a058..122fbeb06 100644
--- a/src/structify/types/job_list_response.py
+++ b/src/structify/types/job_list_response.py
@@ -26,6 +26,8 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
+ "ParametersStructuringInputDatahubIngestion",
+ "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -95,6 +97,18 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class ParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
+
+
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -107,8 +121,7 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -122,6 +135,7 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
+ ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -131,33 +145,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: ParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/list_chat_sessions_response.py b/src/structify/types/list_chat_sessions_response.py
index edc5395de..a62d7c050 100644
--- a/src/structify/types/list_chat_sessions_response.py
+++ b/src/structify/types/list_chat_sessions_response.py
@@ -44,6 +44,3 @@ class ListChatSessionsResponse(BaseModel):
"""Response for listing chat sessions"""
sessions: List[Session]
-
- total_count: int
- """Total number of chat sessions matching the query (for pagination)"""
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 384ef17ae..cd70a4cc2 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -827,7 +827,6 @@ def test_method_list_sessions_with_all_params(self, client: Structify) -> None:
chat = client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
- offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ListChatSessionsResponse, chat, path=["response"])
@@ -2353,7 +2352,6 @@ async def test_method_list_sessions_with_all_params(self, async_client: AsyncStr
chat = await async_client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
- offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ListChatSessionsResponse, chat, path=["response"])
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index d07a07258..ac23c3e9c 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -5,7 +5,9 @@
import os
from typing import Any, cast
+import httpx
import pytest
+from respx import MockRouter
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
@@ -28,6 +30,12 @@
ConnectorListWithSnippetsResponse,
ConnectorGetClarificationRequestsResponse,
)
+from structify._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
from structify.pagination import SyncJobsList, AsyncJobsList
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -734,6 +742,72 @@ def test_path_params_delete_secret(self, client: Structify) -> None:
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ connector = client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert connector.is_closed is True
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert connector.json() == {"foo": "bar"}
+ assert isinstance(connector, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ with client.connectors.with_streaming_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as connector:
+ assert not connector.is_closed
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, StreamedBinaryAPIResponse)
+
+ assert cast(Any, connector.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_path_params_download_datahub_artifact(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ client.connectors.with_raw_response.download_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
@@ -746,8 +820,8 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -1337,6 +1411,59 @@ def test_path_params_update_table(self, client: Structify) -> None:
table_id="",
)
+ @parametrize
+ def test_method_upload_datahub_artifact(self, client: Structify) -> None:
+ connector = client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+ assert connector is None
+
+ @parametrize
+ def test_raw_response_upload_datahub_artifact(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert connector is None
+
+ @parametrize
+ def test_streaming_response_upload_datahub_artifact(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert connector is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ file=b"Example data",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
class TestAsyncConnectors:
parametrize = pytest.mark.parametrize(
@@ -2041,6 +2168,76 @@ async def test_path_params_delete_secret(self, async_client: AsyncStructify) ->
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_download_datahub_artifact(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = await async_client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_raw_response_download_datahub_artifact(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ connector = await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert connector.is_closed is True
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert await connector.json() == {"foo": "bar"}
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_streaming_response_download_datahub_artifact(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ async with async_client.connectors.with_streaming_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as connector:
+ assert not connector.is_closed
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncStreamedBinaryAPIResponse)
+
+ assert cast(Any, connector.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_path_params_download_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
@@ -2053,8 +2250,8 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -2643,3 +2840,56 @@ async def test_path_params_update_table(self, async_client: AsyncStructify) -> N
await async_client.connectors.with_raw_response.update_table(
table_id="",
)
+
+ @parametrize
+ async def test_method_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+ assert connector is None
+
+ @parametrize
+ async def test_raw_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert connector is None
+
+ @parametrize
+ async def test_streaming_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert connector is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ file=b"Example data",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
From 9c9b785cb118b656322d0614e6602b1f64f25c9b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Mar 2026 19:59:40 +0000
Subject: [PATCH 069/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 -
src/structify/resources/admin/jobs.py | 6 +-
.../resources/connectors/connectors.py | 226 +---------------
src/structify/resources/jobs.py | 6 +-
src/structify/types/__init__.py | 3 -
src/structify/types/admin/job_list_params.py | 2 +-
.../types/admin/job_list_response.py | 38 +--
.../types/connector_explore_params.py | 8 +-
...onnector_upload_datahub_artifact_params.py | 15 --
.../types/entity_list_jobs_response.py | 6 +-
src/structify/types/job_cancel_response.py | 6 +-
src/structify/types/job_event_body.py | 12 -
src/structify/types/job_get_response.py | 40 +--
src/structify/types/job_list_params.py | 2 +-
src/structify/types/job_list_response.py | 38 +--
src/structify/types/viz_figure_kind.py | 2 +-
tests/api_resources/test_connectors.py | 254 +-----------------
18 files changed, 68 insertions(+), 606 deletions(-)
delete mode 100644 src/structify/types/connector_upload_datahub_artifact_params.py
diff --git a/.stats.yml b/.stats.yml
index 839481225..21d5bb8a5 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 248
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-7e3bb1c810ee9c928220474b3b5d423d00eb5eff978c24d879a9d8947ccaf8ca.yml
-openapi_spec_hash: 795960913b5f4da29f171b45cfe19824
-config_hash: ab5291af3bd5919aecf1f8e41eb363b8
+configured_endpoints: 246
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-981afe524384e76d9ce167ba960b665362bc8f95925aee3896d49ea6bef4f7e9.yml
+openapi_spec_hash: cc09e6dafdfe4cc91e9c81671067a44b
+config_hash: 6c301c61ddc3ede8e6bd85d2ef513747
diff --git a/api.md b/api.md
index 4547079d0..5cf65a761 100644
--- a/api.md
+++ b/api.md
@@ -735,7 +735,6 @@ Methods:
- client.connectors.create_secret(connector_id, \*\*params) -> None
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
-- client.connectors.download_datahub_artifact(kind, \*, connector_id) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
@@ -752,7 +751,6 @@ Methods:
- client.connectors.summaries(\*\*params) -> ConnectorSummariesResponse
- client.connectors.update_column(column_id, \*\*params) -> None
- client.connectors.update_table(table_id, \*\*params) -> UpdateTableResponse
-- client.connectors.upload_datahub_artifact(kind, \*, connector_id, \*\*params) -> None
## TypeSnippets
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index c95c5fb48..16f81550e 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -52,8 +52,7 @@ def with_streaming_response(self) -> JobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
@@ -183,8 +182,7 @@ def with_streaming_response(self) -> AsyncJobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 579013d49..6a2301e83 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Dict, Mapping, Optional, cast
+from typing import Any, Dict, Optional, cast
from typing_extensions import Literal, overload
import httpx
@@ -21,36 +21,16 @@
connector_add_schema_object_params,
connector_get_explorer_chat_params,
connector_delete_schema_object_params,
- connector_upload_datahub_artifact_params,
)
-from ..._types import (
- Body,
- Omit,
- Query,
- Headers,
- NoneType,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- omit,
- not_given,
-)
-from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
+from ..._utils import required_args, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
- BinaryAPIResponse,
- AsyncBinaryAPIResponse,
- StreamedBinaryAPIResponse,
- AsyncStreamedBinaryAPIResponse,
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
- to_custom_raw_response_wrapper,
async_to_streamed_response_wrapper,
- to_custom_streamed_response_wrapper,
- async_to_custom_raw_response_wrapper,
- async_to_custom_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
from .type_snippets import (
@@ -669,48 +649,13 @@ def delete_secret(
cast_to=NoneType,
)
- def download_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- # 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,
- ) -> BinaryAPIResponse:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
- return self._get(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BinaryAPIResponse,
- )
-
def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
- only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
+ stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -721,7 +666,7 @@ def explore(
) -> None:
"""
Args:
- only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
+ stage: Which exploration stage to run
extra_headers: Send extra headers
@@ -739,8 +684,8 @@ def explore(
body=maybe_transform(
{
"database_id": database_id,
- "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
+ "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -1241,50 +1186,6 @@ def update_table(
cast_to=UpdateTableResponse,
)
- def upload_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- file: FileTypes,
- # 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:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- body = deepcopy_minimal({"file": file})
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers["Content-Type"] = "multipart/form-data"
- return self._put(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- body=maybe_transform(body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
class AsyncConnectorsResource(AsyncAPIResource):
@cached_property
@@ -1871,48 +1772,13 @@ async def delete_secret(
cast_to=NoneType,
)
- async def download_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- # 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,
- ) -> AsyncBinaryAPIResponse:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
- return await self._get(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AsyncBinaryAPIResponse,
- )
-
async def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
- only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
+ stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1923,7 +1789,7 @@ async def explore(
) -> None:
"""
Args:
- only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
+ stage: Which exploration stage to run
extra_headers: Send extra headers
@@ -1941,8 +1807,8 @@ async def explore(
body=await async_maybe_transform(
{
"database_id": database_id,
- "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
+ "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -2447,52 +2313,6 @@ async def update_table(
cast_to=UpdateTableResponse,
)
- async def upload_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- file: FileTypes,
- # 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:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- body = deepcopy_minimal({"file": file})
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers["Content-Type"] = "multipart/form-data"
- return await self._put(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- body=await async_maybe_transform(
- body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams
- ),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
class ConnectorsResourceWithRawResponse:
def __init__(self, connectors: ConnectorsResource) -> None:
@@ -2522,10 +2342,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_raw_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = to_custom_raw_response_wrapper(
- connectors.download_datahub_artifact,
- BinaryAPIResponse,
- )
self.explore = to_raw_response_wrapper(
connectors.explore,
)
@@ -2574,9 +2390,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_raw_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = to_raw_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithRawResponse:
@@ -2611,10 +2424,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_raw_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = async_to_custom_raw_response_wrapper(
- connectors.download_datahub_artifact,
- AsyncBinaryAPIResponse,
- )
self.explore = async_to_raw_response_wrapper(
connectors.explore,
)
@@ -2663,9 +2472,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_raw_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = async_to_raw_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithRawResponse:
@@ -2700,10 +2506,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_streamed_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = to_custom_streamed_response_wrapper(
- connectors.download_datahub_artifact,
- StreamedBinaryAPIResponse,
- )
self.explore = to_streamed_response_wrapper(
connectors.explore,
)
@@ -2752,9 +2554,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_streamed_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = to_streamed_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithStreamingResponse:
@@ -2789,10 +2588,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_streamed_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = async_to_custom_streamed_response_wrapper(
- connectors.download_datahub_artifact,
- AsyncStreamedBinaryAPIResponse,
- )
self.explore = async_to_streamed_response_wrapper(
connectors.explore,
)
@@ -2841,9 +2636,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_streamed_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = async_to_streamed_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithStreamingResponse:
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index a67a9b441..377bd22a2 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -56,8 +56,7 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
@@ -375,8 +374,7 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 7c324f7e2..99a5f6d3d 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -388,9 +388,6 @@
from .structure_enhance_relationship_response import (
StructureEnhanceRelationshipResponse as StructureEnhanceRelationshipResponse,
)
-from .connector_upload_datahub_artifact_params import (
- ConnectorUploadDatahubArtifactParams as ConnectorUploadDatahubArtifactParams,
-)
from .chat_copy_node_output_by_code_hash_params import (
ChatCopyNodeOutputByCodeHashParams as ChatCopyNodeOutputByCodeHashParams,
)
diff --git a/src/structify/types/admin/job_list_params.py b/src/structify/types/admin/job_list_params.py
index 62f040440..cb290ca95 100644
--- a/src/structify/types/admin/job_list_params.py
+++ b/src/structify/types/admin/job_list_params.py
@@ -9,7 +9,7 @@
class JobListParams(TypedDict, total=False):
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
limit: int
diff --git a/src/structify/types/admin/job_list_response.py b/src/structify/types/admin/job_list_response.py
index 523c2310d..d494541eb 100644
--- a/src/structify/types/admin/job_list_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -26,8 +26,6 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
- "ParametersStructuringInputDatahubIngestion",
- "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -97,18 +95,6 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
-class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
- connector_id: str
-
- exploration_run_id: str
-
- only_do_datahub: bool
-
-
-class ParametersStructuringInputDatahubIngestion(BaseModel):
- datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
-
-
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -121,7 +107,8 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- strategy: Literal["full", "diff"]
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -135,7 +122,6 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
- ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -145,33 +131,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- structuring_input: ParametersStructuringInput
-
- instructions: Optional[str] = None
-
- model: Optional[str] = None
-
- seeded_kg: Optional[KnowledgeGraph] = None
+ seeded_kg: KnowledgeGraph
"""
Knowledge graph info structured to deserialize and display in the same format
that the LLM outputs. Also the first representation of an LLM output in the
pipeline from raw tool output to being merged into a DB
"""
+ structuring_input: ParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
- dataset_id: Optional[str] = None
-
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/connector_explore_params.py b/src/structify/types/connector_explore_params.py
index 4d94d5501..d4b23d4b9 100644
--- a/src/structify/types/connector_explore_params.py
+++ b/src/structify/types/connector_explore_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["ConnectorExploreParams"]
@@ -11,9 +11,9 @@
class ConnectorExploreParams(TypedDict, total=False):
database_id: Optional[str]
- only_do_datahub: Optional[bool]
- """If true, run only DataHub ingestion without queuing Diego annotation jobs."""
-
schema_id: Optional[str]
+ stage: Optional[Literal["both", "ingestion", "annotation"]]
+ """Which exploration stage to run"""
+
table_id: Optional[str]
diff --git a/src/structify/types/connector_upload_datahub_artifact_params.py b/src/structify/types/connector_upload_datahub_artifact_params.py
deleted file mode 100644
index 09dfc77e7..000000000
--- a/src/structify/types/connector_upload_datahub_artifact_params.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ConnectorUploadDatahubArtifactParams"]
-
-
-class ConnectorUploadDatahubArtifactParams(TypedDict, total=False):
- connector_id: Required[str]
-
- file: Required[FileTypes]
diff --git a/src/structify/types/entity_list_jobs_response.py b/src/structify/types/entity_list_jobs_response.py
index 31808d0c5..1bcedcda2 100644
--- a/src/structify/types/entity_list_jobs_response.py
+++ b/src/structify/types/entity_list_jobs_response.py
@@ -14,7 +14,9 @@ class EntityListJobsResponseItem(BaseModel):
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
max_steps_without_save: int
@@ -28,8 +30,6 @@ class EntityListJobsResponseItem(BaseModel):
user_id: str
- dataset_id: Optional[str] = None
-
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_cancel_response.py b/src/structify/types/job_cancel_response.py
index 75a5f4673..640fcf079 100644
--- a/src/structify/types/job_cancel_response.py
+++ b/src/structify/types/job_cancel_response.py
@@ -14,7 +14,9 @@ class JobCancelResponse(BaseModel):
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
max_steps_without_save: int
@@ -28,8 +30,6 @@ class JobCancelResponse(BaseModel):
user_id: str
- dataset_id: Optional[str] = None
-
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_event_body.py b/src/structify/types/job_event_body.py
index 8820bff9d..85f1e3f9f 100644
--- a/src/structify/types/job_event_body.py
+++ b/src/structify/types/job_event_body.py
@@ -24,7 +24,6 @@
"DatahubDatabasesCreated",
"DatahubSchemasCreated",
"DatahubTablesProcessed",
- "DatahubAnnotationsQueued",
"DatahubEmbeddingBatch",
"ViewedPdfPage",
]
@@ -168,19 +167,9 @@ class DatahubTablesProcessed(BaseModel):
tables_failed: int
- tables_removed: int
-
tables_updated: int
-class DatahubAnnotationsQueued(BaseModel):
- diff_annotations_queued: int
-
- event_type: Literal["datahub_annotations_queued"]
-
- full_annotations_queued: int
-
-
class DatahubEmbeddingBatch(BaseModel):
batch_num: int
@@ -214,7 +203,6 @@ class ViewedPdfPage(BaseModel):
DatahubDatabasesCreated,
DatahubSchemasCreated,
DatahubTablesProcessed,
- DatahubAnnotationsQueued,
DatahubEmbeddingBatch,
ViewedPdfPage,
],
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
index 82961dcbf..c51109bea 100644
--- a/src/structify/types/job_get_response.py
+++ b/src/structify/types/job_get_response.py
@@ -32,8 +32,6 @@
"InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"InfoParametersStructuringInputScrapeURL",
"InfoParametersStructuringInputScrapeURLScrapeURL",
- "InfoParametersStructuringInputDatahubIngestion",
- "InfoParametersStructuringInputDatahubIngestionDatahubIngestion",
"InfoParametersStructuringInputConnectorExploration",
"InfoParametersStructuringInputConnectorExplorationConnectorExploration",
"Saved",
@@ -137,20 +135,6 @@ class InfoParametersStructuringInputScrapeURL(BaseModel):
scrape_url: InfoParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
-class InfoParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
- connector_id: str
-
- exploration_run_id: str
-
- only_do_datahub: bool
-
-
-class InfoParametersStructuringInputDatahubIngestion(BaseModel):
- datahub_ingestion: InfoParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(
- alias="DatahubIngestion"
- )
-
-
class InfoParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -163,7 +147,8 @@ class InfoParametersStructuringInputConnectorExplorationConnectorExploration(Bas
exploration_run_id: str
- strategy: Literal["full", "diff"]
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
class InfoParametersStructuringInputConnectorExploration(BaseModel):
@@ -177,7 +162,6 @@ class InfoParametersStructuringInputConnectorExploration(BaseModel):
InfoParametersStructuringInputTransformationPrompt,
InfoParametersStructuringInputScrapeFromURLProperty,
InfoParametersStructuringInputScrapeURL,
- InfoParametersStructuringInputDatahubIngestion,
InfoParametersStructuringInputConnectorExploration,
]
@@ -187,33 +171,33 @@ class InfoParameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- structuring_input: InfoParametersStructuringInput
-
- instructions: Optional[str] = None
-
- model: Optional[str] = None
-
- seeded_kg: Optional[KnowledgeGraph] = None
+ seeded_kg: KnowledgeGraph
"""
Knowledge graph info structured to deserialize and display in the same format
that the LLM outputs. Also the first representation of an LLM output in the
pipeline from raw tool output to being merged into a DB
"""
+ structuring_input: InfoParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
class Info(BaseModel):
id: str
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
- dataset_id: Optional[str] = None
-
message: Optional[str] = None
parameters: Optional[InfoParameters] = None
diff --git a/src/structify/types/job_list_params.py b/src/structify/types/job_list_params.py
index d93b17726..e13064899 100644
--- a/src/structify/types/job_list_params.py
+++ b/src/structify/types/job_list_params.py
@@ -15,7 +15,7 @@ class JobListParams(TypedDict, total=False):
dataset: Optional[str]
"""Dataset name to optionally filter jobs by"""
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
"""Type of job to optionally filter jobs by"""
limit: int
diff --git a/src/structify/types/job_list_response.py b/src/structify/types/job_list_response.py
index 122fbeb06..d6567a058 100644
--- a/src/structify/types/job_list_response.py
+++ b/src/structify/types/job_list_response.py
@@ -26,8 +26,6 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
- "ParametersStructuringInputDatahubIngestion",
- "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -97,18 +95,6 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
-class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
- connector_id: str
-
- exploration_run_id: str
-
- only_do_datahub: bool
-
-
-class ParametersStructuringInputDatahubIngestion(BaseModel):
- datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
-
-
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -121,7 +107,8 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- strategy: Literal["full", "diff"]
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -135,7 +122,6 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
- ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -145,33 +131,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- structuring_input: ParametersStructuringInput
-
- instructions: Optional[str] = None
-
- model: Optional[str] = None
-
- seeded_kg: Optional[KnowledgeGraph] = None
+ seeded_kg: KnowledgeGraph
"""
Knowledge graph info structured to deserialize and display in the same format
that the LLM outputs. Also the first representation of an LLM output in the
pipeline from raw tool output to being merged into a DB
"""
+ structuring_input: ParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
- dataset_id: Optional[str] = None
-
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/viz_figure_kind.py b/src/structify/types/viz_figure_kind.py
index 32d895e43..e70d16356 100644
--- a/src/structify/types/viz_figure_kind.py
+++ b/src/structify/types/viz_figure_kind.py
@@ -4,4 +4,4 @@
__all__ = ["VizFigureKind"]
-VizFigureKind: TypeAlias = Literal["js", "vega-lite"]
+VizFigureKind: TypeAlias = Literal["js", "vega-lite", "data-table"]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index ac23c3e9c..d07a07258 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -5,9 +5,7 @@
import os
from typing import Any, cast
-import httpx
import pytest
-from respx import MockRouter
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
@@ -30,12 +28,6 @@
ConnectorListWithSnippetsResponse,
ConnectorGetClarificationRequestsResponse,
)
-from structify._response import (
- BinaryAPIResponse,
- AsyncBinaryAPIResponse,
- StreamedBinaryAPIResponse,
- AsyncStreamedBinaryAPIResponse,
-)
from structify.pagination import SyncJobsList, AsyncJobsList
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -742,72 +734,6 @@ def test_path_params_delete_secret(self, client: Structify) -> None:
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_method_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- connector = client.connectors.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert connector.is_closed
- assert connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, BinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_raw_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
-
- connector = client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert connector.is_closed is True
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
- assert connector.json() == {"foo": "bar"}
- assert isinstance(connector, BinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_streaming_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- with client.connectors.with_streaming_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as connector:
- assert not connector.is_closed
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
-
- assert connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, StreamedBinaryAPIResponse)
-
- assert cast(Any, connector.is_closed) is True
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_path_params_download_datahub_artifact(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- client.connectors.with_raw_response.download_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
@parametrize
def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
@@ -820,8 +746,8 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -1411,59 +1337,6 @@ def test_path_params_update_table(self, client: Structify) -> None:
table_id="",
)
- @parametrize
- def test_method_upload_datahub_artifact(self, client: Structify) -> None:
- connector = client.connectors.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
- assert connector is None
-
- @parametrize
- def test_raw_response_upload_datahub_artifact(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- connector = response.parse()
- assert connector is None
-
- @parametrize
- def test_streaming_response_upload_datahub_artifact(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- connector = response.parse()
- assert connector is None
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="",
- file=b"Example data",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- client.connectors.with_raw_response.upload_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
-
class TestAsyncConnectors:
parametrize = pytest.mark.parametrize(
@@ -2168,76 +2041,6 @@ async def test_path_params_delete_secret(self, async_client: AsyncStructify) ->
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_method_download_datahub_artifact(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- connector = await async_client.connectors.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert connector.is_closed
- assert await connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, AsyncBinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_raw_response_download_datahub_artifact(
- self, async_client: AsyncStructify, respx_mock: MockRouter
- ) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
-
- connector = await async_client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert connector.is_closed is True
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
- assert await connector.json() == {"foo": "bar"}
- assert isinstance(connector, AsyncBinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_streaming_response_download_datahub_artifact(
- self, async_client: AsyncStructify, respx_mock: MockRouter
- ) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- async with async_client.connectors.with_streaming_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as connector:
- assert not connector.is_closed
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
-
- assert await connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, AsyncStreamedBinaryAPIResponse)
-
- assert cast(Any, connector.is_closed) is True
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_path_params_download_datahub_artifact(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- await async_client.connectors.with_raw_response.download_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
@parametrize
async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
@@ -2250,8 +2053,8 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -2840,56 +2643,3 @@ async def test_path_params_update_table(self, async_client: AsyncStructify) -> N
await async_client.connectors.with_raw_response.update_table(
table_id="",
)
-
- @parametrize
- async def test_method_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
- assert connector is None
-
- @parametrize
- async def test_raw_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- connector = await response.parse()
- assert connector is None
-
- @parametrize
- async def test_streaming_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- connector = await response.parse()
- assert connector is None
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="",
- file=b"Example data",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- await async_client.connectors.with_raw_response.upload_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
From 4ec4f4f2c97687d23575d9b235ee1a3aefef648d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Mar 2026 21:24:08 +0000
Subject: [PATCH 070/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/connector_catalog/admin.py | 8 ++++++++
.../connector_catalog/admin_create_catalog_params.py | 2 ++
.../connector_catalog/admin_update_catalog_params.py | 2 ++
.../types/connector_catalog/connector_catalog.py | 2 ++
tests/api_resources/connector_catalog/test_admin.py | 4 ++++
6 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 21d5bb8a5..fe38c1c2a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 246
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-981afe524384e76d9ce167ba960b665362bc8f95925aee3896d49ea6bef4f7e9.yml
-openapi_spec_hash: cc09e6dafdfe4cc91e9c81671067a44b
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-e5a5706ac1f324d2693e3648b80bb9ebdc7d5b680847df6e6a7f80e758640f8d.yml
+openapi_spec_hash: d67590f1d68a6b0a2db2526b3031a8e4
config_hash: 6c301c61ddc3ede8e6bd85d2ef513747
diff --git a/src/structify/resources/connector_catalog/admin.py b/src/structify/resources/connector_catalog/admin.py
index a2e14c043..a9e462bae 100644
--- a/src/structify/resources/connector_catalog/admin.py
+++ b/src/structify/resources/connector_catalog/admin.py
@@ -201,6 +201,7 @@ def create_catalog(
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
enterprise_only: bool | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -230,6 +231,7 @@ def create_catalog(
"categories": categories,
"description": description,
"enterprise_only": enterprise_only,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -541,6 +543,7 @@ def update_catalog(
description: Optional[str] | Omit = omit,
enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -571,6 +574,7 @@ def update_catalog(
"description": description,
"enterprise_only": enterprise_only,
"name": name,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_update_catalog_params.AdminUpdateCatalogParams,
@@ -863,6 +867,7 @@ async def create_catalog(
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
enterprise_only: bool | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -892,6 +897,7 @@ async def create_catalog(
"categories": categories,
"description": description,
"enterprise_only": enterprise_only,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -1203,6 +1209,7 @@ async def update_catalog(
description: Optional[str] | Omit = omit,
enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -1233,6 +1240,7 @@ async def update_catalog(
"description": description,
"enterprise_only": enterprise_only,
"name": name,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_update_catalog_params.AdminUpdateCatalogParams,
diff --git a/src/structify/types/connector_catalog/admin_create_catalog_params.py b/src/structify/types/connector_catalog/admin_create_catalog_params.py
index adfb768f8..98662c009 100644
--- a/src/structify/types/connector_catalog/admin_create_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_create_catalog_params.py
@@ -21,4 +21,6 @@ class AdminCreateCatalogParams(TypedDict, total=False):
enterprise_only: bool
+ onboarding_priority: Optional[int]
+
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/admin_update_catalog_params.py b/src/structify/types/connector_catalog/admin_update_catalog_params.py
index 784ae5ece..23d639c71 100644
--- a/src/structify/types/connector_catalog/admin_update_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_update_catalog_params.py
@@ -19,4 +19,6 @@ class AdminUpdateCatalogParams(TypedDict, total=False):
name: Optional[str]
+ onboarding_priority: Optional[int]
+
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/connector_catalog.py b/src/structify/types/connector_catalog/connector_catalog.py
index c414d1f49..8f0b9eb5e 100644
--- a/src/structify/types/connector_catalog/connector_catalog.py
+++ b/src/structify/types/connector_catalog/connector_catalog.py
@@ -25,4 +25,6 @@ class ConnectorCatalog(BaseModel):
description: Optional[str] = None
+ onboarding_priority: Optional[int] = None
+
priority: Optional[int] = None
diff --git a/tests/api_resources/connector_catalog/test_admin.py b/tests/api_resources/connector_catalog/test_admin.py
index 224b67a19..10cb267d0 100644
--- a/tests/api_resources/connector_catalog/test_admin.py
+++ b/tests/api_resources/connector_catalog/test_admin.py
@@ -195,6 +195,7 @@ def test_method_create_catalog_with_all_params(self, client: Structify) -> None:
categories=["string"],
description="description",
enterprise_only=True,
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -561,6 +562,7 @@ def test_method_update_catalog_with_all_params(self, client: Structify) -> None:
description="description",
enterprise_only=True,
name="name",
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -915,6 +917,7 @@ async def test_method_create_catalog_with_all_params(self, async_client: AsyncSt
categories=["string"],
description="description",
enterprise_only=True,
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -1281,6 +1284,7 @@ async def test_method_update_catalog_with_all_params(self, async_client: AsyncSt
description="description",
enterprise_only=True,
name="name",
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
From 9586986c012ee305ab90de33c7d74ea715becee2 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 19 Mar 2026 23:22:45 +0000
Subject: [PATCH 071/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 +
src/structify/resources/admin/jobs.py | 6 +-
.../resources/connector_catalog/admin.py | 8 -
.../resources/connectors/connectors.py | 226 +++++++++++++++-
src/structify/resources/jobs.py | 6 +-
src/structify/types/__init__.py | 3 +
src/structify/types/admin/job_list_params.py | 2 +-
.../types/admin/job_list_response.py | 38 ++-
.../admin_create_catalog_params.py | 2 -
.../admin_update_catalog_params.py | 2 -
.../connector_catalog/connector_catalog.py | 2 -
.../types/connector_explore_params.py | 8 +-
...onnector_upload_datahub_artifact_params.py | 15 ++
.../types/entity_list_jobs_response.py | 6 +-
src/structify/types/job_cancel_response.py | 6 +-
src/structify/types/job_event_body.py | 12 +
src/structify/types/job_get_response.py | 40 ++-
src/structify/types/job_list_params.py | 2 +-
src/structify/types/job_list_response.py | 38 ++-
.../connector_catalog/test_admin.py | 4 -
tests/api_resources/test_connectors.py | 254 +++++++++++++++++-
22 files changed, 605 insertions(+), 85 deletions(-)
create mode 100644 src/structify/types/connector_upload_datahub_artifact_params.py
diff --git a/.stats.yml b/.stats.yml
index fe38c1c2a..c880f0a4c 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 246
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-e5a5706ac1f324d2693e3648b80bb9ebdc7d5b680847df6e6a7f80e758640f8d.yml
-openapi_spec_hash: d67590f1d68a6b0a2db2526b3031a8e4
-config_hash: 6c301c61ddc3ede8e6bd85d2ef513747
+configured_endpoints: 248
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-738b8753bad183bc3ea4c227cb700d6d4716b9e064abf87c57f3f8e713b21fee.yml
+openapi_spec_hash: 112bc21dc51b40e05ffb37273818c1ce
+config_hash: ab5291af3bd5919aecf1f8e41eb363b8
diff --git a/api.md b/api.md
index 5cf65a761..4547079d0 100644
--- a/api.md
+++ b/api.md
@@ -735,6 +735,7 @@ Methods:
- client.connectors.create_secret(connector_id, \*\*params) -> None
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
+- client.connectors.download_datahub_artifact(kind, \*, connector_id) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
@@ -751,6 +752,7 @@ Methods:
- client.connectors.summaries(\*\*params) -> ConnectorSummariesResponse
- client.connectors.update_column(column_id, \*\*params) -> None
- client.connectors.update_table(table_id, \*\*params) -> UpdateTableResponse
+- client.connectors.upload_datahub_artifact(kind, \*, connector_id, \*\*params) -> None
## TypeSnippets
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index 16f81550e..c95c5fb48 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -52,7 +52,8 @@ def with_streaming_response(self) -> JobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
@@ -182,7 +183,8 @@ def with_streaming_response(self) -> AsyncJobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
diff --git a/src/structify/resources/connector_catalog/admin.py b/src/structify/resources/connector_catalog/admin.py
index a9e462bae..a2e14c043 100644
--- a/src/structify/resources/connector_catalog/admin.py
+++ b/src/structify/resources/connector_catalog/admin.py
@@ -201,7 +201,6 @@ def create_catalog(
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
enterprise_only: bool | Omit = omit,
- onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -231,7 +230,6 @@ def create_catalog(
"categories": categories,
"description": description,
"enterprise_only": enterprise_only,
- "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -543,7 +541,6 @@ def update_catalog(
description: Optional[str] | Omit = omit,
enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
- onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -574,7 +571,6 @@ def update_catalog(
"description": description,
"enterprise_only": enterprise_only,
"name": name,
- "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_update_catalog_params.AdminUpdateCatalogParams,
@@ -867,7 +863,6 @@ async def create_catalog(
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
enterprise_only: bool | Omit = omit,
- onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -897,7 +892,6 @@ async def create_catalog(
"categories": categories,
"description": description,
"enterprise_only": enterprise_only,
- "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -1209,7 +1203,6 @@ async def update_catalog(
description: Optional[str] | Omit = omit,
enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
- onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -1240,7 +1233,6 @@ async def update_catalog(
"description": description,
"enterprise_only": enterprise_only,
"name": name,
- "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_update_catalog_params.AdminUpdateCatalogParams,
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 6a2301e83..579013d49 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Dict, Optional, cast
+from typing import Any, Dict, Mapping, Optional, cast
from typing_extensions import Literal, overload
import httpx
@@ -21,16 +21,36 @@
connector_add_schema_object_params,
connector_get_explorer_chat_params,
connector_delete_schema_object_params,
+ connector_upload_datahub_artifact_params,
)
-from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import required_args, maybe_transform, async_maybe_transform
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NoneType,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
+ to_custom_raw_response_wrapper,
async_to_streamed_response_wrapper,
+ to_custom_streamed_response_wrapper,
+ async_to_custom_raw_response_wrapper,
+ async_to_custom_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
from .type_snippets import (
@@ -649,13 +669,48 @@ def delete_secret(
cast_to=NoneType,
)
+ def download_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> BinaryAPIResponse:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return self._get(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BinaryAPIResponse,
+ )
+
def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
+ only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
- stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -666,7 +721,7 @@ def explore(
) -> None:
"""
Args:
- stage: Which exploration stage to run
+ only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
extra_headers: Send extra headers
@@ -684,8 +739,8 @@ def explore(
body=maybe_transform(
{
"database_id": database_id,
+ "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
- "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -1186,6 +1241,50 @@ def update_table(
cast_to=UpdateTableResponse,
)
+ def upload_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ file: FileTypes,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ body = deepcopy_minimal({"file": file})
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return self._put(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ body=maybe_transform(body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class AsyncConnectorsResource(AsyncAPIResource):
@cached_property
@@ -1772,13 +1871,48 @@ async def delete_secret(
cast_to=NoneType,
)
+ async def download_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> AsyncBinaryAPIResponse:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return await self._get(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AsyncBinaryAPIResponse,
+ )
+
async def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
+ only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
- stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1789,7 +1923,7 @@ async def explore(
) -> None:
"""
Args:
- stage: Which exploration stage to run
+ only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
extra_headers: Send extra headers
@@ -1807,8 +1941,8 @@ async def explore(
body=await async_maybe_transform(
{
"database_id": database_id,
+ "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
- "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -2313,6 +2447,52 @@ async def update_table(
cast_to=UpdateTableResponse,
)
+ async def upload_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ file: FileTypes,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ body = deepcopy_minimal({"file": file})
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return await self._put(
+ f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
+ body=await async_maybe_transform(
+ body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams
+ ),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class ConnectorsResourceWithRawResponse:
def __init__(self, connectors: ConnectorsResource) -> None:
@@ -2342,6 +2522,10 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_raw_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = to_custom_raw_response_wrapper(
+ connectors.download_datahub_artifact,
+ BinaryAPIResponse,
+ )
self.explore = to_raw_response_wrapper(
connectors.explore,
)
@@ -2390,6 +2574,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_raw_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = to_raw_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithRawResponse:
@@ -2424,6 +2611,10 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_raw_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = async_to_custom_raw_response_wrapper(
+ connectors.download_datahub_artifact,
+ AsyncBinaryAPIResponse,
+ )
self.explore = async_to_raw_response_wrapper(
connectors.explore,
)
@@ -2472,6 +2663,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_raw_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = async_to_raw_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithRawResponse:
@@ -2506,6 +2700,10 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_streamed_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = to_custom_streamed_response_wrapper(
+ connectors.download_datahub_artifact,
+ StreamedBinaryAPIResponse,
+ )
self.explore = to_streamed_response_wrapper(
connectors.explore,
)
@@ -2554,6 +2752,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_streamed_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = to_streamed_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithStreamingResponse:
@@ -2588,6 +2789,10 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_streamed_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = async_to_custom_streamed_response_wrapper(
+ connectors.download_datahub_artifact,
+ AsyncStreamedBinaryAPIResponse,
+ )
self.explore = async_to_streamed_response_wrapper(
connectors.explore,
)
@@ -2636,6 +2841,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_streamed_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = async_to_streamed_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithStreamingResponse:
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index 377bd22a2..a67a9b441 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -56,7 +56,8 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
@@ -374,7 +375,8 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 99a5f6d3d..7c324f7e2 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -388,6 +388,9 @@
from .structure_enhance_relationship_response import (
StructureEnhanceRelationshipResponse as StructureEnhanceRelationshipResponse,
)
+from .connector_upload_datahub_artifact_params import (
+ ConnectorUploadDatahubArtifactParams as ConnectorUploadDatahubArtifactParams,
+)
from .chat_copy_node_output_by_code_hash_params import (
ChatCopyNodeOutputByCodeHashParams as ChatCopyNodeOutputByCodeHashParams,
)
diff --git a/src/structify/types/admin/job_list_params.py b/src/structify/types/admin/job_list_params.py
index cb290ca95..62f040440 100644
--- a/src/structify/types/admin/job_list_params.py
+++ b/src/structify/types/admin/job_list_params.py
@@ -9,7 +9,7 @@
class JobListParams(TypedDict, total=False):
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
limit: int
diff --git a/src/structify/types/admin/job_list_response.py b/src/structify/types/admin/job_list_response.py
index d494541eb..523c2310d 100644
--- a/src/structify/types/admin/job_list_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -26,6 +26,8 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
+ "ParametersStructuringInputDatahubIngestion",
+ "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -95,6 +97,18 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class ParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
+
+
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -107,8 +121,7 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -122,6 +135,7 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
+ ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -131,33 +145,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: ParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/connector_catalog/admin_create_catalog_params.py b/src/structify/types/connector_catalog/admin_create_catalog_params.py
index 98662c009..adfb768f8 100644
--- a/src/structify/types/connector_catalog/admin_create_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_create_catalog_params.py
@@ -21,6 +21,4 @@ class AdminCreateCatalogParams(TypedDict, total=False):
enterprise_only: bool
- onboarding_priority: Optional[int]
-
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/admin_update_catalog_params.py b/src/structify/types/connector_catalog/admin_update_catalog_params.py
index 23d639c71..784ae5ece 100644
--- a/src/structify/types/connector_catalog/admin_update_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_update_catalog_params.py
@@ -19,6 +19,4 @@ class AdminUpdateCatalogParams(TypedDict, total=False):
name: Optional[str]
- onboarding_priority: Optional[int]
-
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/connector_catalog.py b/src/structify/types/connector_catalog/connector_catalog.py
index 8f0b9eb5e..c414d1f49 100644
--- a/src/structify/types/connector_catalog/connector_catalog.py
+++ b/src/structify/types/connector_catalog/connector_catalog.py
@@ -25,6 +25,4 @@ class ConnectorCatalog(BaseModel):
description: Optional[str] = None
- onboarding_priority: Optional[int] = None
-
priority: Optional[int] = None
diff --git a/src/structify/types/connector_explore_params.py b/src/structify/types/connector_explore_params.py
index d4b23d4b9..4d94d5501 100644
--- a/src/structify/types/connector_explore_params.py
+++ b/src/structify/types/connector_explore_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import TypedDict
__all__ = ["ConnectorExploreParams"]
@@ -11,9 +11,9 @@
class ConnectorExploreParams(TypedDict, total=False):
database_id: Optional[str]
- schema_id: Optional[str]
+ only_do_datahub: Optional[bool]
+ """If true, run only DataHub ingestion without queuing Diego annotation jobs."""
- stage: Optional[Literal["both", "ingestion", "annotation"]]
- """Which exploration stage to run"""
+ schema_id: Optional[str]
table_id: Optional[str]
diff --git a/src/structify/types/connector_upload_datahub_artifact_params.py b/src/structify/types/connector_upload_datahub_artifact_params.py
new file mode 100644
index 000000000..09dfc77e7
--- /dev/null
+++ b/src/structify/types/connector_upload_datahub_artifact_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ConnectorUploadDatahubArtifactParams"]
+
+
+class ConnectorUploadDatahubArtifactParams(TypedDict, total=False):
+ connector_id: Required[str]
+
+ file: Required[FileTypes]
diff --git a/src/structify/types/entity_list_jobs_response.py b/src/structify/types/entity_list_jobs_response.py
index 1bcedcda2..31808d0c5 100644
--- a/src/structify/types/entity_list_jobs_response.py
+++ b/src/structify/types/entity_list_jobs_response.py
@@ -14,9 +14,7 @@ class EntityListJobsResponseItem(BaseModel):
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
max_steps_without_save: int
@@ -30,6 +28,8 @@ class EntityListJobsResponseItem(BaseModel):
user_id: str
+ dataset_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_cancel_response.py b/src/structify/types/job_cancel_response.py
index 640fcf079..75a5f4673 100644
--- a/src/structify/types/job_cancel_response.py
+++ b/src/structify/types/job_cancel_response.py
@@ -14,9 +14,7 @@ class JobCancelResponse(BaseModel):
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
max_steps_without_save: int
@@ -30,6 +28,8 @@ class JobCancelResponse(BaseModel):
user_id: str
+ dataset_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_event_body.py b/src/structify/types/job_event_body.py
index 85f1e3f9f..8820bff9d 100644
--- a/src/structify/types/job_event_body.py
+++ b/src/structify/types/job_event_body.py
@@ -24,6 +24,7 @@
"DatahubDatabasesCreated",
"DatahubSchemasCreated",
"DatahubTablesProcessed",
+ "DatahubAnnotationsQueued",
"DatahubEmbeddingBatch",
"ViewedPdfPage",
]
@@ -167,9 +168,19 @@ class DatahubTablesProcessed(BaseModel):
tables_failed: int
+ tables_removed: int
+
tables_updated: int
+class DatahubAnnotationsQueued(BaseModel):
+ diff_annotations_queued: int
+
+ event_type: Literal["datahub_annotations_queued"]
+
+ full_annotations_queued: int
+
+
class DatahubEmbeddingBatch(BaseModel):
batch_num: int
@@ -203,6 +214,7 @@ class ViewedPdfPage(BaseModel):
DatahubDatabasesCreated,
DatahubSchemasCreated,
DatahubTablesProcessed,
+ DatahubAnnotationsQueued,
DatahubEmbeddingBatch,
ViewedPdfPage,
],
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
index c51109bea..82961dcbf 100644
--- a/src/structify/types/job_get_response.py
+++ b/src/structify/types/job_get_response.py
@@ -32,6 +32,8 @@
"InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"InfoParametersStructuringInputScrapeURL",
"InfoParametersStructuringInputScrapeURLScrapeURL",
+ "InfoParametersStructuringInputDatahubIngestion",
+ "InfoParametersStructuringInputDatahubIngestionDatahubIngestion",
"InfoParametersStructuringInputConnectorExploration",
"InfoParametersStructuringInputConnectorExplorationConnectorExploration",
"Saved",
@@ -135,6 +137,20 @@ class InfoParametersStructuringInputScrapeURL(BaseModel):
scrape_url: InfoParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class InfoParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class InfoParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: InfoParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(
+ alias="DatahubIngestion"
+ )
+
+
class InfoParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -147,8 +163,7 @@ class InfoParametersStructuringInputConnectorExplorationConnectorExploration(Bas
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class InfoParametersStructuringInputConnectorExploration(BaseModel):
@@ -162,6 +177,7 @@ class InfoParametersStructuringInputConnectorExploration(BaseModel):
InfoParametersStructuringInputTransformationPrompt,
InfoParametersStructuringInputScrapeFromURLProperty,
InfoParametersStructuringInputScrapeURL,
+ InfoParametersStructuringInputDatahubIngestion,
InfoParametersStructuringInputConnectorExploration,
]
@@ -171,33 +187,33 @@ class InfoParameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: InfoParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class Info(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[InfoParameters] = None
diff --git a/src/structify/types/job_list_params.py b/src/structify/types/job_list_params.py
index e13064899..d93b17726 100644
--- a/src/structify/types/job_list_params.py
+++ b/src/structify/types/job_list_params.py
@@ -15,7 +15,7 @@ class JobListParams(TypedDict, total=False):
dataset: Optional[str]
"""Dataset name to optionally filter jobs by"""
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
"""Type of job to optionally filter jobs by"""
limit: int
diff --git a/src/structify/types/job_list_response.py b/src/structify/types/job_list_response.py
index d6567a058..122fbeb06 100644
--- a/src/structify/types/job_list_response.py
+++ b/src/structify/types/job_list_response.py
@@ -26,6 +26,8 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
+ "ParametersStructuringInputDatahubIngestion",
+ "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -95,6 +97,18 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class ParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
+
+
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -107,8 +121,7 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -122,6 +135,7 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
+ ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -131,33 +145,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: ParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/tests/api_resources/connector_catalog/test_admin.py b/tests/api_resources/connector_catalog/test_admin.py
index 10cb267d0..224b67a19 100644
--- a/tests/api_resources/connector_catalog/test_admin.py
+++ b/tests/api_resources/connector_catalog/test_admin.py
@@ -195,7 +195,6 @@ def test_method_create_catalog_with_all_params(self, client: Structify) -> None:
categories=["string"],
description="description",
enterprise_only=True,
- onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -562,7 +561,6 @@ def test_method_update_catalog_with_all_params(self, client: Structify) -> None:
description="description",
enterprise_only=True,
name="name",
- onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -917,7 +915,6 @@ async def test_method_create_catalog_with_all_params(self, async_client: AsyncSt
categories=["string"],
description="description",
enterprise_only=True,
- onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -1284,7 +1281,6 @@ async def test_method_update_catalog_with_all_params(self, async_client: AsyncSt
description="description",
enterprise_only=True,
name="name",
- onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index d07a07258..ac23c3e9c 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -5,7 +5,9 @@
import os
from typing import Any, cast
+import httpx
import pytest
+from respx import MockRouter
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
@@ -28,6 +30,12 @@
ConnectorListWithSnippetsResponse,
ConnectorGetClarificationRequestsResponse,
)
+from structify._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
from structify.pagination import SyncJobsList, AsyncJobsList
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -734,6 +742,72 @@ def test_path_params_delete_secret(self, client: Structify) -> None:
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ connector = client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert connector.is_closed is True
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert connector.json() == {"foo": "bar"}
+ assert isinstance(connector, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ with client.connectors.with_streaming_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as connector:
+ assert not connector.is_closed
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, StreamedBinaryAPIResponse)
+
+ assert cast(Any, connector.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_path_params_download_datahub_artifact(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ client.connectors.with_raw_response.download_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
@@ -746,8 +820,8 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -1337,6 +1411,59 @@ def test_path_params_update_table(self, client: Structify) -> None:
table_id="",
)
+ @parametrize
+ def test_method_upload_datahub_artifact(self, client: Structify) -> None:
+ connector = client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+ assert connector is None
+
+ @parametrize
+ def test_raw_response_upload_datahub_artifact(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert connector is None
+
+ @parametrize
+ def test_streaming_response_upload_datahub_artifact(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert connector is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ file=b"Example data",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
class TestAsyncConnectors:
parametrize = pytest.mark.parametrize(
@@ -2041,6 +2168,76 @@ async def test_path_params_delete_secret(self, async_client: AsyncStructify) ->
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_download_datahub_artifact(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = await async_client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_raw_response_download_datahub_artifact(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ connector = await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert connector.is_closed is True
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert await connector.json() == {"foo": "bar"}
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_streaming_response_download_datahub_artifact(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ async with async_client.connectors.with_streaming_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as connector:
+ assert not connector.is_closed
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncStreamedBinaryAPIResponse)
+
+ assert cast(Any, connector.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_path_params_download_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
@@ -2053,8 +2250,8 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -2643,3 +2840,56 @@ async def test_path_params_update_table(self, async_client: AsyncStructify) -> N
await async_client.connectors.with_raw_response.update_table(
table_id="",
)
+
+ @parametrize
+ async def test_method_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+ assert connector is None
+
+ @parametrize
+ async def test_raw_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert connector is None
+
+ @parametrize
+ async def test_streaming_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert connector is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ file=b"Example data",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
From 234176cb1e424b08de929ee3445ab3ccf6c85105 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 01:11:21 +0000
Subject: [PATCH 072/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 4 +-
src/structify/resources/admin/jobs.py | 6 +-
src/structify/resources/chat.py | 75 ++++++
.../resources/connectors/connectors.py | 226 +---------------
src/structify/resources/jobs.py | 6 +-
src/structify/types/__init__.py | 4 +-
src/structify/types/admin/job_list_params.py | 2 +-
.../types/admin/job_list_response.py | 38 +--
src/structify/types/compress_chat_response.py | 9 +
.../types/connector_explore_params.py | 8 +-
...onnector_upload_datahub_artifact_params.py | 15 --
.../types/entity_list_jobs_response.py | 6 +-
src/structify/types/job_cancel_response.py | 6 +-
src/structify/types/job_event_body.py | 12 -
src/structify/types/job_get_response.py | 40 +--
src/structify/types/job_list_params.py | 2 +-
src/structify/types/job_list_response.py | 38 +--
src/structify/types/viz_figure_kind.py | 2 +-
tests/api_resources/test_chat.py | 77 ++++++
tests/api_resources/test_connectors.py | 254 +-----------------
21 files changed, 232 insertions(+), 606 deletions(-)
create mode 100644 src/structify/types/compress_chat_response.py
delete mode 100644 src/structify/types/connector_upload_datahub_artifact_params.py
diff --git a/.stats.yml b/.stats.yml
index c880f0a4c..492ceab29 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 248
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-738b8753bad183bc3ea4c227cb700d6d4716b9e064abf87c57f3f8e713b21fee.yml
-openapi_spec_hash: 112bc21dc51b40e05ffb37273818c1ce
-config_hash: ab5291af3bd5919aecf1f8e41eb363b8
+configured_endpoints: 247
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-90d851ec2e7164a2b245164443d94886f6cfa165161b79bbde3239e84f2029c8.yml
+openapi_spec_hash: 371d53240965747ae36853a7f9c98018
+config_hash: 27deacd435ab581e7ff08d1f4d495554
diff --git a/api.md b/api.md
index 4547079d0..fd660e471 100644
--- a/api.md
+++ b/api.md
@@ -100,6 +100,7 @@ from structify.types import (
ChatSessionWithMessages,
ChatTemplate,
ChatVisibility,
+ CompressChatResponse,
CopyChatSessionRequest,
CreateChatSessionRequest,
CreateChatSessionResponse,
@@ -142,6 +143,7 @@ Methods:
- client.chat.add_collaborator(chat_id, \*\*params) -> None
- client.chat.add_git_commit(session_id, \*\*params) -> ChatAddGitCommitResponse
- client.chat.admin_issue_found(chat_id, \*\*params) -> AdminIssueFoundResponse
+- client.chat.compress(session_id) -> CompressChatResponse
- client.chat.copy(\*\*params) -> ChatSessionWithMessages
- client.chat.copy_node_output_by_code_hash(session_id, \*\*params) -> ChatCopyNodeOutputByCodeHashResponse
- client.chat.create_session(\*\*params) -> CreateChatSessionResponse
@@ -735,7 +737,6 @@ Methods:
- client.connectors.create_secret(connector_id, \*\*params) -> None
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
-- client.connectors.download_datahub_artifact(kind, \*, connector_id) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
@@ -752,7 +753,6 @@ Methods:
- client.connectors.summaries(\*\*params) -> ConnectorSummariesResponse
- client.connectors.update_column(column_id, \*\*params) -> None
- client.connectors.update_table(table_id, \*\*params) -> UpdateTableResponse
-- client.connectors.upload_datahub_artifact(kind, \*, connector_id, \*\*params) -> None
## TypeSnippets
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index c95c5fb48..16f81550e 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -52,8 +52,7 @@ def with_streaming_response(self) -> JobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
@@ -183,8 +182,7 @@ def with_streaming_response(self) -> AsyncJobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index a365b1d5b..a617b1601 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -53,6 +53,7 @@
from ..types.chat_visibility import ChatVisibility
from ..types.chat_prompt_param import ChatPromptParam
from ..types.chat_session_role import ChatSessionRole
+from ..types.compress_chat_response import CompressChatResponse
from ..types.chat_load_files_response import ChatLoadFilesResponse
from ..types.list_dashboards_response import ListDashboardsResponse
from ..types.simulate_prompt_response import SimulatePromptResponse
@@ -221,6 +222,37 @@ def admin_issue_found(
cast_to=AdminIssueFoundResponse,
)
+ def compress(
+ self,
+ session_id: str,
+ *,
+ # 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,
+ ) -> CompressChatResponse:
+ """
+ Args:
+ 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
+ """
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return self._post(
+ f"/chat/sessions/{session_id}/compress",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CompressChatResponse,
+ )
+
def copy(
self,
*,
@@ -1406,6 +1438,37 @@ async def admin_issue_found(
cast_to=AdminIssueFoundResponse,
)
+ async def compress(
+ self,
+ session_id: str,
+ *,
+ # 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,
+ ) -> CompressChatResponse:
+ """
+ Args:
+ 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
+ """
+ if not session_id:
+ raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
+ return await self._post(
+ f"/chat/sessions/{session_id}/compress",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=CompressChatResponse,
+ )
+
async def copy(
self,
*,
@@ -2472,6 +2535,9 @@ def __init__(self, chat: ChatResource) -> None:
self.admin_issue_found = to_raw_response_wrapper(
chat.admin_issue_found,
)
+ self.compress = to_raw_response_wrapper(
+ chat.compress,
+ )
self.copy = to_raw_response_wrapper(
chat.copy,
)
@@ -2572,6 +2638,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.admin_issue_found = async_to_raw_response_wrapper(
chat.admin_issue_found,
)
+ self.compress = async_to_raw_response_wrapper(
+ chat.compress,
+ )
self.copy = async_to_raw_response_wrapper(
chat.copy,
)
@@ -2672,6 +2741,9 @@ def __init__(self, chat: ChatResource) -> None:
self.admin_issue_found = to_streamed_response_wrapper(
chat.admin_issue_found,
)
+ self.compress = to_streamed_response_wrapper(
+ chat.compress,
+ )
self.copy = to_streamed_response_wrapper(
chat.copy,
)
@@ -2772,6 +2844,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.admin_issue_found = async_to_streamed_response_wrapper(
chat.admin_issue_found,
)
+ self.compress = async_to_streamed_response_wrapper(
+ chat.compress,
+ )
self.copy = async_to_streamed_response_wrapper(
chat.copy,
)
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 579013d49..6a2301e83 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Dict, Mapping, Optional, cast
+from typing import Any, Dict, Optional, cast
from typing_extensions import Literal, overload
import httpx
@@ -21,36 +21,16 @@
connector_add_schema_object_params,
connector_get_explorer_chat_params,
connector_delete_schema_object_params,
- connector_upload_datahub_artifact_params,
)
-from ..._types import (
- Body,
- Omit,
- Query,
- Headers,
- NoneType,
- NotGiven,
- FileTypes,
- SequenceNotStr,
- omit,
- not_given,
-)
-from ..._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
+from ..._utils import required_args, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
- BinaryAPIResponse,
- AsyncBinaryAPIResponse,
- StreamedBinaryAPIResponse,
- AsyncStreamedBinaryAPIResponse,
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
- to_custom_raw_response_wrapper,
async_to_streamed_response_wrapper,
- to_custom_streamed_response_wrapper,
- async_to_custom_raw_response_wrapper,
- async_to_custom_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
from .type_snippets import (
@@ -669,48 +649,13 @@ def delete_secret(
cast_to=NoneType,
)
- def download_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- # 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,
- ) -> BinaryAPIResponse:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
- return self._get(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=BinaryAPIResponse,
- )
-
def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
- only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
+ stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -721,7 +666,7 @@ def explore(
) -> None:
"""
Args:
- only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
+ stage: Which exploration stage to run
extra_headers: Send extra headers
@@ -739,8 +684,8 @@ def explore(
body=maybe_transform(
{
"database_id": database_id,
- "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
+ "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -1241,50 +1186,6 @@ def update_table(
cast_to=UpdateTableResponse,
)
- def upload_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- file: FileTypes,
- # 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:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- body = deepcopy_minimal({"file": file})
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers["Content-Type"] = "multipart/form-data"
- return self._put(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- body=maybe_transform(body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
class AsyncConnectorsResource(AsyncAPIResource):
@cached_property
@@ -1871,48 +1772,13 @@ async def delete_secret(
cast_to=NoneType,
)
- async def download_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- # 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,
- ) -> AsyncBinaryAPIResponse:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
- return await self._get(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=AsyncBinaryAPIResponse,
- )
-
async def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
- only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
+ stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1923,7 +1789,7 @@ async def explore(
) -> None:
"""
Args:
- only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
+ stage: Which exploration stage to run
extra_headers: Send extra headers
@@ -1941,8 +1807,8 @@ async def explore(
body=await async_maybe_transform(
{
"database_id": database_id,
- "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
+ "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -2447,52 +2313,6 @@ async def update_table(
cast_to=UpdateTableResponse,
)
- async def upload_datahub_artifact(
- self,
- kind: str,
- *,
- connector_id: str,
- file: FileTypes,
- # 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:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not kind:
- raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
- body = deepcopy_minimal({"file": file})
- files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers["Content-Type"] = "multipart/form-data"
- return await self._put(
- f"/internal/connectors/{connector_id}/datahub-artifacts/{kind}",
- body=await async_maybe_transform(
- body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams
- ),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=NoneType,
- )
-
class ConnectorsResourceWithRawResponse:
def __init__(self, connectors: ConnectorsResource) -> None:
@@ -2522,10 +2342,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_raw_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = to_custom_raw_response_wrapper(
- connectors.download_datahub_artifact,
- BinaryAPIResponse,
- )
self.explore = to_raw_response_wrapper(
connectors.explore,
)
@@ -2574,9 +2390,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_raw_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = to_raw_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithRawResponse:
@@ -2611,10 +2424,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_raw_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = async_to_custom_raw_response_wrapper(
- connectors.download_datahub_artifact,
- AsyncBinaryAPIResponse,
- )
self.explore = async_to_raw_response_wrapper(
connectors.explore,
)
@@ -2663,9 +2472,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_raw_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = async_to_raw_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithRawResponse:
@@ -2700,10 +2506,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_streamed_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = to_custom_streamed_response_wrapper(
- connectors.download_datahub_artifact,
- StreamedBinaryAPIResponse,
- )
self.explore = to_streamed_response_wrapper(
connectors.explore,
)
@@ -2752,9 +2554,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_streamed_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = to_streamed_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithStreamingResponse:
@@ -2789,10 +2588,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_streamed_response_wrapper(
connectors.delete_secret,
)
- self.download_datahub_artifact = async_to_custom_streamed_response_wrapper(
- connectors.download_datahub_artifact,
- AsyncStreamedBinaryAPIResponse,
- )
self.explore = async_to_streamed_response_wrapper(
connectors.explore,
)
@@ -2841,9 +2636,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_streamed_response_wrapper(
connectors.update_table,
)
- self.upload_datahub_artifact = async_to_streamed_response_wrapper(
- connectors.upload_datahub_artifact,
- )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithStreamingResponse:
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index a67a9b441..377bd22a2 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -56,8 +56,7 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
@@ -375,8 +374,7 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
- | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 7c324f7e2..88f29faca 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -154,6 +154,7 @@
from .workflow_session_edge import WorkflowSessionEdge as WorkflowSessionEdge
from .workflow_session_node import WorkflowSessionNode as WorkflowSessionNode
from .chat_load_files_params import ChatLoadFilesParams as ChatLoadFilesParams
+from .compress_chat_response import CompressChatResponse as CompressChatResponse
from .connector_get_response import ConnectorGetResponse as ConnectorGetResponse
from .connector_with_secrets import ConnectorWithSecrets as ConnectorWithSecrets
from .credits_usage_response import CreditsUsageResponse as CreditsUsageResponse
@@ -388,9 +389,6 @@
from .structure_enhance_relationship_response import (
StructureEnhanceRelationshipResponse as StructureEnhanceRelationshipResponse,
)
-from .connector_upload_datahub_artifact_params import (
- ConnectorUploadDatahubArtifactParams as ConnectorUploadDatahubArtifactParams,
-)
from .chat_copy_node_output_by_code_hash_params import (
ChatCopyNodeOutputByCodeHashParams as ChatCopyNodeOutputByCodeHashParams,
)
diff --git a/src/structify/types/admin/job_list_params.py b/src/structify/types/admin/job_list_params.py
index 62f040440..cb290ca95 100644
--- a/src/structify/types/admin/job_list_params.py
+++ b/src/structify/types/admin/job_list_params.py
@@ -9,7 +9,7 @@
class JobListParams(TypedDict, total=False):
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
limit: int
diff --git a/src/structify/types/admin/job_list_response.py b/src/structify/types/admin/job_list_response.py
index 523c2310d..d494541eb 100644
--- a/src/structify/types/admin/job_list_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -26,8 +26,6 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
- "ParametersStructuringInputDatahubIngestion",
- "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -97,18 +95,6 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
-class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
- connector_id: str
-
- exploration_run_id: str
-
- only_do_datahub: bool
-
-
-class ParametersStructuringInputDatahubIngestion(BaseModel):
- datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
-
-
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -121,7 +107,8 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- strategy: Literal["full", "diff"]
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -135,7 +122,6 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
- ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -145,33 +131,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- structuring_input: ParametersStructuringInput
-
- instructions: Optional[str] = None
-
- model: Optional[str] = None
-
- seeded_kg: Optional[KnowledgeGraph] = None
+ seeded_kg: KnowledgeGraph
"""
Knowledge graph info structured to deserialize and display in the same format
that the LLM outputs. Also the first representation of an LLM output in the
pipeline from raw tool output to being merged into a DB
"""
+ structuring_input: ParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
- dataset_id: Optional[str] = None
-
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/compress_chat_response.py b/src/structify/types/compress_chat_response.py
new file mode 100644
index 000000000..17433aa85
--- /dev/null
+++ b/src/structify/types/compress_chat_response.py
@@ -0,0 +1,9 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+
+__all__ = ["CompressChatResponse"]
+
+
+class CompressChatResponse(BaseModel):
+ status: str
diff --git a/src/structify/types/connector_explore_params.py b/src/structify/types/connector_explore_params.py
index 4d94d5501..d4b23d4b9 100644
--- a/src/structify/types/connector_explore_params.py
+++ b/src/structify/types/connector_explore_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import TypedDict
+from typing_extensions import Literal, TypedDict
__all__ = ["ConnectorExploreParams"]
@@ -11,9 +11,9 @@
class ConnectorExploreParams(TypedDict, total=False):
database_id: Optional[str]
- only_do_datahub: Optional[bool]
- """If true, run only DataHub ingestion without queuing Diego annotation jobs."""
-
schema_id: Optional[str]
+ stage: Optional[Literal["both", "ingestion", "annotation"]]
+ """Which exploration stage to run"""
+
table_id: Optional[str]
diff --git a/src/structify/types/connector_upload_datahub_artifact_params.py b/src/structify/types/connector_upload_datahub_artifact_params.py
deleted file mode 100644
index 09dfc77e7..000000000
--- a/src/structify/types/connector_upload_datahub_artifact_params.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ConnectorUploadDatahubArtifactParams"]
-
-
-class ConnectorUploadDatahubArtifactParams(TypedDict, total=False):
- connector_id: Required[str]
-
- file: Required[FileTypes]
diff --git a/src/structify/types/entity_list_jobs_response.py b/src/structify/types/entity_list_jobs_response.py
index 31808d0c5..1bcedcda2 100644
--- a/src/structify/types/entity_list_jobs_response.py
+++ b/src/structify/types/entity_list_jobs_response.py
@@ -14,7 +14,9 @@ class EntityListJobsResponseItem(BaseModel):
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
max_steps_without_save: int
@@ -28,8 +30,6 @@ class EntityListJobsResponseItem(BaseModel):
user_id: str
- dataset_id: Optional[str] = None
-
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_cancel_response.py b/src/structify/types/job_cancel_response.py
index 75a5f4673..640fcf079 100644
--- a/src/structify/types/job_cancel_response.py
+++ b/src/structify/types/job_cancel_response.py
@@ -14,7 +14,9 @@ class JobCancelResponse(BaseModel):
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
max_steps_without_save: int
@@ -28,8 +30,6 @@ class JobCancelResponse(BaseModel):
user_id: str
- dataset_id: Optional[str] = None
-
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_event_body.py b/src/structify/types/job_event_body.py
index 8820bff9d..85f1e3f9f 100644
--- a/src/structify/types/job_event_body.py
+++ b/src/structify/types/job_event_body.py
@@ -24,7 +24,6 @@
"DatahubDatabasesCreated",
"DatahubSchemasCreated",
"DatahubTablesProcessed",
- "DatahubAnnotationsQueued",
"DatahubEmbeddingBatch",
"ViewedPdfPage",
]
@@ -168,19 +167,9 @@ class DatahubTablesProcessed(BaseModel):
tables_failed: int
- tables_removed: int
-
tables_updated: int
-class DatahubAnnotationsQueued(BaseModel):
- diff_annotations_queued: int
-
- event_type: Literal["datahub_annotations_queued"]
-
- full_annotations_queued: int
-
-
class DatahubEmbeddingBatch(BaseModel):
batch_num: int
@@ -214,7 +203,6 @@ class ViewedPdfPage(BaseModel):
DatahubDatabasesCreated,
DatahubSchemasCreated,
DatahubTablesProcessed,
- DatahubAnnotationsQueued,
DatahubEmbeddingBatch,
ViewedPdfPage,
],
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
index 82961dcbf..c51109bea 100644
--- a/src/structify/types/job_get_response.py
+++ b/src/structify/types/job_get_response.py
@@ -32,8 +32,6 @@
"InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"InfoParametersStructuringInputScrapeURL",
"InfoParametersStructuringInputScrapeURLScrapeURL",
- "InfoParametersStructuringInputDatahubIngestion",
- "InfoParametersStructuringInputDatahubIngestionDatahubIngestion",
"InfoParametersStructuringInputConnectorExploration",
"InfoParametersStructuringInputConnectorExplorationConnectorExploration",
"Saved",
@@ -137,20 +135,6 @@ class InfoParametersStructuringInputScrapeURL(BaseModel):
scrape_url: InfoParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
-class InfoParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
- connector_id: str
-
- exploration_run_id: str
-
- only_do_datahub: bool
-
-
-class InfoParametersStructuringInputDatahubIngestion(BaseModel):
- datahub_ingestion: InfoParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(
- alias="DatahubIngestion"
- )
-
-
class InfoParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -163,7 +147,8 @@ class InfoParametersStructuringInputConnectorExplorationConnectorExploration(Bas
exploration_run_id: str
- strategy: Literal["full", "diff"]
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
class InfoParametersStructuringInputConnectorExploration(BaseModel):
@@ -177,7 +162,6 @@ class InfoParametersStructuringInputConnectorExploration(BaseModel):
InfoParametersStructuringInputTransformationPrompt,
InfoParametersStructuringInputScrapeFromURLProperty,
InfoParametersStructuringInputScrapeURL,
- InfoParametersStructuringInputDatahubIngestion,
InfoParametersStructuringInputConnectorExploration,
]
@@ -187,33 +171,33 @@ class InfoParameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- structuring_input: InfoParametersStructuringInput
-
- instructions: Optional[str] = None
-
- model: Optional[str] = None
-
- seeded_kg: Optional[KnowledgeGraph] = None
+ seeded_kg: KnowledgeGraph
"""
Knowledge graph info structured to deserialize and display in the same format
that the LLM outputs. Also the first representation of an LLM output in the
pipeline from raw tool output to being merged into a DB
"""
+ structuring_input: InfoParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
class Info(BaseModel):
id: str
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
- dataset_id: Optional[str] = None
-
message: Optional[str] = None
parameters: Optional[InfoParameters] = None
diff --git a/src/structify/types/job_list_params.py b/src/structify/types/job_list_params.py
index d93b17726..e13064899 100644
--- a/src/structify/types/job_list_params.py
+++ b/src/structify/types/job_list_params.py
@@ -15,7 +15,7 @@ class JobListParams(TypedDict, total=False):
dataset: Optional[str]
"""Dataset name to optionally filter jobs by"""
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
"""Type of job to optionally filter jobs by"""
limit: int
diff --git a/src/structify/types/job_list_response.py b/src/structify/types/job_list_response.py
index 122fbeb06..d6567a058 100644
--- a/src/structify/types/job_list_response.py
+++ b/src/structify/types/job_list_response.py
@@ -26,8 +26,6 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
- "ParametersStructuringInputDatahubIngestion",
- "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -97,18 +95,6 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
-class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
- connector_id: str
-
- exploration_run_id: str
-
- only_do_datahub: bool
-
-
-class ParametersStructuringInputDatahubIngestion(BaseModel):
- datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
-
-
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -121,7 +107,8 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- strategy: Literal["full", "diff"]
+ stage: Literal["both", "ingestion", "annotation"]
+ """Which exploration stage to run"""
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -135,7 +122,6 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
- ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -145,33 +131,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- structuring_input: ParametersStructuringInput
-
- instructions: Optional[str] = None
-
- model: Optional[str] = None
-
- seeded_kg: Optional[KnowledgeGraph] = None
+ seeded_kg: KnowledgeGraph
"""
Knowledge graph info structured to deserialize and display in the same format
that the LLM outputs. Also the first representation of an LLM output in the
pipeline from raw tool output to being merged into a DB
"""
+ structuring_input: ParametersStructuringInput
+
+ instructions: Optional[str] = None
+
+ model: Optional[str] = None
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+ dataset_id: str
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
- dataset_id: Optional[str] = None
-
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/viz_figure_kind.py b/src/structify/types/viz_figure_kind.py
index e70d16356..32d895e43 100644
--- a/src/structify/types/viz_figure_kind.py
+++ b/src/structify/types/viz_figure_kind.py
@@ -4,4 +4,4 @@
__all__ = ["VizFigureKind"]
-VizFigureKind: TypeAlias = Literal["js", "vega-lite", "data-table"]
+VizFigureKind: TypeAlias = Literal["js", "vega-lite"]
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index cd70a4cc2..d984062af 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -14,6 +14,7 @@
from structify.types import (
ChatSession,
ChatTemplate,
+ CompressChatResponse,
ChatLoadFilesResponse,
GetChatSessionResponse,
ListDashboardsResponse,
@@ -187,6 +188,44 @@ def test_path_params_admin_issue_found(self, client: Structify) -> None:
title="title",
)
+ @parametrize
+ def test_method_compress(self, client: Structify) -> None:
+ chat = client.chat.compress(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(CompressChatResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_compress(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.compress(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(CompressChatResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_compress(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.compress(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(CompressChatResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_compress(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ client.chat.with_raw_response.compress(
+ "",
+ )
+
@parametrize
def test_method_copy(self, client: Structify) -> None:
chat = client.chat.copy(
@@ -1712,6 +1751,44 @@ async def test_path_params_admin_issue_found(self, async_client: AsyncStructify)
title="title",
)
+ @parametrize
+ async def test_method_compress(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.compress(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(CompressChatResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_compress(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.compress(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(CompressChatResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_compress(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.compress(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(CompressChatResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_compress(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `session_id` but received ''"):
+ await async_client.chat.with_raw_response.compress(
+ "",
+ )
+
@parametrize
async def test_method_copy(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.copy(
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index ac23c3e9c..d07a07258 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -5,9 +5,7 @@
import os
from typing import Any, cast
-import httpx
import pytest
-from respx import MockRouter
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
@@ -30,12 +28,6 @@
ConnectorListWithSnippetsResponse,
ConnectorGetClarificationRequestsResponse,
)
-from structify._response import (
- BinaryAPIResponse,
- AsyncBinaryAPIResponse,
- StreamedBinaryAPIResponse,
- AsyncStreamedBinaryAPIResponse,
-)
from structify.pagination import SyncJobsList, AsyncJobsList
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -742,72 +734,6 @@ def test_path_params_delete_secret(self, client: Structify) -> None:
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_method_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- connector = client.connectors.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert connector.is_closed
- assert connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, BinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_raw_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
-
- connector = client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert connector.is_closed is True
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
- assert connector.json() == {"foo": "bar"}
- assert isinstance(connector, BinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_streaming_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- with client.connectors.with_streaming_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as connector:
- assert not connector.is_closed
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
-
- assert connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, StreamedBinaryAPIResponse)
-
- assert cast(Any, connector.is_closed) is True
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- def test_path_params_download_datahub_artifact(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- client.connectors.with_raw_response.download_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
@parametrize
def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
@@ -820,8 +746,8 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -1411,59 +1337,6 @@ def test_path_params_update_table(self, client: Structify) -> None:
table_id="",
)
- @parametrize
- def test_method_upload_datahub_artifact(self, client: Structify) -> None:
- connector = client.connectors.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
- assert connector is None
-
- @parametrize
- def test_raw_response_upload_datahub_artifact(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- connector = response.parse()
- assert connector is None
-
- @parametrize
- def test_streaming_response_upload_datahub_artifact(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- connector = response.parse()
- assert connector is None
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="",
- file=b"Example data",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- client.connectors.with_raw_response.upload_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
-
class TestAsyncConnectors:
parametrize = pytest.mark.parametrize(
@@ -2168,76 +2041,6 @@ async def test_path_params_delete_secret(self, async_client: AsyncStructify) ->
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_method_download_datahub_artifact(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- connector = await async_client.connectors.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert connector.is_closed
- assert await connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, AsyncBinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_raw_response_download_datahub_artifact(
- self, async_client: AsyncStructify, respx_mock: MockRouter
- ) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
-
- connector = await async_client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert connector.is_closed is True
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
- assert await connector.json() == {"foo": "bar"}
- assert isinstance(connector, AsyncBinaryAPIResponse)
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_streaming_response_download_datahub_artifact(
- self, async_client: AsyncStructify, respx_mock: MockRouter
- ) -> None:
- respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
- return_value=httpx.Response(200, json={"foo": "bar"})
- )
- async with async_client.connectors.with_streaming_response.download_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as connector:
- assert not connector.is_closed
- assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
-
- assert await connector.json() == {"foo": "bar"}
- assert cast(Any, connector.is_closed) is True
- assert isinstance(connector, AsyncStreamedBinaryAPIResponse)
-
- assert cast(Any, connector.is_closed) is True
-
- @parametrize
- @pytest.mark.respx(base_url=base_url)
- async def test_path_params_download_datahub_artifact(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.download_datahub_artifact(
- kind="kind",
- connector_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- await async_client.connectors.with_raw_response.download_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
@parametrize
async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
@@ -2250,8 +2053,8 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -2840,56 +2643,3 @@ async def test_path_params_update_table(self, async_client: AsyncStructify) -> N
await async_client.connectors.with_raw_response.update_table(
table_id="",
)
-
- @parametrize
- async def test_method_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
- assert connector is None
-
- @parametrize
- async def test_raw_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- connector = await response.parse()
- assert connector is None
-
- @parametrize
- async def test_streaming_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- connector = await response.parse()
- assert connector is None
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.upload_datahub_artifact(
- kind="kind",
- connector_id="",
- file=b"Example data",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
- await async_client.connectors.with_raw_response.upload_datahub_artifact(
- kind="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=b"Example data",
- )
From dd440d04c277fee4e8373c09bc51b43a951369a1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 02:00:31 +0000
Subject: [PATCH 073/105] fix: sanitize endpoint path params
---
src/structify/_utils/__init__.py | 1 +
src/structify/_utils/_path.py | 127 ++++++++++++++++++
.../resources/admin/chat_templates.py | 6 +-
src/structify/resources/admin/teams.py | 6 +-
src/structify/resources/chat.py | 110 +++++++--------
src/structify/resources/code.py | 6 +-
.../resources/connector_catalog/admin.py | 34 ++---
.../connector_catalog/connector_catalog.py | 10 +-
.../resources/connectors/connectors.py | 82 ++++++-----
.../resources/connectors/type_snippets.py | 6 +-
src/structify/resources/jobs.py | 14 +-
src/structify/resources/projects.py | 14 +-
src/structify/resources/public_sessions.py | 9 +-
src/structify/resources/sandbox.py | 18 +--
src/structify/resources/sessions.py | 81 ++++++-----
src/structify/resources/teams.py | 50 +++----
src/structify/resources/user/api_keys.py | 10 +-
src/structify/resources/whitelabel.py | 13 +-
src/structify/resources/wiki.py | 22 +--
src/structify/resources/workflow_schedule.py | 30 ++---
tests/test_utils/test_path.py | 89 ++++++++++++
21 files changed, 486 insertions(+), 252 deletions(-)
create mode 100644 src/structify/_utils/_path.py
create mode 100644 tests/test_utils/test_path.py
diff --git a/src/structify/_utils/__init__.py b/src/structify/_utils/__init__.py
index dc64e29a1..10cb66d2d 100644
--- a/src/structify/_utils/__init__.py
+++ b/src/structify/_utils/__init__.py
@@ -1,3 +1,4 @@
+from ._path import path_template as path_template
from ._sync import asyncify as asyncify
from ._proxy import LazyProxy as LazyProxy
from ._utils import (
diff --git a/src/structify/_utils/_path.py b/src/structify/_utils/_path.py
new file mode 100644
index 000000000..4d6e1e4cb
--- /dev/null
+++ b/src/structify/_utils/_path.py
@@ -0,0 +1,127 @@
+from __future__ import annotations
+
+import re
+from typing import (
+ Any,
+ Mapping,
+ Callable,
+)
+from urllib.parse import quote
+
+# Matches '.' or '..' where each dot is either literal or percent-encoded (%2e / %2E).
+_DOT_SEGMENT_RE = re.compile(r"^(?:\.|%2[eE]){1,2}$")
+
+_PLACEHOLDER_RE = re.compile(r"\{(\w+)\}")
+
+
+def _quote_path_segment_part(value: str) -> str:
+ """Percent-encode `value` for use in a URI path segment.
+
+ Considers characters not in `pchar` set from RFC 3986 §3.3 to be unsafe.
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.3
+ """
+ # quote() already treats unreserved characters (letters, digits, and -._~)
+ # as safe, so we only need to add sub-delims, ':', and '@'.
+ # Notably, unlike the default `safe` for quote(), / is unsafe and must be quoted.
+ return quote(value, safe="!$&'()*+,;=:@")
+
+
+def _quote_query_part(value: str) -> str:
+ """Percent-encode `value` for use in a URI query string.
+
+ Considers &, = and characters not in `query` set from RFC 3986 §3.4 to be unsafe.
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.4
+ """
+ return quote(value, safe="!$'()*+,;:@/?")
+
+
+def _quote_fragment_part(value: str) -> str:
+ """Percent-encode `value` for use in a URI fragment.
+
+ Considers characters not in `fragment` set from RFC 3986 §3.5 to be unsafe.
+ https://datatracker.ietf.org/doc/html/rfc3986#section-3.5
+ """
+ return quote(value, safe="!$&'()*+,;=:@/?")
+
+
+def _interpolate(
+ template: str,
+ values: Mapping[str, Any],
+ quoter: Callable[[str], str],
+) -> str:
+ """Replace {name} placeholders in `template`, quoting each value with `quoter`.
+
+ Placeholder names are looked up in `values`.
+
+ Raises:
+ KeyError: If a placeholder is not found in `values`.
+ """
+ # re.split with a capturing group returns alternating
+ # [text, name, text, name, ..., text] elements.
+ parts = _PLACEHOLDER_RE.split(template)
+
+ for i in range(1, len(parts), 2):
+ name = parts[i]
+ if name not in values:
+ raise KeyError(f"a value for placeholder {{{name}}} was not provided")
+ val = values[name]
+ if val is None:
+ parts[i] = "null"
+ elif isinstance(val, bool):
+ parts[i] = "true" if val else "false"
+ else:
+ parts[i] = quoter(str(values[name]))
+
+ return "".join(parts)
+
+
+def path_template(template: str, /, **kwargs: Any) -> str:
+ """Interpolate {name} placeholders in `template` from keyword arguments.
+
+ Args:
+ template: The template string containing {name} placeholders.
+ **kwargs: Keyword arguments to interpolate into the template.
+
+ Returns:
+ The template with placeholders interpolated and percent-encoded.
+
+ Safe characters for percent-encoding are dependent on the URI component.
+ Placeholders in path and fragment portions are percent-encoded where the `segment`
+ and `fragment` sets from RFC 3986 respectively are considered safe.
+ Placeholders in the query portion are percent-encoded where the `query` set from
+ RFC 3986 §3.3 is considered safe except for = and & characters.
+
+ Raises:
+ KeyError: If a placeholder is not found in `kwargs`.
+ ValueError: If resulting path contains /./ or /../ segments (including percent-encoded dot-segments).
+ """
+ # Split the template into path, query, and fragment portions.
+ fragment_template: str | None = None
+ query_template: str | None = None
+
+ rest = template
+ if "#" in rest:
+ rest, fragment_template = rest.split("#", 1)
+ if "?" in rest:
+ rest, query_template = rest.split("?", 1)
+ path_template = rest
+
+ # Interpolate each portion with the appropriate quoting rules.
+ path_result = _interpolate(path_template, kwargs, _quote_path_segment_part)
+
+ # Reject dot-segments (. and ..) in the final assembled path. The check
+ # runs after interpolation so that adjacent placeholders or a mix of static
+ # text and placeholders that together form a dot-segment are caught.
+ # Also reject percent-encoded dot-segments to protect against incorrectly
+ # implemented normalization in servers/proxies.
+ for segment in path_result.split("/"):
+ if _DOT_SEGMENT_RE.match(segment):
+ raise ValueError(f"Constructed path {path_result!r} contains dot-segment {segment!r} which is not allowed")
+
+ result = path_result
+ if query_template is not None:
+ result += "?" + _interpolate(query_template, kwargs, _quote_query_part)
+ if fragment_template is not None:
+ result += "#" + _interpolate(fragment_template, kwargs, _quote_fragment_part)
+
+ return result
diff --git a/src/structify/resources/admin/chat_templates.py b/src/structify/resources/admin/chat_templates.py
index 8304e38f4..618e4344f 100644
--- a/src/structify/resources/admin/chat_templates.py
+++ b/src/structify/resources/admin/chat_templates.py
@@ -7,7 +7,7 @@
import httpx
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -125,7 +125,7 @@ def update(
if not template_id:
raise ValueError(f"Expected a non-empty value for `template_id` but received {template_id!r}")
return self._patch(
- f"/admin/chat/templates/{template_id}",
+ path_template("/admin/chat/templates/{template_id}", template_id=template_id),
body=maybe_transform(
{
"description": description,
@@ -280,7 +280,7 @@ async def update(
if not template_id:
raise ValueError(f"Expected a non-empty value for `template_id` but received {template_id!r}")
return await self._patch(
- f"/admin/chat/templates/{template_id}",
+ path_template("/admin/chat/templates/{template_id}", template_id=template_id),
body=await async_maybe_transform(
{
"description": description,
diff --git a/src/structify/resources/admin/teams.py b/src/structify/resources/admin/teams.py
index 3f0befb52..5d6c1799c 100644
--- a/src/structify/resources/admin/teams.py
+++ b/src/structify/resources/admin/teams.py
@@ -10,7 +10,7 @@
from ...types import TeamRole
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -375,7 +375,7 @@ def list_members(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
- f"/admin/team/{team_id}/members",
+ path_template("/admin/team/{team_id}/members", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -788,7 +788,7 @@ async def list_members(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
- f"/admin/team/{team_id}/members",
+ path_template("/admin/team/{team_id}/members", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index a617b1601..028f01964 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -30,7 +30,7 @@
chat_copy_node_output_by_code_hash_params,
)
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr, omit, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._utils import extract_files, path_template, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -129,7 +129,7 @@ def add_collaborator(
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
- f"/chat/sessions/{chat_id}/collaborators",
+ path_template("/chat/sessions/{chat_id}/collaborators", chat_id=chat_id),
body=maybe_transform(
{
"email": email,
@@ -172,7 +172,7 @@ def add_git_commit(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/chat/sessions/{session_id}/commits",
+ path_template("/chat/sessions/{session_id}/commits", session_id=session_id),
body=maybe_transform({"commit_hash": commit_hash}, chat_add_git_commit_params.ChatAddGitCommitParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -208,7 +208,7 @@ def admin_issue_found(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._post(
- f"/chat/sessions/{chat_id}/admin/issue_found",
+ path_template("/chat/sessions/{chat_id}/admin/issue_found", chat_id=chat_id),
body=maybe_transform(
{
"message": message,
@@ -246,7 +246,7 @@ def compress(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/chat/sessions/{session_id}/compress",
+ path_template("/chat/sessions/{session_id}/compress", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -326,7 +326,7 @@ def copy_node_output_by_code_hash(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/chat/sessions/{session_id}/nodes/by_code_hash",
+ path_template("/chat/sessions/{session_id}/nodes/by_code_hash", session_id=session_id),
body=maybe_transform(
{
"code_md5_hash": code_md5_hash,
@@ -412,7 +412,7 @@ def delete_input_file(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._post(
- f"/chat/input-files/delete/{chat_id}",
+ path_template("/chat/input-files/delete/{chat_id}", chat_id=chat_id),
body=maybe_transform({"filenames": filenames}, chat_delete_input_file_params.ChatDeleteInputFileParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -446,7 +446,7 @@ def delete_session(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._delete(
- f"/chat/sessions/{session_id}",
+ path_template("/chat/sessions/{session_id}", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -479,7 +479,7 @@ def get_dependencies(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._get(
- f"/chat/sessions/{session_id}/dependencies",
+ path_template("/chat/sessions/{session_id}/dependencies", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -515,7 +515,7 @@ def get_git_commit(
if not commit_hash:
raise ValueError(f"Expected a non-empty value for `commit_hash` but received {commit_hash!r}")
return self._get(
- f"/chat/sessions/{chat_id}/commits/{commit_hash}",
+ path_template("/chat/sessions/{chat_id}/commits/{commit_hash}", chat_id=chat_id, commit_hash=commit_hash),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -548,7 +548,7 @@ def get_partial_chats(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return self._get(
- f"/chat/{chat_session_id}/partial-chats",
+ path_template("/chat/{chat_session_id}/partial-chats", chat_session_id=chat_session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -581,7 +581,7 @@ def get_session(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._get(
- f"/chat/sessions/{session_id}",
+ path_template("/chat/sessions/{session_id}", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -614,7 +614,7 @@ def get_session_timeline(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._get(
- f"/chat/sessions/{session_id}/timeline",
+ path_template("/chat/sessions/{session_id}/timeline", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -645,7 +645,7 @@ def get_template(
if not template_id:
raise ValueError(f"Expected a non-empty value for `template_id` but received {template_id!r}")
return self._get(
- f"/chat/templates/{template_id}",
+ path_template("/chat/templates/{template_id}", template_id=template_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -682,7 +682,7 @@ def grant_admin_override(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._post(
- f"/chat/sessions/{chat_id}/admin_override",
+ path_template("/chat/sessions/{chat_id}/admin_override", chat_id=chat_id),
body=maybe_transform(
{
"duration_hours": duration_hours,
@@ -722,7 +722,7 @@ def list_collaborators(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._get(
- f"/chat/sessions/{chat_id}/collaborators",
+ path_template("/chat/sessions/{chat_id}/collaborators", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -758,7 +758,7 @@ def list_dashboards(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._get(
- f"/chat/sessions/{chat_id}/dashboards",
+ path_template("/chat/sessions/{chat_id}/dashboards", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -797,7 +797,7 @@ def list_input_files(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._get(
- f"/chat/input-files/list/{chat_id}",
+ path_template("/chat/input-files/list/{chat_id}", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -943,7 +943,7 @@ def load_input_file(
raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return self._get(
- f"/chat/input-files/download/{chat_id}/{filename}",
+ path_template("/chat/input-files/download/{chat_id}/{filename}", chat_id=chat_id, filename=filename),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -979,7 +979,7 @@ def load_input_files(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._get(
- f"/chat/input-files/download-all/{chat_id}",
+ path_template("/chat/input-files/download-all/{chat_id}", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1017,7 +1017,7 @@ def make_permanent(
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._patch(
- f"/chat/sessions/{session_id}/make-permanent",
+ path_template("/chat/sessions/{session_id}/make-permanent", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1052,7 +1052,7 @@ def remove_collaborator(
raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/chat/sessions/{chat_id}/collaborators/{user_id}",
+ path_template("/chat/sessions/{chat_id}/collaborators/{user_id}", chat_id=chat_id, user_id=user_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1088,7 +1088,7 @@ def revert_to_commit(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/chat/sessions/{session_id}/revert",
+ path_template("/chat/sessions/{session_id}/revert", session_id=session_id),
body=maybe_transform({"commit_hash": commit_hash}, chat_revert_to_commit_params.ChatRevertToCommitParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -1123,7 +1123,7 @@ def simulate_prompt(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return self._post(
- f"/chat/{chat_session_id}/simulate-prompt",
+ path_template("/chat/{chat_session_id}/simulate-prompt", chat_session_id=chat_session_id),
body=maybe_transform({"chat_prompt": chat_prompt}, chat_simulate_prompt_params.ChatSimulatePromptParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -1159,7 +1159,7 @@ def update_session(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._patch(
- f"/chat/sessions/{session_id}",
+ path_template("/chat/sessions/{session_id}", session_id=session_id),
body=maybe_transform(
{
"message_head": message_head,
@@ -1200,7 +1200,7 @@ def update_session_favorite(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._patch(
- f"/chat/sessions/{session_id}/favorite",
+ path_template("/chat/sessions/{session_id}/favorite", session_id=session_id),
body=maybe_transform(
{"is_favorite": is_favorite}, chat_update_session_favorite_params.ChatUpdateSessionFavoriteParams
),
@@ -1237,7 +1237,7 @@ def update_visibility(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._put(
- f"/chat/sessions/{session_id}/visibility",
+ path_template("/chat/sessions/{session_id}/visibility", session_id=session_id),
body=maybe_transform({"visibility": visibility}, chat_update_visibility_params.ChatUpdateVisibilityParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -1286,7 +1286,7 @@ def upload_input_file(
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
- f"/chat/input-files/upload/{chat_id}",
+ path_template("/chat/input-files/upload/{chat_id}", chat_id=chat_id),
body=maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
files=files,
options=make_request_options(
@@ -1343,7 +1343,7 @@ async def add_collaborator(
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
- f"/chat/sessions/{chat_id}/collaborators",
+ path_template("/chat/sessions/{chat_id}/collaborators", chat_id=chat_id),
body=await async_maybe_transform(
{
"email": email,
@@ -1386,7 +1386,7 @@ async def add_git_commit(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/chat/sessions/{session_id}/commits",
+ path_template("/chat/sessions/{session_id}/commits", session_id=session_id),
body=await async_maybe_transform(
{"commit_hash": commit_hash}, chat_add_git_commit_params.ChatAddGitCommitParams
),
@@ -1424,7 +1424,7 @@ async def admin_issue_found(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._post(
- f"/chat/sessions/{chat_id}/admin/issue_found",
+ path_template("/chat/sessions/{chat_id}/admin/issue_found", chat_id=chat_id),
body=await async_maybe_transform(
{
"message": message,
@@ -1462,7 +1462,7 @@ async def compress(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/chat/sessions/{session_id}/compress",
+ path_template("/chat/sessions/{session_id}/compress", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1542,7 +1542,7 @@ async def copy_node_output_by_code_hash(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/chat/sessions/{session_id}/nodes/by_code_hash",
+ path_template("/chat/sessions/{session_id}/nodes/by_code_hash", session_id=session_id),
body=await async_maybe_transform(
{
"code_md5_hash": code_md5_hash,
@@ -1628,7 +1628,7 @@ async def delete_input_file(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._post(
- f"/chat/input-files/delete/{chat_id}",
+ path_template("/chat/input-files/delete/{chat_id}", chat_id=chat_id),
body=await async_maybe_transform(
{"filenames": filenames}, chat_delete_input_file_params.ChatDeleteInputFileParams
),
@@ -1664,7 +1664,7 @@ async def delete_session(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._delete(
- f"/chat/sessions/{session_id}",
+ path_template("/chat/sessions/{session_id}", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1697,7 +1697,7 @@ async def get_dependencies(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._get(
- f"/chat/sessions/{session_id}/dependencies",
+ path_template("/chat/sessions/{session_id}/dependencies", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1733,7 +1733,7 @@ async def get_git_commit(
if not commit_hash:
raise ValueError(f"Expected a non-empty value for `commit_hash` but received {commit_hash!r}")
return await self._get(
- f"/chat/sessions/{chat_id}/commits/{commit_hash}",
+ path_template("/chat/sessions/{chat_id}/commits/{commit_hash}", chat_id=chat_id, commit_hash=commit_hash),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1766,7 +1766,7 @@ async def get_partial_chats(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return await self._get(
- f"/chat/{chat_session_id}/partial-chats",
+ path_template("/chat/{chat_session_id}/partial-chats", chat_session_id=chat_session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1799,7 +1799,7 @@ async def get_session(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._get(
- f"/chat/sessions/{session_id}",
+ path_template("/chat/sessions/{session_id}", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1832,7 +1832,7 @@ async def get_session_timeline(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._get(
- f"/chat/sessions/{session_id}/timeline",
+ path_template("/chat/sessions/{session_id}/timeline", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1863,7 +1863,7 @@ async def get_template(
if not template_id:
raise ValueError(f"Expected a non-empty value for `template_id` but received {template_id!r}")
return await self._get(
- f"/chat/templates/{template_id}",
+ path_template("/chat/templates/{template_id}", template_id=template_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1900,7 +1900,7 @@ async def grant_admin_override(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._post(
- f"/chat/sessions/{chat_id}/admin_override",
+ path_template("/chat/sessions/{chat_id}/admin_override", chat_id=chat_id),
body=await async_maybe_transform(
{
"duration_hours": duration_hours,
@@ -1940,7 +1940,7 @@ async def list_collaborators(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._get(
- f"/chat/sessions/{chat_id}/collaborators",
+ path_template("/chat/sessions/{chat_id}/collaborators", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1976,7 +1976,7 @@ async def list_dashboards(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._get(
- f"/chat/sessions/{chat_id}/dashboards",
+ path_template("/chat/sessions/{chat_id}/dashboards", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -2015,7 +2015,7 @@ async def list_input_files(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._get(
- f"/chat/input-files/list/{chat_id}",
+ path_template("/chat/input-files/list/{chat_id}", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2161,7 +2161,7 @@ async def load_input_file(
raise ValueError(f"Expected a non-empty value for `filename` but received {filename!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return await self._get(
- f"/chat/input-files/download/{chat_id}/{filename}",
+ path_template("/chat/input-files/download/{chat_id}/{filename}", chat_id=chat_id, filename=filename),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2197,7 +2197,7 @@ async def load_input_files(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._get(
- f"/chat/input-files/download-all/{chat_id}",
+ path_template("/chat/input-files/download-all/{chat_id}", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -2237,7 +2237,7 @@ async def make_permanent(
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._patch(
- f"/chat/sessions/{session_id}/make-permanent",
+ path_template("/chat/sessions/{session_id}/make-permanent", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2272,7 +2272,7 @@ async def remove_collaborator(
raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/chat/sessions/{chat_id}/collaborators/{user_id}",
+ path_template("/chat/sessions/{chat_id}/collaborators/{user_id}", chat_id=chat_id, user_id=user_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2308,7 +2308,7 @@ async def revert_to_commit(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/chat/sessions/{session_id}/revert",
+ path_template("/chat/sessions/{session_id}/revert", session_id=session_id),
body=await async_maybe_transform(
{"commit_hash": commit_hash}, chat_revert_to_commit_params.ChatRevertToCommitParams
),
@@ -2345,7 +2345,7 @@ async def simulate_prompt(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return await self._post(
- f"/chat/{chat_session_id}/simulate-prompt",
+ path_template("/chat/{chat_session_id}/simulate-prompt", chat_session_id=chat_session_id),
body=await async_maybe_transform(
{"chat_prompt": chat_prompt}, chat_simulate_prompt_params.ChatSimulatePromptParams
),
@@ -2383,7 +2383,7 @@ async def update_session(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._patch(
- f"/chat/sessions/{session_id}",
+ path_template("/chat/sessions/{session_id}", session_id=session_id),
body=await async_maybe_transform(
{
"message_head": message_head,
@@ -2424,7 +2424,7 @@ async def update_session_favorite(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._patch(
- f"/chat/sessions/{session_id}/favorite",
+ path_template("/chat/sessions/{session_id}/favorite", session_id=session_id),
body=await async_maybe_transform(
{"is_favorite": is_favorite}, chat_update_session_favorite_params.ChatUpdateSessionFavoriteParams
),
@@ -2461,7 +2461,7 @@ async def update_visibility(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._put(
- f"/chat/sessions/{session_id}/visibility",
+ path_template("/chat/sessions/{session_id}/visibility", session_id=session_id),
body=await async_maybe_transform(
{"visibility": visibility}, chat_update_visibility_params.ChatUpdateVisibilityParams
),
@@ -2512,7 +2512,7 @@ async def upload_input_file(
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
- f"/chat/input-files/upload/{chat_id}",
+ path_template("/chat/input-files/upload/{chat_id}", chat_id=chat_id),
body=await async_maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
files=files,
options=make_request_options(
diff --git a/src/structify/resources/code.py b/src/structify/resources/code.py
index c3ad813b2..016dfa512 100644
--- a/src/structify/resources/code.py
+++ b/src/structify/resources/code.py
@@ -8,7 +8,7 @@
from ..types import code_generate_code_params, code_apply_manual_edit_params, code_interrupt_generation_params
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -71,7 +71,7 @@ def apply_manual_edit(
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
- f"/code/apply-manual-edit/{chat_id}",
+ path_template("/code/apply-manual-edit/{chat_id}", chat_id=chat_id),
body=maybe_transform(
{
"code": code,
@@ -229,7 +229,7 @@ async def apply_manual_edit(
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
- f"/code/apply-manual-edit/{chat_id}",
+ path_template("/code/apply-manual-edit/{chat_id}", chat_id=chat_id),
body=await async_maybe_transform(
{
"code": code,
diff --git a/src/structify/resources/connector_catalog/admin.py b/src/structify/resources/connector_catalog/admin.py
index a2e14c043..21b4925cd 100644
--- a/src/structify/resources/connector_catalog/admin.py
+++ b/src/structify/resources/connector_catalog/admin.py
@@ -19,7 +19,7 @@
omit,
not_given,
)
-from ..._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..._utils import extract_files, path_template, maybe_transform, deepcopy_minimal, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -361,7 +361,7 @@ def delete_catalog(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/admin/connector-catalog/{id}",
+ path_template("/admin/connector-catalog/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -395,7 +395,7 @@ def delete_credential_field(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/admin/connector-catalog/credential-fields/{id}",
+ path_template("/admin/connector-catalog/credential-fields/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -427,7 +427,7 @@ def delete_scope(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/admin/connector-catalog/scopes/{id}",
+ path_template("/admin/connector-catalog/scopes/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -518,7 +518,7 @@ def update_auth_method(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._patch(
- f"/admin/connector-catalog/auth-methods/{id}",
+ path_template("/admin/connector-catalog/auth-methods/{id}", id=id),
body=maybe_transform(
{
"is_active": is_active,
@@ -564,7 +564,7 @@ def update_catalog(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._patch(
- f"/admin/connector-catalog/{id}",
+ path_template("/admin/connector-catalog/{id}", id=id),
body=maybe_transform(
{
"categories": categories,
@@ -615,7 +615,7 @@ def update_credential_field(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._patch(
- f"/admin/connector-catalog/credential-fields/{id}",
+ path_template("/admin/connector-catalog/credential-fields/{id}", id=id),
body=maybe_transform(
{
"default_value": default_value,
@@ -663,7 +663,7 @@ def update_scope(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._patch(
- f"/admin/connector-catalog/scopes/{id}",
+ path_template("/admin/connector-catalog/scopes/{id}", id=id),
body=maybe_transform(
{
"is_recommended": is_recommended,
@@ -710,7 +710,7 @@ def upload_logo(
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._put(
- f"/admin/connector-catalog/{slug}/logo",
+ path_template("/admin/connector-catalog/{slug}/logo", slug=slug),
body=maybe_transform(body, admin_upload_logo_params.AdminUploadLogoParams),
files=files,
options=make_request_options(
@@ -1023,7 +1023,7 @@ async def delete_catalog(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/admin/connector-catalog/{id}",
+ path_template("/admin/connector-catalog/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1057,7 +1057,7 @@ async def delete_credential_field(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/admin/connector-catalog/credential-fields/{id}",
+ path_template("/admin/connector-catalog/credential-fields/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1089,7 +1089,7 @@ async def delete_scope(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/admin/connector-catalog/scopes/{id}",
+ path_template("/admin/connector-catalog/scopes/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1180,7 +1180,7 @@ async def update_auth_method(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._patch(
- f"/admin/connector-catalog/auth-methods/{id}",
+ path_template("/admin/connector-catalog/auth-methods/{id}", id=id),
body=await async_maybe_transform(
{
"is_active": is_active,
@@ -1226,7 +1226,7 @@ async def update_catalog(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._patch(
- f"/admin/connector-catalog/{id}",
+ path_template("/admin/connector-catalog/{id}", id=id),
body=await async_maybe_transform(
{
"categories": categories,
@@ -1277,7 +1277,7 @@ async def update_credential_field(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._patch(
- f"/admin/connector-catalog/credential-fields/{id}",
+ path_template("/admin/connector-catalog/credential-fields/{id}", id=id),
body=await async_maybe_transform(
{
"default_value": default_value,
@@ -1325,7 +1325,7 @@ async def update_scope(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._patch(
- f"/admin/connector-catalog/scopes/{id}",
+ path_template("/admin/connector-catalog/scopes/{id}", id=id),
body=await async_maybe_transform(
{
"is_recommended": is_recommended,
@@ -1372,7 +1372,7 @@ async def upload_logo(
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._put(
- f"/admin/connector-catalog/{slug}/logo",
+ path_template("/admin/connector-catalog/{slug}/logo", slug=slug),
body=await async_maybe_transform(body, admin_upload_logo_params.AdminUploadLogoParams),
files=files,
options=make_request_options(
diff --git a/src/structify/resources/connector_catalog/connector_catalog.py b/src/structify/resources/connector_catalog/connector_catalog.py
index ce8920a03..1dcfb0683 100644
--- a/src/structify/resources/connector_catalog/connector_catalog.py
+++ b/src/structify/resources/connector_catalog/connector_catalog.py
@@ -16,7 +16,7 @@
)
from ...types import connector_catalog_list_params
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -142,7 +142,7 @@ def get(
if not slug:
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
return self._get(
- f"/connector-catalog/{slug}",
+ path_template("/connector-catalog/{slug}", slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -174,7 +174,7 @@ def get_logo(
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return self._get(
- f"/connector-catalog/{slug}/logo",
+ path_template("/connector-catalog/{slug}/logo", slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -284,7 +284,7 @@ async def get(
if not slug:
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
return await self._get(
- f"/connector-catalog/{slug}",
+ path_template("/connector-catalog/{slug}", slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -316,7 +316,7 @@ async def get_logo(
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return await self._get(
- f"/connector-catalog/{slug}/logo",
+ path_template("/connector-catalog/{slug}/logo", slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 6a2301e83..29589882c 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -23,7 +23,7 @@
connector_delete_schema_object_params,
)
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import required_args, maybe_transform, async_maybe_transform
+from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -171,7 +171,7 @@ def update(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._patch(
- f"/connectors/{connector_id}",
+ path_template("/connectors/{connector_id}", connector_id=connector_id),
body=maybe_transform(
{
"connector_category": connector_category,
@@ -260,7 +260,7 @@ def delete(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/connectors/{connector_id}",
+ path_template("/connectors/{connector_id}", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -414,7 +414,7 @@ def add_schema_object(
return cast(
ConnectorAddSchemaObjectResponse,
self._post(
- f"/connectors/{connector_id}/schema_object",
+ path_template("/connectors/{connector_id}/schema_object", connector_id=connector_id),
body=maybe_transform(
{
"name": name,
@@ -465,7 +465,7 @@ def create_secret(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
- f"/connectors/{connector_id}/secrets",
+ path_template("/connectors/{connector_id}/secrets", connector_id=connector_id),
body=maybe_transform(
{
"secret_name": secret_name,
@@ -600,7 +600,7 @@ def delete_schema_object(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._delete(
- f"/connectors/{connector_id}/schema_object",
+ path_template("/connectors/{connector_id}/schema_object", connector_id=connector_id),
body=maybe_transform(
{
"id": id,
@@ -642,7 +642,9 @@ def delete_secret(
raise ValueError(f"Expected a non-empty value for `secret_name` but received {secret_name!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/connectors/{connector_id}/secrets/{secret_name}",
+ path_template(
+ "/connectors/{connector_id}/secrets/{secret_name}", connector_id=connector_id, secret_name=secret_name
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -680,7 +682,7 @@ def explore(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
- f"/connectors/{connector_id}/explore",
+ path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=maybe_transform(
{
"database_id": database_id,
@@ -720,7 +722,7 @@ def get(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}",
+ path_template("/connectors/{connector_id}", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -753,7 +755,7 @@ def get_clarification_requests(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}/clarification-requests",
+ path_template("/connectors/{connector_id}/clarification-requests", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -786,7 +788,7 @@ def get_exploration_runs(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}/explore/runs",
+ path_template("/connectors/{connector_id}/explore/runs", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -817,7 +819,7 @@ def get_exploration_status(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}/explore/status",
+ path_template("/connectors/{connector_id}/explore/status", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -854,7 +856,7 @@ def get_explorer_chat(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}/explore/chat",
+ path_template("/connectors/{connector_id}/explore/chat", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -891,7 +893,7 @@ def get_store(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}/store",
+ path_template("/connectors/{connector_id}/store", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -922,7 +924,7 @@ def get_table_path(
if not table_id:
raise ValueError(f"Expected a non-empty value for `table_id` but received {table_id!r}")
return self._get(
- f"/connectors/tables/{table_id}/path",
+ path_template("/connectors/tables/{table_id}/path", table_id=table_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -975,7 +977,7 @@ def list_tables(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- f"/connectors/{connector_id}/tables",
+ path_template("/connectors/{connector_id}/tables", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1027,7 +1029,9 @@ def resolve_clarification(
raise ValueError(f"Expected a non-empty value for `clarification_id` but received {clarification_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._patch(
- f"/connectors/clarification-requests/{clarification_id}/resolve",
+ path_template(
+ "/connectors/clarification-requests/{clarification_id}/resolve", clarification_id=clarification_id
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1136,7 +1140,7 @@ def update_column(
raise ValueError(f"Expected a non-empty value for `column_id` but received {column_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._patch(
- f"/connectors/columns/{column_id}",
+ path_template("/connectors/columns/{column_id}", column_id=column_id),
body=maybe_transform({"notes": notes}, connector_update_column_params.ConnectorUpdateColumnParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -1172,7 +1176,7 @@ def update_table(
if not table_id:
raise ValueError(f"Expected a non-empty value for `table_id` but received {table_id!r}")
return self._patch(
- f"/connectors/tables/{table_id}",
+ path_template("/connectors/tables/{table_id}", table_id=table_id),
body=maybe_transform(
{
"description": description,
@@ -1294,7 +1298,7 @@ async def update(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._patch(
- f"/connectors/{connector_id}",
+ path_template("/connectors/{connector_id}", connector_id=connector_id),
body=await async_maybe_transform(
{
"connector_category": connector_category,
@@ -1383,7 +1387,7 @@ async def delete(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/connectors/{connector_id}",
+ path_template("/connectors/{connector_id}", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1537,7 +1541,7 @@ async def add_schema_object(
return cast(
ConnectorAddSchemaObjectResponse,
await self._post(
- f"/connectors/{connector_id}/schema_object",
+ path_template("/connectors/{connector_id}/schema_object", connector_id=connector_id),
body=await async_maybe_transform(
{
"name": name,
@@ -1588,7 +1592,7 @@ async def create_secret(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
- f"/connectors/{connector_id}/secrets",
+ path_template("/connectors/{connector_id}/secrets", connector_id=connector_id),
body=await async_maybe_transform(
{
"secret_name": secret_name,
@@ -1723,7 +1727,7 @@ async def delete_schema_object(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._delete(
- f"/connectors/{connector_id}/schema_object",
+ path_template("/connectors/{connector_id}/schema_object", connector_id=connector_id),
body=await async_maybe_transform(
{
"id": id,
@@ -1765,7 +1769,9 @@ async def delete_secret(
raise ValueError(f"Expected a non-empty value for `secret_name` but received {secret_name!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/connectors/{connector_id}/secrets/{secret_name}",
+ path_template(
+ "/connectors/{connector_id}/secrets/{secret_name}", connector_id=connector_id, secret_name=secret_name
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1803,7 +1809,7 @@ async def explore(
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
- f"/connectors/{connector_id}/explore",
+ path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=await async_maybe_transform(
{
"database_id": database_id,
@@ -1843,7 +1849,7 @@ async def get(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}",
+ path_template("/connectors/{connector_id}", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1876,7 +1882,7 @@ async def get_clarification_requests(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}/clarification-requests",
+ path_template("/connectors/{connector_id}/clarification-requests", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1909,7 +1915,7 @@ async def get_exploration_runs(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}/explore/runs",
+ path_template("/connectors/{connector_id}/explore/runs", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1940,7 +1946,7 @@ async def get_exploration_status(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}/explore/status",
+ path_template("/connectors/{connector_id}/explore/status", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1977,7 +1983,7 @@ async def get_explorer_chat(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}/explore/chat",
+ path_template("/connectors/{connector_id}/explore/chat", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -2014,7 +2020,7 @@ async def get_store(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}/store",
+ path_template("/connectors/{connector_id}/store", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2045,7 +2051,7 @@ async def get_table_path(
if not table_id:
raise ValueError(f"Expected a non-empty value for `table_id` but received {table_id!r}")
return await self._get(
- f"/connectors/tables/{table_id}/path",
+ path_template("/connectors/tables/{table_id}/path", table_id=table_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2098,7 +2104,7 @@ async def list_tables(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- f"/connectors/{connector_id}/tables",
+ path_template("/connectors/{connector_id}/tables", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2150,7 +2156,9 @@ async def resolve_clarification(
raise ValueError(f"Expected a non-empty value for `clarification_id` but received {clarification_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._patch(
- f"/connectors/clarification-requests/{clarification_id}/resolve",
+ path_template(
+ "/connectors/clarification-requests/{clarification_id}/resolve", clarification_id=clarification_id
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -2261,7 +2269,7 @@ async def update_column(
raise ValueError(f"Expected a non-empty value for `column_id` but received {column_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._patch(
- f"/connectors/columns/{column_id}",
+ path_template("/connectors/columns/{column_id}", column_id=column_id),
body=await async_maybe_transform(
{"notes": notes}, connector_update_column_params.ConnectorUpdateColumnParams
),
@@ -2299,7 +2307,7 @@ async def update_table(
if not table_id:
raise ValueError(f"Expected a non-empty value for `table_id` but received {table_id!r}")
return await self._patch(
- f"/connectors/tables/{table_id}",
+ path_template("/connectors/tables/{table_id}", table_id=table_id),
body=await async_maybe_transform(
{
"description": description,
diff --git a/src/structify/resources/connectors/type_snippets.py b/src/structify/resources/connectors/type_snippets.py
index 84a1b11a1..d7f8bb234 100644
--- a/src/structify/resources/connectors/type_snippets.py
+++ b/src/structify/resources/connectors/type_snippets.py
@@ -7,7 +7,7 @@
import httpx
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -68,7 +68,7 @@ def upsert(
if not connector_type:
raise ValueError(f"Expected a non-empty value for `connector_type` but received {connector_type!r}")
return self._put(
- f"/connector-type-snippets/{connector_type}",
+ path_template("/connector-type-snippets/{connector_type}", connector_type=connector_type),
body=maybe_transform({"usage_snippet": usage_snippet}, type_snippet_upsert_params.TypeSnippetUpsertParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -122,7 +122,7 @@ async def upsert(
if not connector_type:
raise ValueError(f"Expected a non-empty value for `connector_type` but received {connector_type!r}")
return await self._put(
- f"/connector-type-snippets/{connector_type}",
+ path_template("/connector-type-snippets/{connector_type}", connector_type=connector_type),
body=await async_maybe_transform(
{"usage_snippet": usage_snippet}, type_snippet_upsert_params.TypeSnippetUpsertParams
),
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index 377bd22a2..1184844cb 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -12,7 +12,7 @@
from ..types import job_list_params, job_status_params
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -145,7 +145,7 @@ def cancel(
if not uuid:
raise ValueError(f"Expected a non-empty value for `uuid` but received {uuid!r}")
return self._post(
- f"/jobs/cancel/{uuid}",
+ path_template("/jobs/cancel/{uuid}", uuid=uuid),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -176,7 +176,7 @@ def get(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return self._get(
- f"/jobs/get/{job_id}",
+ path_template("/jobs/get/{job_id}", job_id=job_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -207,7 +207,7 @@ def get_events(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return self._get(
- f"/jobs/{job_id}/events",
+ path_template("/jobs/{job_id}/events", job_id=job_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -463,7 +463,7 @@ async def cancel(
if not uuid:
raise ValueError(f"Expected a non-empty value for `uuid` but received {uuid!r}")
return await self._post(
- f"/jobs/cancel/{uuid}",
+ path_template("/jobs/cancel/{uuid}", uuid=uuid),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -494,7 +494,7 @@ async def get(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return await self._get(
- f"/jobs/get/{job_id}",
+ path_template("/jobs/get/{job_id}", job_id=job_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -525,7 +525,7 @@ async def get_events(
if not job_id:
raise ValueError(f"Expected a non-empty value for `job_id` but received {job_id!r}")
return await self._get(
- f"/jobs/{job_id}/events",
+ path_template("/jobs/{job_id}/events", job_id=job_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/projects.py b/src/structify/resources/projects.py
index ddbd2488a..98eb1c2b5 100644
--- a/src/structify/resources/projects.py
+++ b/src/structify/resources/projects.py
@@ -8,7 +8,7 @@
from ..types import ProjectVisibility, project_update_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -80,7 +80,7 @@ def update(
if not project_id:
raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}")
return self._patch(
- f"/team/{team_id}/project/{project_id}",
+ path_template("/team/{team_id}/project/{project_id}", team_id=team_id, project_id=project_id),
body=maybe_transform(
{
"collaborators": collaborators,
@@ -123,7 +123,7 @@ def delete(
if not project_id:
raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}")
return self._delete(
- f"/team/{team_id}/project/{project_id}",
+ path_template("/team/{team_id}/project/{project_id}", team_id=team_id, project_id=project_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -157,7 +157,7 @@ def get(
if not project_id:
raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}")
return self._get(
- f"/team/{team_id}/project/{project_id}",
+ path_template("/team/{team_id}/project/{project_id}", team_id=team_id, project_id=project_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -218,7 +218,7 @@ async def update(
if not project_id:
raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}")
return await self._patch(
- f"/team/{team_id}/project/{project_id}",
+ path_template("/team/{team_id}/project/{project_id}", team_id=team_id, project_id=project_id),
body=await async_maybe_transform(
{
"collaborators": collaborators,
@@ -261,7 +261,7 @@ async def delete(
if not project_id:
raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}")
return await self._delete(
- f"/team/{team_id}/project/{project_id}",
+ path_template("/team/{team_id}/project/{project_id}", team_id=team_id, project_id=project_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -295,7 +295,7 @@ async def get(
if not project_id:
raise ValueError(f"Expected a non-empty value for `project_id` but received {project_id!r}")
return await self._get(
- f"/team/{team_id}/project/{project_id}",
+ path_template("/team/{team_id}/project/{project_id}", team_id=team_id, project_id=project_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/public_sessions.py b/src/structify/resources/public_sessions.py
index 65bc52ffc..eb8136ff7 100644
--- a/src/structify/resources/public_sessions.py
+++ b/src/structify/resources/public_sessions.py
@@ -5,6 +5,7 @@
import httpx
from .._types import Body, Query, Headers, NotGiven, not_given
+from .._utils import path_template
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -71,7 +72,7 @@ def get_latest_workflow(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return self._get(
- f"/public/chat/{chat_session_id}/latest-workflow",
+ path_template("/public/chat/{chat_session_id}/latest-workflow", chat_session_id=chat_session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -103,7 +104,7 @@ def get_node_output_data(
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return self._get(
- f"/public/nodes/{node_id}/output_data",
+ path_template("/public/nodes/{node_id}/output_data", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -155,7 +156,7 @@ async def get_latest_workflow(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return await self._get(
- f"/public/chat/{chat_session_id}/latest-workflow",
+ path_template("/public/chat/{chat_session_id}/latest-workflow", chat_session_id=chat_session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -187,7 +188,7 @@ async def get_node_output_data(
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return await self._get(
- f"/public/nodes/{node_id}/output_data",
+ path_template("/public/nodes/{node_id}/output_data", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/sandbox.py b/src/structify/resources/sandbox.py
index 62b8ce497..1a47e4931 100644
--- a/src/structify/resources/sandbox.py
+++ b/src/structify/resources/sandbox.py
@@ -8,7 +8,7 @@
from ..types import sandbox_get_params, sandbox_update_status_params
from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -71,7 +71,7 @@ def list(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._get(
- f"/sandbox/list/{chat_id}",
+ path_template("/sandbox/list/{chat_id}", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -105,7 +105,7 @@ def get(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return self._post(
- f"/sandbox/live/{chat_id}",
+ path_template("/sandbox/live/{chat_id}", chat_id=chat_id),
body=maybe_transform(
{"modal_control_service_url_override": modal_control_service_url_override},
sandbox_get_params.SandboxGetParams,
@@ -140,7 +140,7 @@ def get_metrics(
if not sandbox_id:
raise ValueError(f"Expected a non-empty value for `sandbox_id` but received {sandbox_id!r}")
return self._get(
- f"/sandbox/{sandbox_id}/metrics",
+ path_template("/sandbox/{sandbox_id}/metrics", sandbox_id=sandbox_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -172,7 +172,7 @@ def update_status(
if not sandbox_id:
raise ValueError(f"Expected a non-empty value for `sandbox_id` but received {sandbox_id!r}")
return self._patch(
- f"/sandbox/{sandbox_id}/status",
+ path_template("/sandbox/{sandbox_id}/status", sandbox_id=sandbox_id),
body=maybe_transform({"status": status}, sandbox_update_status_params.SandboxUpdateStatusParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -227,7 +227,7 @@ async def list(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._get(
- f"/sandbox/list/{chat_id}",
+ path_template("/sandbox/list/{chat_id}", chat_id=chat_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -261,7 +261,7 @@ async def get(
if not chat_id:
raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
return await self._post(
- f"/sandbox/live/{chat_id}",
+ path_template("/sandbox/live/{chat_id}", chat_id=chat_id),
body=await async_maybe_transform(
{"modal_control_service_url_override": modal_control_service_url_override},
sandbox_get_params.SandboxGetParams,
@@ -296,7 +296,7 @@ async def get_metrics(
if not sandbox_id:
raise ValueError(f"Expected a non-empty value for `sandbox_id` but received {sandbox_id!r}")
return await self._get(
- f"/sandbox/{sandbox_id}/metrics",
+ path_template("/sandbox/{sandbox_id}/metrics", sandbox_id=sandbox_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -328,7 +328,7 @@ async def update_status(
if not sandbox_id:
raise ValueError(f"Expected a non-empty value for `sandbox_id` but received {sandbox_id!r}")
return await self._patch(
- f"/sandbox/{sandbox_id}/status",
+ path_template("/sandbox/{sandbox_id}/status", sandbox_id=sandbox_id),
body=await async_maybe_transform(
{"status": status}, sandbox_update_status_params.SandboxUpdateStatusParams
),
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 19cea9a1e..08f675436 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -25,7 +25,14 @@
session_upload_node_visualization_output_params,
)
from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
-from .._utils import extract_files, required_args, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._utils import (
+ extract_files,
+ path_template,
+ required_args,
+ maybe_transform,
+ deepcopy_minimal,
+ async_maybe_transform,
+)
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -109,7 +116,7 @@ def confirm_node(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._post(
- f"/sessions/nodes/{node_id}/confirm",
+ path_template("/sessions/nodes/{node_id}/confirm", node_id=node_id),
body=maybe_transform({"confirmed": confirmed}, session_confirm_node_params.SessionConfirmNodeParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -181,7 +188,7 @@ def edit_node_output(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._post(
- f"/sessions/nodes/{node_id}/edit_output",
+ path_template("/sessions/nodes/{node_id}/edit_output", node_id=node_id),
body=maybe_transform({"edits": edits}, session_edit_node_output_params.SessionEditNodeOutputParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -222,7 +229,7 @@ def finalize_dag(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/sessions/{session_id}/dag_ready",
+ path_template("/sessions/{session_id}/dag_ready", session_id=session_id),
body=maybe_transform(
{
"edges": edges,
@@ -261,7 +268,7 @@ def get_dag(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._get(
- f"/sessions/{session_id}/dag",
+ path_template("/sessions/{session_id}/dag", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -298,7 +305,7 @@ def get_events(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._get(
- f"/sessions/nodes/{node_id}/events",
+ path_template("/sessions/nodes/{node_id}/events", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -341,7 +348,7 @@ def get_node(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._get(
- f"/sessions/nodes/{node_id}",
+ path_template("/sessions/nodes/{node_id}", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -374,7 +381,7 @@ def get_node_logs(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._get(
- f"/sessions/node/{node_id}/logs",
+ path_template("/sessions/node/{node_id}/logs", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -406,7 +413,7 @@ def get_node_output_data(
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return self._get(
- f"/sessions/nodes/{node_id}/output_data",
+ path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -437,7 +444,7 @@ def get_node_progress(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._get(
- f"/sessions/nodes/{node_id}/progress",
+ path_template("/sessions/nodes/{node_id}/progress", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -469,7 +476,7 @@ def kill_jobs(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/sessions/{session_id}/kill_jobs",
+ path_template("/sessions/{session_id}/kill_jobs", session_id=session_id),
body=maybe_transform({"message": message}, session_kill_jobs_params.SessionKillJobsParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -505,7 +512,7 @@ def mark_errored(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._patch(
- f"/sessions/{session_id}/error",
+ path_template("/sessions/{session_id}/error", session_id=session_id),
body=maybe_transform(
{
"error_message": error_message,
@@ -547,7 +554,7 @@ def request_confirmation(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._post(
- f"/sessions/nodes/{node_id}/request_confirmation",
+ path_template("/sessions/nodes/{node_id}/request_confirmation", node_id=node_id),
body=maybe_transform(
{
"operation": operation,
@@ -585,7 +592,7 @@ def trigger_review(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/sessions/{session_id}/trigger_review",
+ path_template("/sessions/{session_id}/trigger_review", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -620,7 +627,7 @@ def update_node(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._patch(
- f"/sessions/nodes/{node_id}",
+ path_template("/sessions/nodes/{node_id}", node_id=node_id),
body=maybe_transform(
{
"execution_status": execution_status,
@@ -664,7 +671,7 @@ def update_node_progress(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._patch(
- f"/sessions/nodes/{node_id}/progress",
+ path_template("/sessions/nodes/{node_id}/progress", node_id=node_id),
body=maybe_transform(
{
"current": current,
@@ -750,7 +757,7 @@ def upload_dashboard_layout(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return self._post(
- f"/sessions/{session_id}/dashboard_layout",
+ path_template("/sessions/{session_id}/dashboard_layout", session_id=session_id),
body=maybe_transform(
{
"layout": layout,
@@ -813,7 +820,7 @@ def upload_node_output_data(
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return self._post(
- f"/sessions/nodes/{node_id}/output_data",
+ path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
body=maybe_transform(body, session_upload_node_output_data_params.SessionUploadNodeOutputDataParams),
files=files,
options=make_request_options(
@@ -847,7 +854,7 @@ def upload_node_visualization_output(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return self._post(
- f"/sessions/nodes/{node_id}/visualization_output",
+ path_template("/sessions/nodes/{node_id}/visualization_output", node_id=node_id),
body=maybe_transform(
{"visualization_output": visualization_output},
session_upload_node_visualization_output_params.SessionUploadNodeVisualizationOutputParams,
@@ -904,7 +911,7 @@ async def confirm_node(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._post(
- f"/sessions/nodes/{node_id}/confirm",
+ path_template("/sessions/nodes/{node_id}/confirm", node_id=node_id),
body=await async_maybe_transform(
{"confirmed": confirmed}, session_confirm_node_params.SessionConfirmNodeParams
),
@@ -978,7 +985,7 @@ async def edit_node_output(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._post(
- f"/sessions/nodes/{node_id}/edit_output",
+ path_template("/sessions/nodes/{node_id}/edit_output", node_id=node_id),
body=await async_maybe_transform(
{"edits": edits}, session_edit_node_output_params.SessionEditNodeOutputParams
),
@@ -1021,7 +1028,7 @@ async def finalize_dag(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/sessions/{session_id}/dag_ready",
+ path_template("/sessions/{session_id}/dag_ready", session_id=session_id),
body=await async_maybe_transform(
{
"edges": edges,
@@ -1060,7 +1067,7 @@ async def get_dag(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._get(
- f"/sessions/{session_id}/dag",
+ path_template("/sessions/{session_id}/dag", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1097,7 +1104,7 @@ async def get_events(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._get(
- f"/sessions/nodes/{node_id}/events",
+ path_template("/sessions/nodes/{node_id}/events", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -1140,7 +1147,7 @@ async def get_node(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._get(
- f"/sessions/nodes/{node_id}",
+ path_template("/sessions/nodes/{node_id}", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1173,7 +1180,7 @@ async def get_node_logs(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._get(
- f"/sessions/node/{node_id}/logs",
+ path_template("/sessions/node/{node_id}/logs", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1205,7 +1212,7 @@ async def get_node_output_data(
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
return await self._get(
- f"/sessions/nodes/{node_id}/output_data",
+ path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1236,7 +1243,7 @@ async def get_node_progress(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._get(
- f"/sessions/nodes/{node_id}/progress",
+ path_template("/sessions/nodes/{node_id}/progress", node_id=node_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1268,7 +1275,7 @@ async def kill_jobs(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/sessions/{session_id}/kill_jobs",
+ path_template("/sessions/{session_id}/kill_jobs", session_id=session_id),
body=await async_maybe_transform({"message": message}, session_kill_jobs_params.SessionKillJobsParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -1304,7 +1311,7 @@ async def mark_errored(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._patch(
- f"/sessions/{session_id}/error",
+ path_template("/sessions/{session_id}/error", session_id=session_id),
body=await async_maybe_transform(
{
"error_message": error_message,
@@ -1346,7 +1353,7 @@ async def request_confirmation(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._post(
- f"/sessions/nodes/{node_id}/request_confirmation",
+ path_template("/sessions/nodes/{node_id}/request_confirmation", node_id=node_id),
body=await async_maybe_transform(
{
"operation": operation,
@@ -1384,7 +1391,7 @@ async def trigger_review(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/sessions/{session_id}/trigger_review",
+ path_template("/sessions/{session_id}/trigger_review", session_id=session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1419,7 +1426,7 @@ async def update_node(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._patch(
- f"/sessions/nodes/{node_id}",
+ path_template("/sessions/nodes/{node_id}", node_id=node_id),
body=await async_maybe_transform(
{
"execution_status": execution_status,
@@ -1463,7 +1470,7 @@ async def update_node_progress(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._patch(
- f"/sessions/nodes/{node_id}/progress",
+ path_template("/sessions/nodes/{node_id}/progress", node_id=node_id),
body=await async_maybe_transform(
{
"current": current,
@@ -1549,7 +1556,7 @@ async def upload_dashboard_layout(
if not session_id:
raise ValueError(f"Expected a non-empty value for `session_id` but received {session_id!r}")
return await self._post(
- f"/sessions/{session_id}/dashboard_layout",
+ path_template("/sessions/{session_id}/dashboard_layout", session_id=session_id),
body=await async_maybe_transform(
{
"layout": layout,
@@ -1612,7 +1619,7 @@ async def upload_node_output_data(
# multipart/form-data; boundary=---abc--
extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
return await self._post(
- f"/sessions/nodes/{node_id}/output_data",
+ path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
body=await async_maybe_transform(
body, session_upload_node_output_data_params.SessionUploadNodeOutputDataParams
),
@@ -1648,7 +1655,7 @@ async def upload_node_visualization_output(
if not node_id:
raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
return await self._post(
- f"/sessions/nodes/{node_id}/visualization_output",
+ path_template("/sessions/nodes/{node_id}/visualization_output", node_id=node_id),
body=await async_maybe_transform(
{"visualization_output": visualization_output},
session_upload_node_visualization_output_params.SessionUploadNodeVisualizationOutputParams,
diff --git a/src/structify/resources/teams.py b/src/structify/resources/teams.py
index 8bddb0091..45134d829 100644
--- a/src/structify/resources/teams.py
+++ b/src/structify/resources/teams.py
@@ -21,7 +21,7 @@
team_update_member_role_params,
)
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -144,7 +144,7 @@ def update(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._put(
- f"/team/{team_id}",
+ path_template("/team/{team_id}", team_id=team_id),
body=maybe_transform(
{
"daytona_credentials": daytona_credentials,
@@ -242,7 +242,7 @@ def add_member(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._post(
- f"/team/{team_id}/members",
+ path_template("/team/{team_id}/members", team_id=team_id),
body=maybe_transform(
{
"email": email,
@@ -282,7 +282,7 @@ def cancel_invitation(
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/team/{team_id}/invitations",
+ path_template("/team/{team_id}/invitations", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -319,7 +319,7 @@ def create_project(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._post(
- f"/team/{team_id}/projects",
+ path_template("/team/{team_id}/projects", team_id=team_id),
body=maybe_transform(
{
"name": name,
@@ -369,7 +369,7 @@ def credits_usage(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
- f"/team/{team_id}/credits/usage",
+ path_template("/team/{team_id}/credits/usage", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -412,7 +412,7 @@ def get(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
- f"/team/{team_id}",
+ path_template("/team/{team_id}", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -443,7 +443,7 @@ def invitation_details(
if not token:
raise ValueError(f"Expected a non-empty value for `token` but received {token!r}")
return self._get(
- f"/team/invitations/details/{token}",
+ path_template("/team/invitations/details/{token}", token=token),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -474,7 +474,7 @@ def list_members(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
- f"/team/{team_id}/members",
+ path_template("/team/{team_id}/members", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -505,7 +505,7 @@ def list_projects(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
- f"/team/{team_id}/projects",
+ path_template("/team/{team_id}/projects", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -539,7 +539,7 @@ def remove_member(
if not user_id:
raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}")
return self._delete(
- f"/team/{team_id}/members/{user_id}",
+ path_template("/team/{team_id}/members/{user_id}", team_id=team_id, user_id=user_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -570,7 +570,7 @@ def select(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._post(
- f"/team/{team_id}/select",
+ path_template("/team/{team_id}/select", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -605,7 +605,7 @@ def update_member_role(
if not user_id:
raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}")
return self._patch(
- f"/team/{team_id}/members/{user_id}/role",
+ path_template("/team/{team_id}/members/{user_id}/role", team_id=team_id, user_id=user_id),
body=maybe_transform({"role": role}, team_update_member_role_params.TeamUpdateMemberRoleParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -707,7 +707,7 @@ async def update(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._put(
- f"/team/{team_id}",
+ path_template("/team/{team_id}", team_id=team_id),
body=await async_maybe_transform(
{
"daytona_credentials": daytona_credentials,
@@ -807,7 +807,7 @@ async def add_member(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._post(
- f"/team/{team_id}/members",
+ path_template("/team/{team_id}/members", team_id=team_id),
body=await async_maybe_transform(
{
"email": email,
@@ -847,7 +847,7 @@ async def cancel_invitation(
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/team/{team_id}/invitations",
+ path_template("/team/{team_id}/invitations", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -886,7 +886,7 @@ async def create_project(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._post(
- f"/team/{team_id}/projects",
+ path_template("/team/{team_id}/projects", team_id=team_id),
body=await async_maybe_transform(
{
"name": name,
@@ -936,7 +936,7 @@ async def credits_usage(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
- f"/team/{team_id}/credits/usage",
+ path_template("/team/{team_id}/credits/usage", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers,
extra_query=extra_query,
@@ -979,7 +979,7 @@ async def get(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
- f"/team/{team_id}",
+ path_template("/team/{team_id}", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1010,7 +1010,7 @@ async def invitation_details(
if not token:
raise ValueError(f"Expected a non-empty value for `token` but received {token!r}")
return await self._get(
- f"/team/invitations/details/{token}",
+ path_template("/team/invitations/details/{token}", token=token),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1041,7 +1041,7 @@ async def list_members(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
- f"/team/{team_id}/members",
+ path_template("/team/{team_id}/members", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1072,7 +1072,7 @@ async def list_projects(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
- f"/team/{team_id}/projects",
+ path_template("/team/{team_id}/projects", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1106,7 +1106,7 @@ async def remove_member(
if not user_id:
raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}")
return await self._delete(
- f"/team/{team_id}/members/{user_id}",
+ path_template("/team/{team_id}/members/{user_id}", team_id=team_id, user_id=user_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1137,7 +1137,7 @@ async def select(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._post(
- f"/team/{team_id}/select",
+ path_template("/team/{team_id}/select", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -1172,7 +1172,7 @@ async def update_member_role(
if not user_id:
raise ValueError(f"Expected a non-empty value for `user_id` but received {user_id!r}")
return await self._patch(
- f"/team/{team_id}/members/{user_id}/role",
+ path_template("/team/{team_id}/members/{user_id}/role", team_id=team_id, user_id=user_id),
body=await async_maybe_transform({"role": role}, team_update_member_role_params.TeamUpdateMemberRoleParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
diff --git a/src/structify/resources/user/api_keys.py b/src/structify/resources/user/api_keys.py
index 3f22ae0f3..1adb80f3f 100644
--- a/src/structify/resources/user/api_keys.py
+++ b/src/structify/resources/user/api_keys.py
@@ -8,7 +8,7 @@
import httpx
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -129,7 +129,7 @@ def get(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return self._get(
- f"/user/api_keys/{id}",
+ path_template("/user/api_keys/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -161,7 +161,7 @@ def revoke(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/user/api_keys/{id}",
+ path_template("/user/api_keys/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -272,7 +272,7 @@ async def get(
if not id:
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
return await self._get(
- f"/user/api_keys/{id}",
+ path_template("/user/api_keys/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -304,7 +304,7 @@ async def revoke(
raise ValueError(f"Expected a non-empty value for `id` but received {id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/user/api_keys/{id}",
+ path_template("/user/api_keys/{id}", id=id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/whitelabel.py b/src/structify/resources/whitelabel.py
index fabecbb6b..08cd5aa8e 100644
--- a/src/structify/resources/whitelabel.py
+++ b/src/structify/resources/whitelabel.py
@@ -5,6 +5,7 @@
import httpx
from .._types import Body, Query, Headers, NoneType, NotGiven, not_given
+from .._utils import path_template
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -68,7 +69,7 @@ def estimate_cost(
if not path:
raise ValueError(f"Expected a non-empty value for `path` but received {path!r}")
return self._get(
- f"/whitelabel/{service}/estimate-cost/{path}",
+ path_template("/whitelabel/{service}/estimate-cost/{path}", service=service, path=path),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -103,7 +104,7 @@ def proxy_get(
raise ValueError(f"Expected a non-empty value for `path` but received {path!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._get(
- f"/whitelabel/{service}/{path}",
+ path_template("/whitelabel/{service}/{path}", service=service, path=path),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -138,7 +139,7 @@ def proxy_post(
raise ValueError(f"Expected a non-empty value for `path` but received {path!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
- f"/whitelabel/{service}/{path}",
+ path_template("/whitelabel/{service}/{path}", service=service, path=path),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -195,7 +196,7 @@ async def estimate_cost(
if not path:
raise ValueError(f"Expected a non-empty value for `path` but received {path!r}")
return await self._get(
- f"/whitelabel/{service}/estimate-cost/{path}",
+ path_template("/whitelabel/{service}/estimate-cost/{path}", service=service, path=path),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -230,7 +231,7 @@ async def proxy_get(
raise ValueError(f"Expected a non-empty value for `path` but received {path!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._get(
- f"/whitelabel/{service}/{path}",
+ path_template("/whitelabel/{service}/{path}", service=service, path=path),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -265,7 +266,7 @@ async def proxy_post(
raise ValueError(f"Expected a non-empty value for `path` but received {path!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
- f"/whitelabel/{service}/{path}",
+ path_template("/whitelabel/{service}/{path}", service=service, path=path),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/wiki.py b/src/structify/resources/wiki.py
index 915b0eb63..85e6d0b43 100644
--- a/src/structify/resources/wiki.py
+++ b/src/structify/resources/wiki.py
@@ -8,7 +8,7 @@
from ..types import wiki_create_params, wiki_update_params
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -74,7 +74,7 @@ def create(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._post(
- f"/team/{team_id}/wiki",
+ path_template("/team/{team_id}/wiki", team_id=team_id),
body=maybe_transform(
{
"markdown": markdown,
@@ -119,7 +119,7 @@ def update(
if not slug:
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
return self._put(
- f"/team/{team_id}/wiki/{slug}",
+ path_template("/team/{team_id}/wiki/{slug}", team_id=team_id, slug=slug),
body=maybe_transform(
{
"markdown": markdown,
@@ -158,7 +158,7 @@ def list(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return self._get(
- f"/team/{team_id}/wiki",
+ path_template("/team/{team_id}/wiki", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -193,7 +193,7 @@ def delete(
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/team/{team_id}/wiki/{slug}",
+ path_template("/team/{team_id}/wiki/{slug}", team_id=team_id, slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -227,7 +227,7 @@ def get(
if not slug:
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
return self._get(
- f"/team/{team_id}/wiki/{slug}",
+ path_template("/team/{team_id}/wiki/{slug}", team_id=team_id, slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -284,7 +284,7 @@ async def create(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._post(
- f"/team/{team_id}/wiki",
+ path_template("/team/{team_id}/wiki", team_id=team_id),
body=await async_maybe_transform(
{
"markdown": markdown,
@@ -329,7 +329,7 @@ async def update(
if not slug:
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
return await self._put(
- f"/team/{team_id}/wiki/{slug}",
+ path_template("/team/{team_id}/wiki/{slug}", team_id=team_id, slug=slug),
body=await async_maybe_transform(
{
"markdown": markdown,
@@ -368,7 +368,7 @@ async def list(
if not team_id:
raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
return await self._get(
- f"/team/{team_id}/wiki",
+ path_template("/team/{team_id}/wiki", team_id=team_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -403,7 +403,7 @@ async def delete(
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/team/{team_id}/wiki/{slug}",
+ path_template("/team/{team_id}/wiki/{slug}", team_id=team_id, slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -437,7 +437,7 @@ async def get(
if not slug:
raise ValueError(f"Expected a non-empty value for `slug` but received {slug!r}")
return await self._get(
- f"/team/{team_id}/wiki/{slug}",
+ path_template("/team/{team_id}/wiki/{slug}", team_id=team_id, slug=slug),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/src/structify/resources/workflow_schedule.py b/src/structify/resources/workflow_schedule.py
index 111c2d17e..740128e23 100644
--- a/src/structify/resources/workflow_schedule.py
+++ b/src/structify/resources/workflow_schedule.py
@@ -13,7 +13,7 @@
workflow_schedule_get_sessions_params,
)
from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -77,7 +77,7 @@ def create(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return self._post(
- f"/workflow-schedule/{chat_session_id}",
+ path_template("/workflow-schedule/{chat_session_id}", chat_session_id=chat_session_id),
body=maybe_transform(
{
"name": name,
@@ -120,7 +120,7 @@ def update(
if not schedule_id:
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
return self._put(
- f"/workflow-schedule/{schedule_id}",
+ path_template("/workflow-schedule/{schedule_id}", schedule_id=schedule_id),
body=maybe_transform(
{
"cron_schedule": cron_schedule,
@@ -161,7 +161,7 @@ def delete(
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._delete(
- f"/workflow-schedule/{schedule_id}",
+ path_template("/workflow-schedule/{schedule_id}", schedule_id=schedule_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -192,7 +192,7 @@ def get(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return self._get(
- f"/workflow-schedule/{chat_session_id}",
+ path_template("/workflow-schedule/{chat_session_id}", chat_session_id=chat_session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -243,7 +243,7 @@ def get_sessions(
if not schedule_id:
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
return self._post(
- f"/workflow-schedule/{schedule_id}/sessions",
+ path_template("/workflow-schedule/{schedule_id}/sessions", schedule_id=schedule_id),
body=maybe_transform(
{
"limit": limit,
@@ -282,7 +282,7 @@ def pause(
if not schedule_id:
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
return self._patch(
- f"/workflow-schedule/{schedule_id}/pause",
+ path_template("/workflow-schedule/{schedule_id}/pause", schedule_id=schedule_id),
body=maybe_transform({"paused": paused}, workflow_schedule_pause_params.WorkflowSchedulePauseParams),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
@@ -315,7 +315,7 @@ def run(
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
- f"/workflow-schedule/{schedule_id}/run",
+ path_template("/workflow-schedule/{schedule_id}/run", schedule_id=schedule_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -370,7 +370,7 @@ async def create(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return await self._post(
- f"/workflow-schedule/{chat_session_id}",
+ path_template("/workflow-schedule/{chat_session_id}", chat_session_id=chat_session_id),
body=await async_maybe_transform(
{
"name": name,
@@ -413,7 +413,7 @@ async def update(
if not schedule_id:
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
return await self._put(
- f"/workflow-schedule/{schedule_id}",
+ path_template("/workflow-schedule/{schedule_id}", schedule_id=schedule_id),
body=await async_maybe_transform(
{
"cron_schedule": cron_schedule,
@@ -454,7 +454,7 @@ async def delete(
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._delete(
- f"/workflow-schedule/{schedule_id}",
+ path_template("/workflow-schedule/{schedule_id}", schedule_id=schedule_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -485,7 +485,7 @@ async def get(
if not chat_session_id:
raise ValueError(f"Expected a non-empty value for `chat_session_id` but received {chat_session_id!r}")
return await self._get(
- f"/workflow-schedule/{chat_session_id}",
+ path_template("/workflow-schedule/{chat_session_id}", chat_session_id=chat_session_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
@@ -536,7 +536,7 @@ async def get_sessions(
if not schedule_id:
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
return await self._post(
- f"/workflow-schedule/{schedule_id}/sessions",
+ path_template("/workflow-schedule/{schedule_id}/sessions", schedule_id=schedule_id),
body=await async_maybe_transform(
{
"limit": limit,
@@ -575,7 +575,7 @@ async def pause(
if not schedule_id:
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
return await self._patch(
- f"/workflow-schedule/{schedule_id}/pause",
+ path_template("/workflow-schedule/{schedule_id}/pause", schedule_id=schedule_id),
body=await async_maybe_transform(
{"paused": paused}, workflow_schedule_pause_params.WorkflowSchedulePauseParams
),
@@ -610,7 +610,7 @@ async def run(
raise ValueError(f"Expected a non-empty value for `schedule_id` but received {schedule_id!r}")
extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
- f"/workflow-schedule/{schedule_id}/run",
+ path_template("/workflow-schedule/{schedule_id}/run", schedule_id=schedule_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
diff --git a/tests/test_utils/test_path.py b/tests/test_utils/test_path.py
new file mode 100644
index 000000000..a181b7010
--- /dev/null
+++ b/tests/test_utils/test_path.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+from typing import Any
+
+import pytest
+
+from structify._utils._path import path_template
+
+
+@pytest.mark.parametrize(
+ "template, kwargs, expected",
+ [
+ ("/v1/{id}", dict(id="abc"), "/v1/abc"),
+ ("/v1/{a}/{b}", dict(a="x", b="y"), "/v1/x/y"),
+ ("/v1/{a}{b}/path/{c}?val={d}#{e}", dict(a="x", b="y", c="z", d="u", e="v"), "/v1/xy/path/z?val=u#v"),
+ ("/{w}/{w}", dict(w="echo"), "/echo/echo"),
+ ("/v1/static", {}, "/v1/static"),
+ ("", {}, ""),
+ ("/v1/?q={n}&count=10", dict(n=42), "/v1/?q=42&count=10"),
+ ("/v1/{v}", dict(v=None), "/v1/null"),
+ ("/v1/{v}", dict(v=True), "/v1/true"),
+ ("/v1/{v}", dict(v=False), "/v1/false"),
+ ("/v1/{v}", dict(v=".hidden"), "/v1/.hidden"), # dot prefix ok
+ ("/v1/{v}", dict(v="file.txt"), "/v1/file.txt"), # dot in middle ok
+ ("/v1/{v}", dict(v="..."), "/v1/..."), # triple dot ok
+ ("/v1/{a}{b}", dict(a=".", b="txt"), "/v1/.txt"), # dot var combining with adjacent to be ok
+ ("/items?q={v}#{f}", dict(v=".", f=".."), "/items?q=.#.."), # dots in query/fragment are fine
+ (
+ "/v1/{a}?query={b}",
+ dict(a="../../other/endpoint", b="a&bad=true"),
+ "/v1/..%2F..%2Fother%2Fendpoint?query=a%26bad%3Dtrue",
+ ),
+ ("/v1/{val}", dict(val="a/b/c"), "/v1/a%2Fb%2Fc"),
+ ("/v1/{val}", dict(val="a/b/c?query=value"), "/v1/a%2Fb%2Fc%3Fquery=value"),
+ ("/v1/{val}", dict(val="a/b/c?query=value&bad=true"), "/v1/a%2Fb%2Fc%3Fquery=value&bad=true"),
+ ("/v1/{val}", dict(val="%20"), "/v1/%2520"), # escapes escape sequences in input
+ # Query: slash and ? are safe, # is not
+ ("/items?q={v}", dict(v="a/b"), "/items?q=a/b"),
+ ("/items?q={v}", dict(v="a?b"), "/items?q=a?b"),
+ ("/items?q={v}", dict(v="a#b"), "/items?q=a%23b"),
+ ("/items?q={v}", dict(v="a b"), "/items?q=a%20b"),
+ # Fragment: slash and ? are safe
+ ("/docs#{v}", dict(v="a/b"), "/docs#a/b"),
+ ("/docs#{v}", dict(v="a?b"), "/docs#a?b"),
+ # Path: slash, ? and # are all encoded
+ ("/v1/{v}", dict(v="a/b"), "/v1/a%2Fb"),
+ ("/v1/{v}", dict(v="a?b"), "/v1/a%3Fb"),
+ ("/v1/{v}", dict(v="a#b"), "/v1/a%23b"),
+ # same var encoded differently by component
+ (
+ "/v1/{v}?q={v}#{v}",
+ dict(v="a/b?c#d"),
+ "/v1/a%2Fb%3Fc%23d?q=a/b?c%23d#a/b?c%23d",
+ ),
+ ("/v1/{val}", dict(val="x?admin=true"), "/v1/x%3Fadmin=true"), # query injection
+ ("/v1/{val}", dict(val="x#admin"), "/v1/x%23admin"), # fragment injection
+ ],
+)
+def test_interpolation(template: str, kwargs: dict[str, Any], expected: str) -> None:
+ assert path_template(template, **kwargs) == expected
+
+
+def test_missing_kwarg_raises_key_error() -> None:
+ with pytest.raises(KeyError, match="org_id"):
+ path_template("/v1/{org_id}")
+
+
+@pytest.mark.parametrize(
+ "template, kwargs",
+ [
+ ("{a}/path", dict(a=".")),
+ ("{a}/path", dict(a="..")),
+ ("/v1/{a}", dict(a=".")),
+ ("/v1/{a}", dict(a="..")),
+ ("/v1/{a}/path", dict(a=".")),
+ ("/v1/{a}/path", dict(a="..")),
+ ("/v1/{a}{b}", dict(a=".", b=".")), # adjacent vars → ".."
+ ("/v1/{a}.", dict(a=".")), # var + static → ".."
+ ("/v1/{a}{b}", dict(a="", b=".")), # empty + dot → "."
+ ("/v1/%2e/{x}", dict(x="ok")), # encoded dot in static text
+ ("/v1/%2e./{x}", dict(x="ok")), # mixed encoded ".." in static
+ ("/v1/.%2E/{x}", dict(x="ok")), # mixed encoded ".." in static
+ ("/v1/{v}?q=1", dict(v="..")),
+ ("/v1/{v}#frag", dict(v="..")),
+ ],
+)
+def test_dot_segment_rejected(template: str, kwargs: dict[str, Any]) -> None:
+ with pytest.raises(ValueError, match="dot-segment"):
+ path_template(template, **kwargs)
From cc504acffcde1581af4c46f697b06ff34dfb4643 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 02:01:45 +0000
Subject: [PATCH 074/105] refactor(tests): switch from prism to steady
---
CONTRIBUTING.md | 2 +-
scripts/mock | 26 +++++++++++++-------------
scripts/test | 16 ++++++++--------
3 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index abde1f04b..cdb270a71 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -85,7 +85,7 @@ $ pip install ./path-to-wheel-file.whl
## Running tests
-Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.
+Most tests require you to [set up a mock server](https://github.com/dgellow/steady) against the OpenAPI spec to run the tests.
```sh
$ ./scripts/mock
diff --git a/scripts/mock b/scripts/mock
index bcf3b392b..38201de83 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -19,34 +19,34 @@ fi
echo "==> Starting mock server with URL ${URL}"
-# Run prism mock on the given spec
+# Run steady mock on the given spec
if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
- npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism --version
+ npm exec --package=@stdy/cli@0.19.3 -- steady --version
- npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log &
+ npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" &> .stdy.log &
- # Wait for server to come online (max 30s)
+ # Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
attempts=0
- while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do
+ while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do
+ if ! kill -0 $! 2>/dev/null; then
+ echo
+ cat .stdy.log
+ exit 1
+ fi
attempts=$((attempts + 1))
if [ "$attempts" -ge 300 ]; then
echo
- echo "Timed out waiting for Prism server to start"
- cat .prism.log
+ echo "Timed out waiting for Steady server to start"
+ cat .stdy.log
exit 1
fi
echo -n "."
sleep 0.1
done
- if grep -q "✖ fatal" ".prism.log"; then
- cat .prism.log
- exit 1
- fi
-
echo
else
- npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL"
+ npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL"
fi
diff --git a/scripts/test b/scripts/test
index dbeda2d21..2dfdc4093 100755
--- a/scripts/test
+++ b/scripts/test
@@ -9,8 +9,8 @@ GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
-function prism_is_running() {
- curl --silent "http://localhost:4010" >/dev/null 2>&1
+function steady_is_running() {
+ curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1
}
kill_server_on_port() {
@@ -25,7 +25,7 @@ function is_overriding_api_base_url() {
[ -n "$TEST_API_BASE_URL" ]
}
-if ! is_overriding_api_base_url && ! prism_is_running ; then
+if ! is_overriding_api_base_url && ! steady_is_running ; then
# When we exit this script, make sure to kill the background mock server process
trap 'kill_server_on_port 4010' EXIT
@@ -36,19 +36,19 @@ fi
if is_overriding_api_base_url ; then
echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}"
echo
-elif ! prism_is_running ; then
- echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server"
+elif ! steady_is_running ; then
+ echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server"
echo -e "running against your OpenAPI spec."
echo
echo -e "To run the server, pass in the path or url of your OpenAPI"
- echo -e "spec to the prism command:"
+ echo -e "spec to the steady command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.3 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets${NC}"
echo
exit 1
else
- echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}"
+ echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}"
echo
fi
From 5a232300a64a4d64671f8167da883d3b80389b9b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 17:56:34 +0000
Subject: [PATCH 075/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 2 +
src/structify/resources/admin/jobs.py | 6 +-
.../resources/connector_catalog/admin.py | 8 +
.../resources/connectors/connectors.py | 241 ++++++++++++++++-
src/structify/resources/jobs.py | 6 +-
src/structify/types/__init__.py | 3 +
src/structify/types/admin/job_list_params.py | 2 +-
.../types/admin/job_list_response.py | 38 ++-
.../admin_create_catalog_params.py | 2 +
.../admin_update_catalog_params.py | 2 +
.../connector_catalog/connector_catalog.py | 2 +
.../types/connector_explore_params.py | 8 +-
...onnector_upload_datahub_artifact_params.py | 15 ++
.../types/entity_list_jobs_response.py | 6 +-
src/structify/types/exploration_run.py | 7 +-
src/structify/types/job_cancel_response.py | 6 +-
src/structify/types/job_event_body.py | 12 +
src/structify/types/job_get_response.py | 40 ++-
src/structify/types/job_list_params.py | 2 +-
src/structify/types/job_list_response.py | 38 ++-
src/structify/types/viz_figure_kind.py | 2 +-
.../connector_catalog/test_admin.py | 4 +
tests/api_resources/test_connectors.py | 254 +++++++++++++++++-
24 files changed, 645 insertions(+), 69 deletions(-)
create mode 100644 src/structify/types/connector_upload_datahub_artifact_params.py
diff --git a/.stats.yml b/.stats.yml
index 492ceab29..04f5c0cf7 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 247
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-90d851ec2e7164a2b245164443d94886f6cfa165161b79bbde3239e84f2029c8.yml
-openapi_spec_hash: 371d53240965747ae36853a7f9c98018
-config_hash: 27deacd435ab581e7ff08d1f4d495554
+configured_endpoints: 249
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0f94f635dece92ce017968d527659407388a23fdccd92534c9cba9cddfd44ec0.yml
+openapi_spec_hash: 57cca7c7caa928fc88b5892a9e6def86
+config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/api.md b/api.md
index fd660e471..4a4d68da1 100644
--- a/api.md
+++ b/api.md
@@ -737,6 +737,7 @@ Methods:
- client.connectors.create_secret(connector_id, \*\*params) -> None
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
+- client.connectors.download_datahub_artifact(kind, \*, connector_id) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
@@ -753,6 +754,7 @@ Methods:
- client.connectors.summaries(\*\*params) -> ConnectorSummariesResponse
- client.connectors.update_column(column_id, \*\*params) -> None
- client.connectors.update_table(table_id, \*\*params) -> UpdateTableResponse
+- client.connectors.upload_datahub_artifact(kind, \*, connector_id, \*\*params) -> None
## TypeSnippets
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index 16f81550e..c95c5fb48 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -52,7 +52,8 @@ def with_streaming_response(self) -> JobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
@@ -182,7 +183,8 @@ def with_streaming_response(self) -> AsyncJobsResourceWithStreamingResponse:
def list(
self,
*,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
status: Optional[Literal["Queued", "Running", "Completed", "Failed"]] | Omit = omit,
diff --git a/src/structify/resources/connector_catalog/admin.py b/src/structify/resources/connector_catalog/admin.py
index 21b4925cd..fb245fc6c 100644
--- a/src/structify/resources/connector_catalog/admin.py
+++ b/src/structify/resources/connector_catalog/admin.py
@@ -201,6 +201,7 @@ def create_catalog(
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
enterprise_only: bool | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -230,6 +231,7 @@ def create_catalog(
"categories": categories,
"description": description,
"enterprise_only": enterprise_only,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -541,6 +543,7 @@ def update_catalog(
description: Optional[str] | Omit = omit,
enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -571,6 +574,7 @@ def update_catalog(
"description": description,
"enterprise_only": enterprise_only,
"name": name,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_update_catalog_params.AdminUpdateCatalogParams,
@@ -863,6 +867,7 @@ async def create_catalog(
categories: SequenceNotStr[str] | Omit = omit,
description: Optional[str] | Omit = omit,
enterprise_only: bool | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -892,6 +897,7 @@ async def create_catalog(
"categories": categories,
"description": description,
"enterprise_only": enterprise_only,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_create_catalog_params.AdminCreateCatalogParams,
@@ -1203,6 +1209,7 @@ async def update_catalog(
description: Optional[str] | Omit = omit,
enterprise_only: Optional[bool] | Omit = omit,
name: Optional[str] | Omit = omit,
+ onboarding_priority: Optional[int] | Omit = omit,
priority: Optional[int] | 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.
@@ -1233,6 +1240,7 @@ async def update_catalog(
"description": description,
"enterprise_only": enterprise_only,
"name": name,
+ "onboarding_priority": onboarding_priority,
"priority": priority,
},
admin_update_catalog_params.AdminUpdateCatalogParams,
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 29589882c..32b4577dc 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Any, Dict, Optional, cast
+from typing import Any, Dict, Mapping, Optional, cast
from typing_extensions import Literal, overload
import httpx
@@ -21,16 +21,43 @@
connector_add_schema_object_params,
connector_get_explorer_chat_params,
connector_delete_schema_object_params,
+ connector_upload_datahub_artifact_params,
+)
+from ..._types import (
+ Body,
+ Omit,
+ Query,
+ Headers,
+ NoneType,
+ NotGiven,
+ FileTypes,
+ SequenceNotStr,
+ omit,
+ not_given,
+)
+from ..._utils import (
+ extract_files,
+ path_template,
+ required_args,
+ maybe_transform,
+ deepcopy_minimal,
+ async_maybe_transform,
)
-from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
to_raw_response_wrapper,
to_streamed_response_wrapper,
async_to_raw_response_wrapper,
+ to_custom_raw_response_wrapper,
async_to_streamed_response_wrapper,
+ to_custom_streamed_response_wrapper,
+ async_to_custom_raw_response_wrapper,
+ async_to_custom_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
from .type_snippets import (
@@ -651,13 +678,50 @@ def delete_secret(
cast_to=NoneType,
)
+ def download_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> BinaryAPIResponse:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return self._get(
+ path_template(
+ "/internal/connectors/{connector_id}/datahub-artifacts/{kind}", connector_id=connector_id, kind=kind
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=BinaryAPIResponse,
+ )
+
def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
+ only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
- stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -668,7 +732,7 @@ def explore(
) -> None:
"""
Args:
- stage: Which exploration stage to run
+ only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
extra_headers: Send extra headers
@@ -686,8 +750,8 @@ def explore(
body=maybe_transform(
{
"database_id": database_id,
+ "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
- "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -1190,6 +1254,52 @@ def update_table(
cast_to=UpdateTableResponse,
)
+ def upload_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ file: FileTypes,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ body = deepcopy_minimal({"file": file})
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return self._put(
+ path_template(
+ "/internal/connectors/{connector_id}/datahub-artifacts/{kind}", connector_id=connector_id, kind=kind
+ ),
+ body=maybe_transform(body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class AsyncConnectorsResource(AsyncAPIResource):
@cached_property
@@ -1778,13 +1888,50 @@ async def delete_secret(
cast_to=NoneType,
)
+ async def download_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> AsyncBinaryAPIResponse:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "application/octet-stream", **(extra_headers or {})}
+ return await self._get(
+ path_template(
+ "/internal/connectors/{connector_id}/datahub-artifacts/{kind}", connector_id=connector_id, kind=kind
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AsyncBinaryAPIResponse,
+ )
+
async def explore(
self,
connector_id: str,
*,
database_id: Optional[str] | Omit = omit,
+ only_do_datahub: Optional[bool] | Omit = omit,
schema_id: Optional[str] | Omit = omit,
- stage: Optional[Literal["both", "ingestion", "annotation"]] | Omit = omit,
table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
@@ -1795,7 +1942,7 @@ async def explore(
) -> None:
"""
Args:
- stage: Which exploration stage to run
+ only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
extra_headers: Send extra headers
@@ -1813,8 +1960,8 @@ async def explore(
body=await async_maybe_transform(
{
"database_id": database_id,
+ "only_do_datahub": only_do_datahub,
"schema_id": schema_id,
- "stage": stage,
"table_id": table_id,
},
connector_explore_params.ConnectorExploreParams,
@@ -2321,6 +2468,54 @@ async def update_table(
cast_to=UpdateTableResponse,
)
+ async def upload_datahub_artifact(
+ self,
+ kind: str,
+ *,
+ connector_id: str,
+ file: FileTypes,
+ # 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:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not kind:
+ raise ValueError(f"Expected a non-empty value for `kind` but received {kind!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
+ body = deepcopy_minimal({"file": file})
+ files = extract_files(cast(Mapping[str, object], body), paths=[["file"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return await self._put(
+ path_template(
+ "/internal/connectors/{connector_id}/datahub-artifacts/{kind}", connector_id=connector_id, kind=kind
+ ),
+ body=await async_maybe_transform(
+ body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams
+ ),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=NoneType,
+ )
+
class ConnectorsResourceWithRawResponse:
def __init__(self, connectors: ConnectorsResource) -> None:
@@ -2350,6 +2545,10 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_raw_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = to_custom_raw_response_wrapper(
+ connectors.download_datahub_artifact,
+ BinaryAPIResponse,
+ )
self.explore = to_raw_response_wrapper(
connectors.explore,
)
@@ -2398,6 +2597,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_raw_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = to_raw_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithRawResponse:
@@ -2432,6 +2634,10 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_raw_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = async_to_custom_raw_response_wrapper(
+ connectors.download_datahub_artifact,
+ AsyncBinaryAPIResponse,
+ )
self.explore = async_to_raw_response_wrapper(
connectors.explore,
)
@@ -2480,6 +2686,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_raw_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = async_to_raw_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithRawResponse:
@@ -2514,6 +2723,10 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.delete_secret = to_streamed_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = to_custom_streamed_response_wrapper(
+ connectors.download_datahub_artifact,
+ StreamedBinaryAPIResponse,
+ )
self.explore = to_streamed_response_wrapper(
connectors.explore,
)
@@ -2562,6 +2775,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.update_table = to_streamed_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = to_streamed_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> TypeSnippetsResourceWithStreamingResponse:
@@ -2596,6 +2812,10 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.delete_secret = async_to_streamed_response_wrapper(
connectors.delete_secret,
)
+ self.download_datahub_artifact = async_to_custom_streamed_response_wrapper(
+ connectors.download_datahub_artifact,
+ AsyncStreamedBinaryAPIResponse,
+ )
self.explore = async_to_streamed_response_wrapper(
connectors.explore,
)
@@ -2644,6 +2864,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.update_table = async_to_streamed_response_wrapper(
connectors.update_table,
)
+ self.upload_datahub_artifact = async_to_streamed_response_wrapper(
+ connectors.upload_datahub_artifact,
+ )
@cached_property
def type_snippets(self) -> AsyncTypeSnippetsResourceWithStreamingResponse:
diff --git a/src/structify/resources/jobs.py b/src/structify/resources/jobs.py
index 1184844cb..4caf8e80b 100644
--- a/src/structify/resources/jobs.py
+++ b/src/structify/resources/jobs.py
@@ -56,7 +56,8 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
@@ -374,7 +375,8 @@ def list(
self,
*,
dataset: Optional[str] | Omit = omit,
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]] | Omit = omit,
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
+ | Omit = omit,
limit: int | Omit = omit,
node_id: Optional[str] | Omit = omit,
offset: int | Omit = omit,
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 88f29faca..1f4896432 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -389,6 +389,9 @@
from .structure_enhance_relationship_response import (
StructureEnhanceRelationshipResponse as StructureEnhanceRelationshipResponse,
)
+from .connector_upload_datahub_artifact_params import (
+ ConnectorUploadDatahubArtifactParams as ConnectorUploadDatahubArtifactParams,
+)
from .chat_copy_node_output_by_code_hash_params import (
ChatCopyNodeOutputByCodeHashParams as ChatCopyNodeOutputByCodeHashParams,
)
diff --git a/src/structify/types/admin/job_list_params.py b/src/structify/types/admin/job_list_params.py
index cb290ca95..62f040440 100644
--- a/src/structify/types/admin/job_list_params.py
+++ b/src/structify/types/admin/job_list_params.py
@@ -9,7 +9,7 @@
class JobListParams(TypedDict, total=False):
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
limit: int
diff --git a/src/structify/types/admin/job_list_response.py b/src/structify/types/admin/job_list_response.py
index d494541eb..523c2310d 100644
--- a/src/structify/types/admin/job_list_response.py
+++ b/src/structify/types/admin/job_list_response.py
@@ -26,6 +26,8 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
+ "ParametersStructuringInputDatahubIngestion",
+ "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -95,6 +97,18 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class ParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
+
+
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -107,8 +121,7 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -122,6 +135,7 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
+ ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -131,33 +145,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: ParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/connector_catalog/admin_create_catalog_params.py b/src/structify/types/connector_catalog/admin_create_catalog_params.py
index adfb768f8..98662c009 100644
--- a/src/structify/types/connector_catalog/admin_create_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_create_catalog_params.py
@@ -21,4 +21,6 @@ class AdminCreateCatalogParams(TypedDict, total=False):
enterprise_only: bool
+ onboarding_priority: Optional[int]
+
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/admin_update_catalog_params.py b/src/structify/types/connector_catalog/admin_update_catalog_params.py
index 784ae5ece..23d639c71 100644
--- a/src/structify/types/connector_catalog/admin_update_catalog_params.py
+++ b/src/structify/types/connector_catalog/admin_update_catalog_params.py
@@ -19,4 +19,6 @@ class AdminUpdateCatalogParams(TypedDict, total=False):
name: Optional[str]
+ onboarding_priority: Optional[int]
+
priority: Optional[int]
diff --git a/src/structify/types/connector_catalog/connector_catalog.py b/src/structify/types/connector_catalog/connector_catalog.py
index c414d1f49..8f0b9eb5e 100644
--- a/src/structify/types/connector_catalog/connector_catalog.py
+++ b/src/structify/types/connector_catalog/connector_catalog.py
@@ -25,4 +25,6 @@ class ConnectorCatalog(BaseModel):
description: Optional[str] = None
+ onboarding_priority: Optional[int] = None
+
priority: Optional[int] = None
diff --git a/src/structify/types/connector_explore_params.py b/src/structify/types/connector_explore_params.py
index d4b23d4b9..4d94d5501 100644
--- a/src/structify/types/connector_explore_params.py
+++ b/src/structify/types/connector_explore_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Literal, TypedDict
+from typing_extensions import TypedDict
__all__ = ["ConnectorExploreParams"]
@@ -11,9 +11,9 @@
class ConnectorExploreParams(TypedDict, total=False):
database_id: Optional[str]
- schema_id: Optional[str]
+ only_do_datahub: Optional[bool]
+ """If true, run only DataHub ingestion without queuing Diego annotation jobs."""
- stage: Optional[Literal["both", "ingestion", "annotation"]]
- """Which exploration stage to run"""
+ schema_id: Optional[str]
table_id: Optional[str]
diff --git a/src/structify/types/connector_upload_datahub_artifact_params.py b/src/structify/types/connector_upload_datahub_artifact_params.py
new file mode 100644
index 000000000..09dfc77e7
--- /dev/null
+++ b/src/structify/types/connector_upload_datahub_artifact_params.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ConnectorUploadDatahubArtifactParams"]
+
+
+class ConnectorUploadDatahubArtifactParams(TypedDict, total=False):
+ connector_id: Required[str]
+
+ file: Required[FileTypes]
diff --git a/src/structify/types/entity_list_jobs_response.py b/src/structify/types/entity_list_jobs_response.py
index 1bcedcda2..31808d0c5 100644
--- a/src/structify/types/entity_list_jobs_response.py
+++ b/src/structify/types/entity_list_jobs_response.py
@@ -14,9 +14,7 @@ class EntityListJobsResponseItem(BaseModel):
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
max_steps_without_save: int
@@ -30,6 +28,8 @@ class EntityListJobsResponseItem(BaseModel):
user_id: str
+ dataset_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/exploration_run.py b/src/structify/types/exploration_run.py
index ff4368f5a..769a45984 100644
--- a/src/structify/types/exploration_run.py
+++ b/src/structify/types/exploration_run.py
@@ -1,5 +1,6 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+from typing import Optional
from datetime import datetime
from .._models import BaseModel
@@ -8,6 +9,10 @@
class ExplorationRun(BaseModel):
+ id: str
+
+ connector_id: str
+
created_at: datetime
- run_id: str
+ triggered_by: Optional[str] = None
diff --git a/src/structify/types/job_cancel_response.py b/src/structify/types/job_cancel_response.py
index 640fcf079..75a5f4673 100644
--- a/src/structify/types/job_cancel_response.py
+++ b/src/structify/types/job_cancel_response.py
@@ -14,9 +14,7 @@ class JobCancelResponse(BaseModel):
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
max_steps_without_save: int
@@ -30,6 +28,8 @@ class JobCancelResponse(BaseModel):
user_id: str
+ dataset_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/job_event_body.py b/src/structify/types/job_event_body.py
index 85f1e3f9f..8820bff9d 100644
--- a/src/structify/types/job_event_body.py
+++ b/src/structify/types/job_event_body.py
@@ -24,6 +24,7 @@
"DatahubDatabasesCreated",
"DatahubSchemasCreated",
"DatahubTablesProcessed",
+ "DatahubAnnotationsQueued",
"DatahubEmbeddingBatch",
"ViewedPdfPage",
]
@@ -167,9 +168,19 @@ class DatahubTablesProcessed(BaseModel):
tables_failed: int
+ tables_removed: int
+
tables_updated: int
+class DatahubAnnotationsQueued(BaseModel):
+ diff_annotations_queued: int
+
+ event_type: Literal["datahub_annotations_queued"]
+
+ full_annotations_queued: int
+
+
class DatahubEmbeddingBatch(BaseModel):
batch_num: int
@@ -203,6 +214,7 @@ class ViewedPdfPage(BaseModel):
DatahubDatabasesCreated,
DatahubSchemasCreated,
DatahubTablesProcessed,
+ DatahubAnnotationsQueued,
DatahubEmbeddingBatch,
ViewedPdfPage,
],
diff --git a/src/structify/types/job_get_response.py b/src/structify/types/job_get_response.py
index c51109bea..82961dcbf 100644
--- a/src/structify/types/job_get_response.py
+++ b/src/structify/types/job_get_response.py
@@ -32,6 +32,8 @@
"InfoParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"InfoParametersStructuringInputScrapeURL",
"InfoParametersStructuringInputScrapeURLScrapeURL",
+ "InfoParametersStructuringInputDatahubIngestion",
+ "InfoParametersStructuringInputDatahubIngestionDatahubIngestion",
"InfoParametersStructuringInputConnectorExploration",
"InfoParametersStructuringInputConnectorExplorationConnectorExploration",
"Saved",
@@ -135,6 +137,20 @@ class InfoParametersStructuringInputScrapeURL(BaseModel):
scrape_url: InfoParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class InfoParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class InfoParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: InfoParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(
+ alias="DatahubIngestion"
+ )
+
+
class InfoParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -147,8 +163,7 @@ class InfoParametersStructuringInputConnectorExplorationConnectorExploration(Bas
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class InfoParametersStructuringInputConnectorExploration(BaseModel):
@@ -162,6 +177,7 @@ class InfoParametersStructuringInputConnectorExploration(BaseModel):
InfoParametersStructuringInputTransformationPrompt,
InfoParametersStructuringInputScrapeFromURLProperty,
InfoParametersStructuringInputScrapeURL,
+ InfoParametersStructuringInputDatahubIngestion,
InfoParametersStructuringInputConnectorExploration,
]
@@ -171,33 +187,33 @@ class InfoParameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: InfoParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class Info(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[InfoParameters] = None
diff --git a/src/structify/types/job_list_params.py b/src/structify/types/job_list_params.py
index e13064899..d93b17726 100644
--- a/src/structify/types/job_list_params.py
+++ b/src/structify/types/job_list_params.py
@@ -15,7 +15,7 @@ class JobListParams(TypedDict, total=False):
dataset: Optional[str]
"""Dataset name to optionally filter jobs by"""
- job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]]
+ job_type: Optional[Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]]
"""Type of job to optionally filter jobs by"""
limit: int
diff --git a/src/structify/types/job_list_response.py b/src/structify/types/job_list_response.py
index d6567a058..122fbeb06 100644
--- a/src/structify/types/job_list_response.py
+++ b/src/structify/types/job_list_response.py
@@ -26,6 +26,8 @@
"ParametersStructuringInputScrapeFromURLPropertyScrapeFromURLProperty",
"ParametersStructuringInputScrapeURL",
"ParametersStructuringInputScrapeURLScrapeURL",
+ "ParametersStructuringInputDatahubIngestion",
+ "ParametersStructuringInputDatahubIngestionDatahubIngestion",
"ParametersStructuringInputConnectorExploration",
"ParametersStructuringInputConnectorExplorationConnectorExploration",
]
@@ -95,6 +97,18 @@ class ParametersStructuringInputScrapeURL(BaseModel):
scrape_url: ParametersStructuringInputScrapeURLScrapeURL = FieldInfo(alias="ScrapeUrl")
+class ParametersStructuringInputDatahubIngestionDatahubIngestion(BaseModel):
+ connector_id: str
+
+ exploration_run_id: str
+
+ only_do_datahub: bool
+
+
+class ParametersStructuringInputDatahubIngestion(BaseModel):
+ datahub_ingestion: ParametersStructuringInputDatahubIngestionDatahubIngestion = FieldInfo(alias="DatahubIngestion")
+
+
class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseModel):
connector_id: str
@@ -107,8 +121,7 @@ class ParametersStructuringInputConnectorExplorationConnectorExploration(BaseMod
exploration_run_id: str
- stage: Literal["both", "ingestion", "annotation"]
- """Which exploration stage to run"""
+ strategy: Literal["full", "diff"]
class ParametersStructuringInputConnectorExploration(BaseModel):
@@ -122,6 +135,7 @@ class ParametersStructuringInputConnectorExploration(BaseModel):
ParametersStructuringInputTransformationPrompt,
ParametersStructuringInputScrapeFromURLProperty,
ParametersStructuringInputScrapeURL,
+ ParametersStructuringInputDatahubIngestion,
ParametersStructuringInputConnectorExploration,
]
@@ -131,33 +145,33 @@ class Parameters(BaseModel):
extraction_criteria: List[SaveRequirement]
- seeded_kg: KnowledgeGraph
- """
- Knowledge graph info structured to deserialize and display in the same format
- that the LLM outputs. Also the first representation of an LLM output in the
- pipeline from raw tool output to being merged into a DB
- """
-
structuring_input: ParametersStructuringInput
instructions: Optional[str] = None
model: Optional[str] = None
+ seeded_kg: Optional[KnowledgeGraph] = None
+ """
+ Knowledge graph info structured to deserialize and display in the same format
+ that the LLM outputs. Also the first representation of an LLM output in the
+ pipeline from raw tool output to being merged into a DB
+ """
+
class JobListResponse(BaseModel):
id: str
created_at: datetime
- dataset_id: str
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore"]
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
status: Literal["Queued", "Running", "Completed", "Failed"]
user_id: str
+ dataset_id: Optional[str] = None
+
message: Optional[str] = None
parameters: Optional[Parameters] = None
diff --git a/src/structify/types/viz_figure_kind.py b/src/structify/types/viz_figure_kind.py
index 32d895e43..e70d16356 100644
--- a/src/structify/types/viz_figure_kind.py
+++ b/src/structify/types/viz_figure_kind.py
@@ -4,4 +4,4 @@
__all__ = ["VizFigureKind"]
-VizFigureKind: TypeAlias = Literal["js", "vega-lite"]
+VizFigureKind: TypeAlias = Literal["js", "vega-lite", "data-table"]
diff --git a/tests/api_resources/connector_catalog/test_admin.py b/tests/api_resources/connector_catalog/test_admin.py
index 224b67a19..10cb267d0 100644
--- a/tests/api_resources/connector_catalog/test_admin.py
+++ b/tests/api_resources/connector_catalog/test_admin.py
@@ -195,6 +195,7 @@ def test_method_create_catalog_with_all_params(self, client: Structify) -> None:
categories=["string"],
description="description",
enterprise_only=True,
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -561,6 +562,7 @@ def test_method_update_catalog_with_all_params(self, client: Structify) -> None:
description="description",
enterprise_only=True,
name="name",
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -915,6 +917,7 @@ async def test_method_create_catalog_with_all_params(self, async_client: AsyncSt
categories=["string"],
description="description",
enterprise_only=True,
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
@@ -1281,6 +1284,7 @@ async def test_method_update_catalog_with_all_params(self, async_client: AsyncSt
description="description",
enterprise_only=True,
name="name",
+ onboarding_priority=0,
priority=0,
)
assert_matches_type(ConnectorCatalog, admin, path=["response"])
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index d07a07258..ac23c3e9c 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -5,7 +5,9 @@
import os
from typing import Any, cast
+import httpx
import pytest
+from respx import MockRouter
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
@@ -28,6 +30,12 @@
ConnectorListWithSnippetsResponse,
ConnectorGetClarificationRequestsResponse,
)
+from structify._response import (
+ BinaryAPIResponse,
+ AsyncBinaryAPIResponse,
+ StreamedBinaryAPIResponse,
+ AsyncStreamedBinaryAPIResponse,
+)
from structify.pagination import SyncJobsList, AsyncJobsList
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -734,6 +742,72 @@ def test_path_params_delete_secret(self, client: Structify) -> None:
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_raw_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ connector = client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert connector.is_closed is True
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert connector.json() == {"foo": "bar"}
+ assert isinstance(connector, BinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_streaming_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ with client.connectors.with_streaming_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as connector:
+ assert not connector.is_closed
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, StreamedBinaryAPIResponse)
+
+ assert cast(Any, connector.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_path_params_download_datahub_artifact(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ client.connectors.with_raw_response.download_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
@@ -746,8 +820,8 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -1337,6 +1411,59 @@ def test_path_params_update_table(self, client: Structify) -> None:
table_id="",
)
+ @parametrize
+ def test_method_upload_datahub_artifact(self, client: Structify) -> None:
+ connector = client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+ assert connector is None
+
+ @parametrize
+ def test_raw_response_upload_datahub_artifact(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert connector is None
+
+ @parametrize
+ def test_streaming_response_upload_datahub_artifact(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert connector is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ file=b"Example data",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
class TestAsyncConnectors:
parametrize = pytest.mark.parametrize(
@@ -2041,6 +2168,76 @@ async def test_path_params_delete_secret(self, async_client: AsyncStructify) ->
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_download_datahub_artifact(self, async_client: AsyncStructify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = await async_client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_raw_response_download_datahub_artifact(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+
+ connector = await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert connector.is_closed is True
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+ assert await connector.json() == {"foo": "bar"}
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_streaming_response_download_datahub_artifact(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ async with async_client.connectors.with_streaming_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as connector:
+ assert not connector.is_closed
+ assert connector.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncStreamedBinaryAPIResponse)
+
+ assert cast(Any, connector.is_closed) is True
+
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_path_params_download_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ await async_client.connectors.with_raw_response.download_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
@@ -2053,8 +2250,8 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ only_do_datahub=True,
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- stage="both",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert connector is None
@@ -2643,3 +2840,56 @@ async def test_path_params_update_table(self, async_client: AsyncStructify) -> N
await async_client.connectors.with_raw_response.update_table(
table_id="",
)
+
+ @parametrize
+ async def test_method_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+ assert connector is None
+
+ @parametrize
+ async def test_raw_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert connector is None
+
+ @parametrize
+ async def test_streaming_response_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert connector is None
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="kind",
+ connector_id="",
+ file=b"Example data",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `kind` but received ''"):
+ await async_client.connectors.with_raw_response.upload_datahub_artifact(
+ kind="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=b"Example data",
+ )
From c82fda0263115ed45d8587e4d114e7f387b25a84 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 19:03:13 +0000
Subject: [PATCH 076/105] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 04f5c0cf7..b36a12b49 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-0f94f635dece92ce017968d527659407388a23fdccd92534c9cba9cddfd44ec0.yml
-openapi_spec_hash: 57cca7c7caa928fc88b5892a9e6def86
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-3cfd7b676909cbdda8a067628408c436cdcedcfada124c31c101bc94c1396adf.yml
+openapi_spec_hash: 024eea2157472e1dc4b94a9765942055
config_hash: 63c3aa248700e46cfe93b79afa9f0065
From ac9f0d53b217e035ccbb75d026593634e054f117 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 19:39:35 +0000
Subject: [PATCH 077/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/chat_create_session_params.py | 1 +
src/structify/types/code_generate_code_params.py | 1 +
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index b36a12b49..fcfdbfcbe 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-3cfd7b676909cbdda8a067628408c436cdcedcfada124c31c101bc94c1396adf.yml
-openapi_spec_hash: 024eea2157472e1dc4b94a9765942055
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-6a8e77b25fb2033f798cdf54f0e2a8b4e001dffdf98a25d93fa5f97ddcea4f3c.yml
+openapi_spec_hash: 0bc0cf5a99bb49cee24423a2496c22c5
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/src/structify/types/chat_create_session_params.py b/src/structify/types/chat_create_session_params.py
index 835fa23ac..61b16071f 100644
--- a/src/structify/types/chat_create_session_params.py
+++ b/src/structify/types/chat_create_session_params.py
@@ -50,6 +50,7 @@ class Config(TypedDict, total=False):
"gemini.gemini-3-flash-preview",
"gemini.gemini-3.1-flash-lite-preview",
"vertex_anthropic.claude-sonnet-4-5-vertex",
+ "vertex_anthropic.claude-opus-4-5-vertex",
]
]
"""LLM model keys available in the system. Format: ."""
diff --git a/src/structify/types/code_generate_code_params.py b/src/structify/types/code_generate_code_params.py
index 23ffbc170..0d8de217d 100644
--- a/src/structify/types/code_generate_code_params.py
+++ b/src/structify/types/code_generate_code_params.py
@@ -63,6 +63,7 @@ class Config(TypedDict, total=False):
"gemini.gemini-3-flash-preview",
"gemini.gemini-3.1-flash-lite-preview",
"vertex_anthropic.claude-sonnet-4-5-vertex",
+ "vertex_anthropic.claude-opus-4-5-vertex",
]
]
"""LLM model keys available in the system. Format: ."""
From 2db1ef601ecc67ffb5696f4cf8cdd6e92e8915bf Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 20 Mar 2026 21:50:45 +0000
Subject: [PATCH 078/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +-
api.md | 2 +-
.../resources/connectors/connectors.py | 41 +++++++++++++++--
src/structify/types/__init__.py | 3 ++
...nector_download_datahub_artifact_params.py | 14 ++++++
...onnector_upload_datahub_artifact_params.py | 2 +
src/structify/types/exploration_run.py | 4 ++
tests/api_resources/test_connectors.py | 44 +++++++++++++++++++
8 files changed, 107 insertions(+), 7 deletions(-)
create mode 100644 src/structify/types/connector_download_datahub_artifact_params.py
diff --git a/.stats.yml b/.stats.yml
index fcfdbfcbe..6d446d830 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-6a8e77b25fb2033f798cdf54f0e2a8b4e001dffdf98a25d93fa5f97ddcea4f3c.yml
-openapi_spec_hash: 0bc0cf5a99bb49cee24423a2496c22c5
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-62d07fb1a833f3e0d133fd032a77a545244b770f38c8346a193136ccd82774ba.yml
+openapi_spec_hash: f1abca6b91e0d3d80d7ec63242cd7837
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/api.md b/api.md
index 4a4d68da1..fad0d5feb 100644
--- a/api.md
+++ b/api.md
@@ -737,7 +737,7 @@ Methods:
- client.connectors.create_secret(connector_id, \*\*params) -> None
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
-- client.connectors.download_datahub_artifact(kind, \*, connector_id) -> BinaryAPIResponse
+- client.connectors.download_datahub_artifact(kind, \*, connector_id, \*\*params) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 32b4577dc..07e6e43fe 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -22,6 +22,7 @@
connector_get_explorer_chat_params,
connector_delete_schema_object_params,
connector_upload_datahub_artifact_params,
+ connector_download_datahub_artifact_params,
)
from ..._types import (
Body,
@@ -683,6 +684,7 @@ def download_datahub_artifact(
kind: str,
*,
connector_id: str,
+ exploration_run_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -710,7 +712,14 @@ def download_datahub_artifact(
"/internal/connectors/{connector_id}/datahub-artifacts/{kind}", connector_id=connector_id, kind=kind
),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"exploration_run_id": exploration_run_id},
+ connector_download_datahub_artifact_params.ConnectorDownloadDatahubArtifactParams,
+ ),
),
cast_to=BinaryAPIResponse,
)
@@ -1259,6 +1268,7 @@ def upload_datahub_artifact(
kind: str,
*,
connector_id: str,
+ exploration_run_id: str,
file: FileTypes,
# 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.
@@ -1295,7 +1305,14 @@ def upload_datahub_artifact(
body=maybe_transform(body, connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams),
files=files,
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {"exploration_run_id": exploration_run_id},
+ connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams,
+ ),
),
cast_to=NoneType,
)
@@ -1893,6 +1910,7 @@ async def download_datahub_artifact(
kind: str,
*,
connector_id: str,
+ exploration_run_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -1920,7 +1938,14 @@ async def download_datahub_artifact(
"/internal/connectors/{connector_id}/datahub-artifacts/{kind}", connector_id=connector_id, kind=kind
),
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"exploration_run_id": exploration_run_id},
+ connector_download_datahub_artifact_params.ConnectorDownloadDatahubArtifactParams,
+ ),
),
cast_to=AsyncBinaryAPIResponse,
)
@@ -2473,6 +2498,7 @@ async def upload_datahub_artifact(
kind: str,
*,
connector_id: str,
+ exploration_run_id: str,
file: FileTypes,
# 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.
@@ -2511,7 +2537,14 @@ async def upload_datahub_artifact(
),
files=files,
options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {"exploration_run_id": exploration_run_id},
+ connector_upload_datahub_artifact_params.ConnectorUploadDatahubArtifactParams,
+ ),
),
cast_to=NoneType,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 1f4896432..3d7bb30bb 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -398,6 +398,9 @@
from .dataset_count_missing_embeddings_response import (
DatasetCountMissingEmbeddingsResponse as DatasetCountMissingEmbeddingsResponse,
)
+from .connector_download_datahub_artifact_params import (
+ ConnectorDownloadDatahubArtifactParams as ConnectorDownloadDatahubArtifactParams,
+)
from .chat_copy_node_output_by_code_hash_response import (
ChatCopyNodeOutputByCodeHashResponse as ChatCopyNodeOutputByCodeHashResponse,
)
diff --git a/src/structify/types/connector_download_datahub_artifact_params.py b/src/structify/types/connector_download_datahub_artifact_params.py
new file mode 100644
index 000000000..d62b879dd
--- /dev/null
+++ b/src/structify/types/connector_download_datahub_artifact_params.py
@@ -0,0 +1,14 @@
+# 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 Required, TypedDict
+
+__all__ = ["ConnectorDownloadDatahubArtifactParams"]
+
+
+class ConnectorDownloadDatahubArtifactParams(TypedDict, total=False):
+ connector_id: Required[str]
+
+ exploration_run_id: Optional[str]
diff --git a/src/structify/types/connector_upload_datahub_artifact_params.py b/src/structify/types/connector_upload_datahub_artifact_params.py
index 09dfc77e7..d7e22d8f5 100644
--- a/src/structify/types/connector_upload_datahub_artifact_params.py
+++ b/src/structify/types/connector_upload_datahub_artifact_params.py
@@ -12,4 +12,6 @@
class ConnectorUploadDatahubArtifactParams(TypedDict, total=False):
connector_id: Required[str]
+ exploration_run_id: Required[str]
+
file: Required[FileTypes]
diff --git a/src/structify/types/exploration_run.py b/src/structify/types/exploration_run.py
index 769a45984..1d89e8a1c 100644
--- a/src/structify/types/exploration_run.py
+++ b/src/structify/types/exploration_run.py
@@ -15,4 +15,8 @@ class ExplorationRun(BaseModel):
created_at: datetime
+ checkpoint_blob_name: Optional[str] = None
+
+ latest_snapshot_blob_name: Optional[str] = None
+
triggered_by: Optional[str] = None
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index ac23c3e9c..b0c894850 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -757,6 +757,22 @@ def test_method_download_datahub_artifact(self, client: Structify, respx_mock: M
assert cast(Any, connector.is_closed) is True
assert isinstance(connector, BinaryAPIResponse)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ def test_method_download_datahub_artifact_with_all_params(self, client: Structify, respx_mock: MockRouter) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, BinaryAPIResponse)
+
@parametrize
@pytest.mark.respx(base_url=base_url)
def test_raw_response_download_datahub_artifact(self, client: Structify, respx_mock: MockRouter) -> None:
@@ -1416,6 +1432,7 @@ def test_method_upload_datahub_artifact(self, client: Structify) -> None:
connector = client.connectors.upload_datahub_artifact(
kind="kind",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
assert connector is None
@@ -1425,6 +1442,7 @@ def test_raw_response_upload_datahub_artifact(self, client: Structify) -> None:
response = client.connectors.with_raw_response.upload_datahub_artifact(
kind="kind",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
@@ -1438,6 +1456,7 @@ def test_streaming_response_upload_datahub_artifact(self, client: Structify) ->
with client.connectors.with_streaming_response.upload_datahub_artifact(
kind="kind",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
) as response:
assert not response.is_closed
@@ -1454,6 +1473,7 @@ def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
client.connectors.with_raw_response.upload_datahub_artifact(
kind="kind",
connector_id="",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
@@ -1461,6 +1481,7 @@ def test_path_params_upload_datahub_artifact(self, client: Structify) -> None:
client.connectors.with_raw_response.upload_datahub_artifact(
kind="",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
@@ -2183,6 +2204,24 @@ async def test_method_download_datahub_artifact(self, async_client: AsyncStructi
assert cast(Any, connector.is_closed) is True
assert isinstance(connector, AsyncBinaryAPIResponse)
+ @parametrize
+ @pytest.mark.respx(base_url=base_url)
+ async def test_method_download_datahub_artifact_with_all_params(
+ self, async_client: AsyncStructify, respx_mock: MockRouter
+ ) -> None:
+ respx_mock.get("/internal/connectors/182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e/datahub-artifacts/kind").mock(
+ return_value=httpx.Response(200, json={"foo": "bar"})
+ )
+ connector = await async_client.connectors.download_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert connector.is_closed
+ assert await connector.json() == {"foo": "bar"}
+ assert cast(Any, connector.is_closed) is True
+ assert isinstance(connector, AsyncBinaryAPIResponse)
+
@parametrize
@pytest.mark.respx(base_url=base_url)
async def test_raw_response_download_datahub_artifact(
@@ -2846,6 +2885,7 @@ async def test_method_upload_datahub_artifact(self, async_client: AsyncStructify
connector = await async_client.connectors.upload_datahub_artifact(
kind="kind",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
assert connector is None
@@ -2855,6 +2895,7 @@ async def test_raw_response_upload_datahub_artifact(self, async_client: AsyncStr
response = await async_client.connectors.with_raw_response.upload_datahub_artifact(
kind="kind",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
@@ -2868,6 +2909,7 @@ async def test_streaming_response_upload_datahub_artifact(self, async_client: As
async with async_client.connectors.with_streaming_response.upload_datahub_artifact(
kind="kind",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
) as response:
assert not response.is_closed
@@ -2884,6 +2926,7 @@ async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStru
await async_client.connectors.with_raw_response.upload_datahub_artifact(
kind="kind",
connector_id="",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
@@ -2891,5 +2934,6 @@ async def test_path_params_upload_datahub_artifact(self, async_client: AsyncStru
await async_client.connectors.with_raw_response.upload_datahub_artifact(
kind="",
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
file=b"Example data",
)
From da0f0de6d612197df5fd6c85d493e25474f71f1b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 00:27:09 +0000
Subject: [PATCH 079/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +--
src/structify/resources/chat.py | 25 +++++++++++++++++++
.../types/chat_list_sessions_params.py | 11 +++++++-
.../types/list_chat_sessions_response.py | 24 +++++++++++++++++-
tests/api_resources/test_chat.py | 6 +++++
5 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 6d446d830..88bdef53a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-62d07fb1a833f3e0d133fd032a77a545244b770f38c8346a193136ccd82774ba.yml
-openapi_spec_hash: f1abca6b91e0d3d80d7ec63242cd7837
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-51d3dfdd0ccf5e96a45c216b9e70887dc1347d8a853f7680a5d6d05f5ddffa3a.yml
+openapi_spec_hash: 1f18626ddf20e8070aef5670c79949f3
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 028f01964..7ec8d33cc 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -4,6 +4,7 @@
from typing import Union, Mapping, Optional, cast
from datetime import datetime
+from typing_extensions import Literal
import httpx
@@ -809,7 +810,10 @@ def list_sessions(
*,
team_id: str,
limit: Optional[int] | Omit = omit,
+ offset: Optional[int] | Omit = omit,
project_id: Optional[str] | Omit = omit,
+ search: Optional[str] | Omit = omit,
+ tab: Optional[Literal["my_chats", "favorites", "shared", "team", "recents", "from_messaging"]] | 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,
@@ -826,8 +830,14 @@ def list_sessions(
limit: Maximum number of sessions to return (default: 50)
+ offset: Number of sessions to skip (default: 0)
+
project_id: Project ID to filter chat sessions
+ search: Search query to filter sessions by name (case-insensitive)
+
+ tab: Tab filter for chat sessions
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -847,7 +857,10 @@ def list_sessions(
{
"team_id": team_id,
"limit": limit,
+ "offset": offset,
"project_id": project_id,
+ "search": search,
+ "tab": tab,
},
chat_list_sessions_params.ChatListSessionsParams,
),
@@ -2027,7 +2040,10 @@ async def list_sessions(
*,
team_id: str,
limit: Optional[int] | Omit = omit,
+ offset: Optional[int] | Omit = omit,
project_id: Optional[str] | Omit = omit,
+ search: Optional[str] | Omit = omit,
+ tab: Optional[Literal["my_chats", "favorites", "shared", "team", "recents", "from_messaging"]] | 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,
@@ -2044,8 +2060,14 @@ async def list_sessions(
limit: Maximum number of sessions to return (default: 50)
+ offset: Number of sessions to skip (default: 0)
+
project_id: Project ID to filter chat sessions
+ search: Search query to filter sessions by name (case-insensitive)
+
+ tab: Tab filter for chat sessions
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -2065,7 +2087,10 @@ async def list_sessions(
{
"team_id": team_id,
"limit": limit,
+ "offset": offset,
"project_id": project_id,
+ "search": search,
+ "tab": tab,
},
chat_list_sessions_params.ChatListSessionsParams,
),
diff --git a/src/structify/types/chat_list_sessions_params.py b/src/structify/types/chat_list_sessions_params.py
index ad0ab10d6..7c354bcd5 100644
--- a/src/structify/types/chat_list_sessions_params.py
+++ b/src/structify/types/chat_list_sessions_params.py
@@ -3,7 +3,7 @@
from __future__ import annotations
from typing import Optional
-from typing_extensions import Required, TypedDict
+from typing_extensions import Literal, Required, TypedDict
__all__ = ["ChatListSessionsParams"]
@@ -15,5 +15,14 @@ class ChatListSessionsParams(TypedDict, total=False):
limit: Optional[int]
"""Maximum number of sessions to return (default: 50)"""
+ offset: Optional[int]
+ """Number of sessions to skip (default: 0)"""
+
project_id: Optional[str]
"""Project ID to filter chat sessions"""
+
+ search: Optional[str]
+ """Search query to filter sessions by name (case-insensitive)"""
+
+ tab: Optional[Literal["my_chats", "favorites", "shared", "team", "recents", "from_messaging"]]
+ """Tab filter for chat sessions"""
diff --git a/src/structify/types/list_chat_sessions_response.py b/src/structify/types/list_chat_sessions_response.py
index a62d7c050..0b98a2930 100644
--- a/src/structify/types/list_chat_sessions_response.py
+++ b/src/structify/types/list_chat_sessions_response.py
@@ -7,7 +7,7 @@
from .chat_visibility import ChatVisibility
from .chat_session_role import ChatSessionRole
-__all__ = ["ListChatSessionsResponse", "Session"]
+__all__ = ["ListChatSessionsResponse", "Session", "TabCounts"]
class Session(BaseModel):
@@ -40,7 +40,29 @@ class Session(BaseModel):
teams_conversation_id: Optional[str] = None
+class TabCounts(BaseModel):
+ """Per-tab counts for chat session listing"""
+
+ favorites: int
+
+ from_messaging: int
+
+ my_chats: int
+
+ recents: int
+
+ shared: int
+
+ team: int
+
+
class ListChatSessionsResponse(BaseModel):
"""Response for listing chat sessions"""
sessions: List[Session]
+
+ tab_counts: TabCounts
+ """Per-tab counts for chat session listing"""
+
+ total_count: int
+ """Total number of chat sessions matching the query (for pagination)"""
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index d984062af..6b6999fc5 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -866,7 +866,10 @@ def test_method_list_sessions_with_all_params(self, client: Structify) -> None:
chat = client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
+ offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ search="search",
+ tab="my_chats",
)
assert_matches_type(ListChatSessionsResponse, chat, path=["response"])
@@ -2429,7 +2432,10 @@ async def test_method_list_sessions_with_all_params(self, async_client: AsyncStr
chat = await async_client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
+ offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ search="search",
+ tab="my_chats",
)
assert_matches_type(ListChatSessionsResponse, chat, path=["response"])
From 15d506ee5ea1a4a7bf1a0091237718e1f94edad9 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 02:07:00 +0000
Subject: [PATCH 080/105] chore(tests): bump steady to v0.19.4
---
scripts/mock | 6 +++---
scripts/test | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/mock b/scripts/mock
index 38201de83..e1c19e88f 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}"
# Run steady mock on the given spec
if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
- npm exec --package=@stdy/cli@0.19.3 -- steady --version
+ npm exec --package=@stdy/cli@0.19.4 -- steady --version
- npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL" &> .stdy.log &
+ npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
@@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then
echo
else
- npm exec --package=@stdy/cli@0.19.3 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets "$URL"
+ npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
fi
diff --git a/scripts/test b/scripts/test
index 2dfdc4093..36fab0ae3 100755
--- a/scripts/test
+++ b/scripts/test
@@ -43,7 +43,7 @@ elif ! steady_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the steady command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.3 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-query-object-format=brackets${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.4 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
echo
exit 1
From afa480c9b5df39ee202220baf8a7dbf7a367eb39 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 02:14:34 +0000
Subject: [PATCH 081/105] chore(tests): bump steady to v0.19.5
---
scripts/mock | 6 +++---
scripts/test | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/mock b/scripts/mock
index e1c19e88f..ab814d383 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}"
# Run steady mock on the given spec
if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
- npm exec --package=@stdy/cli@0.19.4 -- steady --version
+ npm exec --package=@stdy/cli@0.19.5 -- steady --version
- npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
+ npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
@@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then
echo
else
- npm exec --package=@stdy/cli@0.19.4 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
+ npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
fi
diff --git a/scripts/test b/scripts/test
index 36fab0ae3..d1c8e1a9d 100755
--- a/scripts/test
+++ b/scripts/test
@@ -43,7 +43,7 @@ elif ! steady_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the steady command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.4 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.5 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
echo
exit 1
From d31cd4b98af129060626b47828b9d99dfae6dbce Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 19:40:26 +0000
Subject: [PATCH 082/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/resources/chat.py | 8 ++++++++
src/structify/types/chat_list_sessions_params.py | 3 +++
src/structify/types/list_chat_sessions_response.py | 2 ++
tests/api_resources/test_chat.py | 2 ++
5 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 88bdef53a..4abe22991 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-51d3dfdd0ccf5e96a45c216b9e70887dc1347d8a853f7680a5d6d05f5ddffa3a.yml
-openapi_spec_hash: 1f18626ddf20e8070aef5670c79949f3
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-f5a1824fac5f9cb28723c4288dbab666954b831e159221c5d04301e4a37893ea.yml
+openapi_spec_hash: 4c865670a504eabe861e51a10bb3ac84
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 7ec8d33cc..1d29f7dbb 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -809,6 +809,7 @@ def list_sessions(
self,
*,
team_id: str,
+ connector_id: Optional[str] | Omit = omit,
limit: Optional[int] | Omit = omit,
offset: Optional[int] | Omit = omit,
project_id: Optional[str] | Omit = omit,
@@ -828,6 +829,8 @@ def list_sessions(
Args:
team_id: Team ID to filter chat sessions
+ connector_id: Connector ID to filter chat sessions that use this connector
+
limit: Maximum number of sessions to return (default: 50)
offset: Number of sessions to skip (default: 0)
@@ -856,6 +859,7 @@ def list_sessions(
query=maybe_transform(
{
"team_id": team_id,
+ "connector_id": connector_id,
"limit": limit,
"offset": offset,
"project_id": project_id,
@@ -2039,6 +2043,7 @@ async def list_sessions(
self,
*,
team_id: str,
+ connector_id: Optional[str] | Omit = omit,
limit: Optional[int] | Omit = omit,
offset: Optional[int] | Omit = omit,
project_id: Optional[str] | Omit = omit,
@@ -2058,6 +2063,8 @@ async def list_sessions(
Args:
team_id: Team ID to filter chat sessions
+ connector_id: Connector ID to filter chat sessions that use this connector
+
limit: Maximum number of sessions to return (default: 50)
offset: Number of sessions to skip (default: 0)
@@ -2086,6 +2093,7 @@ async def list_sessions(
query=await async_maybe_transform(
{
"team_id": team_id,
+ "connector_id": connector_id,
"limit": limit,
"offset": offset,
"project_id": project_id,
diff --git a/src/structify/types/chat_list_sessions_params.py b/src/structify/types/chat_list_sessions_params.py
index 7c354bcd5..70db59561 100644
--- a/src/structify/types/chat_list_sessions_params.py
+++ b/src/structify/types/chat_list_sessions_params.py
@@ -12,6 +12,9 @@ class ChatListSessionsParams(TypedDict, total=False):
team_id: Required[str]
"""Team ID to filter chat sessions"""
+ connector_id: Optional[str]
+ """Connector ID to filter chat sessions that use this connector"""
+
limit: Optional[int]
"""Maximum number of sessions to return (default: 50)"""
diff --git a/src/structify/types/list_chat_sessions_response.py b/src/structify/types/list_chat_sessions_response.py
index 0b98a2930..320833ee3 100644
--- a/src/structify/types/list_chat_sessions_response.py
+++ b/src/structify/types/list_chat_sessions_response.py
@@ -15,6 +15,8 @@ class Session(BaseModel):
created_at: datetime
+ has_workflow_schedule: bool
+
is_favorite: bool
team_id: str
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 6b6999fc5..c2800d934 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -865,6 +865,7 @@ def test_method_list_sessions(self, client: Structify) -> None:
def test_method_list_sessions_with_all_params(self, client: Structify) -> None:
chat = client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
@@ -2431,6 +2432,7 @@ async def test_method_list_sessions(self, async_client: AsyncStructify) -> None:
async def test_method_list_sessions_with_all_params(self, async_client: AsyncStructify) -> None:
chat = await async_client.chat.list_sessions(
team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
limit=0,
offset=0,
project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
From 387dd1845dfe380e4f36dfa592b57e3131f76fed Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 20:30:03 +0000
Subject: [PATCH 083/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +--
.../resources/connectors/connectors.py | 36 ++++++++++++-------
.../connector_get_explorer_chat_params.py | 12 +++++--
tests/api_resources/test_connectors.py | 30 +++++++++++-----
4 files changed, 57 insertions(+), 25 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 4abe22991..4a68662b8 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-f5a1824fac5f9cb28723c4288dbab666954b831e159221c5d04301e4a37893ea.yml
-openapi_spec_hash: 4c865670a504eabe861e51a10bb3ac84
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-86fd302959cd66342ae2106e9952bea2db1925a27e57c04d0527548fcb5c33c6.yml
+openapi_spec_hash: 3b95b68d6fbf433814fc71e8bede464c
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 07e6e43fe..fe84b0d2c 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -903,7 +903,10 @@ def get_explorer_chat(
self,
connector_id: str,
*,
- run_id: str,
+ database_id: Optional[str] | Omit = omit,
+ run_id: Optional[str] | Omit = omit,
+ schema_id: Optional[str] | Omit = omit,
+ table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -912,12 +915,9 @@ def get_explorer_chat(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ExplorerChatResponse:
"""
- Returns chats for all phases (table discovery, column discovery for each table,
- etc.)
+ Optionally filter by run, database, schema, or table
Args:
- run_id: Exploration run ID (required)
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -936,7 +936,13 @@ def get_explorer_chat(
extra_body=extra_body,
timeout=timeout,
query=maybe_transform(
- {"run_id": run_id}, connector_get_explorer_chat_params.ConnectorGetExplorerChatParams
+ {
+ "database_id": database_id,
+ "run_id": run_id,
+ "schema_id": schema_id,
+ "table_id": table_id,
+ },
+ connector_get_explorer_chat_params.ConnectorGetExplorerChatParams,
),
),
cast_to=ExplorerChatResponse,
@@ -2129,7 +2135,10 @@ async def get_explorer_chat(
self,
connector_id: str,
*,
- run_id: str,
+ database_id: Optional[str] | Omit = omit,
+ run_id: Optional[str] | Omit = omit,
+ schema_id: Optional[str] | Omit = omit,
+ table_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.
# The extra values given here take precedence over values defined on the client or passed to this method.
extra_headers: Headers | None = None,
@@ -2138,12 +2147,9 @@ async def get_explorer_chat(
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> ExplorerChatResponse:
"""
- Returns chats for all phases (table discovery, column discovery for each table,
- etc.)
+ Optionally filter by run, database, schema, or table
Args:
- run_id: Exploration run ID (required)
-
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -2162,7 +2168,13 @@ async def get_explorer_chat(
extra_body=extra_body,
timeout=timeout,
query=await async_maybe_transform(
- {"run_id": run_id}, connector_get_explorer_chat_params.ConnectorGetExplorerChatParams
+ {
+ "database_id": database_id,
+ "run_id": run_id,
+ "schema_id": schema_id,
+ "table_id": table_id,
+ },
+ connector_get_explorer_chat_params.ConnectorGetExplorerChatParams,
),
),
cast_to=ExplorerChatResponse,
diff --git a/src/structify/types/connector_get_explorer_chat_params.py b/src/structify/types/connector_get_explorer_chat_params.py
index f84ede929..32d136fc4 100644
--- a/src/structify/types/connector_get_explorer_chat_params.py
+++ b/src/structify/types/connector_get_explorer_chat_params.py
@@ -2,11 +2,17 @@
from __future__ import annotations
-from typing_extensions import Required, TypedDict
+from typing import Optional
+from typing_extensions import TypedDict
__all__ = ["ConnectorGetExplorerChatParams"]
class ConnectorGetExplorerChatParams(TypedDict, total=False):
- run_id: Required[str]
- """Exploration run ID (required)"""
+ database_id: Optional[str]
+
+ run_id: Optional[str]
+
+ schema_id: Optional[str]
+
+ table_id: Optional[str]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index b0c894850..d8f4aab12 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -1029,7 +1029,17 @@ def test_path_params_get_exploration_status(self, client: Structify) -> None:
def test_method_get_explorer_chat(self, client: Structify) -> None:
connector = client.connectors.get_explorer_chat(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- run_id="run_id",
+ )
+ assert_matches_type(ExplorerChatResponse, connector, path=["response"])
+
+ @parametrize
+ def test_method_get_explorer_chat_with_all_params(self, client: Structify) -> None:
+ connector = client.connectors.get_explorer_chat(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ExplorerChatResponse, connector, path=["response"])
@@ -1037,7 +1047,6 @@ def test_method_get_explorer_chat(self, client: Structify) -> None:
def test_raw_response_get_explorer_chat(self, client: Structify) -> None:
response = client.connectors.with_raw_response.get_explorer_chat(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- run_id="run_id",
)
assert response.is_closed is True
@@ -1049,7 +1058,6 @@ def test_raw_response_get_explorer_chat(self, client: Structify) -> None:
def test_streaming_response_get_explorer_chat(self, client: Structify) -> None:
with client.connectors.with_streaming_response.get_explorer_chat(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- run_id="run_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -1064,7 +1072,6 @@ def test_path_params_get_explorer_chat(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
client.connectors.with_raw_response.get_explorer_chat(
connector_id="",
- run_id="run_id",
)
@parametrize
@@ -2482,7 +2489,17 @@ async def test_path_params_get_exploration_status(self, async_client: AsyncStruc
async def test_method_get_explorer_chat(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.get_explorer_chat(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- run_id="run_id",
+ )
+ assert_matches_type(ExplorerChatResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_method_get_explorer_chat_with_all_params(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.get_explorer_chat(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ database_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert_matches_type(ExplorerChatResponse, connector, path=["response"])
@@ -2490,7 +2507,6 @@ async def test_method_get_explorer_chat(self, async_client: AsyncStructify) -> N
async def test_raw_response_get_explorer_chat(self, async_client: AsyncStructify) -> None:
response = await async_client.connectors.with_raw_response.get_explorer_chat(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- run_id="run_id",
)
assert response.is_closed is True
@@ -2502,7 +2518,6 @@ async def test_raw_response_get_explorer_chat(self, async_client: AsyncStructify
async def test_streaming_response_get_explorer_chat(self, async_client: AsyncStructify) -> None:
async with async_client.connectors.with_streaming_response.get_explorer_chat(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- run_id="run_id",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
@@ -2517,7 +2532,6 @@ async def test_path_params_get_explorer_chat(self, async_client: AsyncStructify)
with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
await async_client.connectors.with_raw_response.get_explorer_chat(
connector_id="",
- run_id="run_id",
)
@parametrize
From 37cd67f7a018a7d6b37aea2646ca1f9d5559977d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Sat, 21 Mar 2026 23:24:17 +0000
Subject: [PATCH 084/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/connector.py | 7 -------
src/structify/types/entity_list_jobs_response.py | 2 ++
src/structify/types/exploration_run.py | 3 +++
src/structify/types/explore_status_response.py | 2 --
src/structify/types/job_cancel_response.py | 2 ++
6 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 4a68662b8..874be1409 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-86fd302959cd66342ae2106e9952bea2db1925a27e57c04d0527548fcb5c33c6.yml
-openapi_spec_hash: 3b95b68d6fbf433814fc71e8bede464c
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-f7ed4ced2a1536efc601167a6d62678e8e8364c3bb1a55f0afd9e1ef9e6b2f95.yml
+openapi_spec_hash: 8af7b747d839855334386e6c53208ad0
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index a6d645c0e..4a006c785 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -6,7 +6,6 @@
from .._models import BaseModel
from .connector_category import ConnectorCategory
-from .exploration_status import ExplorationStatus
__all__ = ["Connector"]
@@ -16,8 +15,6 @@ class Connector(BaseModel):
created_at: datetime
- exploration_status: ExplorationStatus
-
known_connector_type: str
name: str
@@ -38,10 +35,6 @@ class Connector(BaseModel):
description: Optional[str] = None
- exploration_error: Optional[str] = None
-
- exploration_started_at: Optional[datetime] = None
-
nango_connection_id: Optional[str] = None
oauth_scopes: Optional[List[Optional[str]]] = None
diff --git a/src/structify/types/entity_list_jobs_response.py b/src/structify/types/entity_list_jobs_response.py
index 31808d0c5..85ddcb6dc 100644
--- a/src/structify/types/entity_list_jobs_response.py
+++ b/src/structify/types/entity_list_jobs_response.py
@@ -30,6 +30,8 @@ class EntityListJobsResponseItem(BaseModel):
dataset_id: Optional[str] = None
+ exploration_run_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
diff --git a/src/structify/types/exploration_run.py b/src/structify/types/exploration_run.py
index 1d89e8a1c..e4bb3798a 100644
--- a/src/structify/types/exploration_run.py
+++ b/src/structify/types/exploration_run.py
@@ -4,6 +4,7 @@
from datetime import datetime
from .._models import BaseModel
+from .exploration_status import ExplorationStatus
__all__ = ["ExplorationRun"]
@@ -15,6 +16,8 @@ class ExplorationRun(BaseModel):
created_at: datetime
+ status: ExplorationStatus
+
checkpoint_blob_name: Optional[str] = None
latest_snapshot_blob_name: Optional[str] = None
diff --git a/src/structify/types/explore_status_response.py b/src/structify/types/explore_status_response.py
index 475324a99..4275c265a 100644
--- a/src/structify/types/explore_status_response.py
+++ b/src/structify/types/explore_status_response.py
@@ -12,6 +12,4 @@
class ExploreStatusResponse(BaseModel):
status: ExplorationStatus
- error: Optional[str] = None
-
started_at: Optional[datetime] = None
diff --git a/src/structify/types/job_cancel_response.py b/src/structify/types/job_cancel_response.py
index 75a5f4673..01f4a4293 100644
--- a/src/structify/types/job_cancel_response.py
+++ b/src/structify/types/job_cancel_response.py
@@ -30,6 +30,8 @@ class JobCancelResponse(BaseModel):
dataset_id: Optional[str] = None
+ exploration_run_id: Optional[str] = None
+
max_errors: Optional[int] = None
max_execution_time_secs: Optional[int] = None
From 60cf0874a5e1299c02ca7dea7118ae831c51e6ef Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 00:13:14 +0000
Subject: [PATCH 085/105] feat(api): api update
---
.stats.yml | 6 +-
README.md | 10 +-
api.md | 4 -
src/structify/resources/chat.py | 120 +--------------
src/structify/resources/documents.py | 141 +----------------
src/structify/resources/sessions.py | 144 +-----------------
src/structify/types/__init__.py | 6 -
.../types/chat_upload_input_file_params.py | 17 ---
.../types/chat_upload_input_file_response.py | 23 ---
src/structify/types/document_list_response.py | 2 +
src/structify/types/document_upload_params.py | 22 ---
.../session_upload_node_output_data_params.py | 28 ----
src/structify/types/workflow_session_node.py | 2 +
tests/api_resources/test_chat.py | 101 ------------
tests/api_resources/test_documents.py | 96 ------------
tests/api_resources/test_sessions.py | 114 --------------
16 files changed, 22 insertions(+), 814 deletions(-)
delete mode 100644 src/structify/types/chat_upload_input_file_params.py
delete mode 100644 src/structify/types/chat_upload_input_file_response.py
delete mode 100644 src/structify/types/document_upload_params.py
delete mode 100644 src/structify/types/session_upload_node_output_data_params.py
diff --git a/.stats.yml b/.stats.yml
index 874be1409..c38ce07d9 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 249
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-f7ed4ced2a1536efc601167a6d62678e8e8364c3bb1a55f0afd9e1ef9e6b2f95.yml
-openapi_spec_hash: 8af7b747d839855334386e6c53208ad0
+configured_endpoints: 246
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-8acf14fe5e003f7ba6a5297b607616f6b42ab5b9b6eb40dafaab336260d29f77.yml
+openapi_spec_hash: 5e7378a0d31076f6bbe2cb8d65f177d6
config_hash: 63c3aa248700e46cfe93b79afa9f0065
diff --git a/README.md b/README.md
index 2a8ad2bb6..debe126cf 100644
--- a/README.md
+++ b/README.md
@@ -195,11 +195,11 @@ from structify import Structify
client = Structify()
-client.chat.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=Path("/path/to/file"),
- content_type="content_type",
- file_name="file_name",
+client.connectors.upload_datahub_artifact(
+ kind="kind",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ file=Path("/path/to/file"),
)
```
diff --git a/api.md b/api.md
index fad0d5feb..6183db669 100644
--- a/api.md
+++ b/api.md
@@ -134,7 +134,6 @@ from structify.types import (
ChatLoadFilesResponse,
ChatLoadInputFilesResponse,
ChatRevertToCommitResponse,
- ChatUploadInputFileResponse,
)
```
@@ -171,7 +170,6 @@ Methods:
- client.chat.update_session(session_id, \*\*params) -> ChatSession
- client.chat.update_session_favorite(session_id, \*\*params) -> ChatSession
- client.chat.update_visibility(session_id, \*\*params) -> UpdateVisibilityResponse
-- client.chat.upload_input_file(chat_id, \*\*params) -> ChatUploadInputFileResponse
# Teams
@@ -521,7 +519,6 @@ Methods:
- client.documents.list(\*\*params) -> DocumentListResponse
- client.documents.delete(\*\*params) -> None
- client.documents.download(\*\*params) -> DocumentDownloadResponse
-- client.documents.upload(\*\*params) -> None
# Jobs
@@ -641,7 +638,6 @@ Methods:
- client.sessions.update_node(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.update_node_progress(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.upload_dashboard_layout(session_id, \*\*params) -> WorkflowSession
-- client.sessions.upload_node_output_data(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.upload_node_visualization_output(node_id, \*\*params) -> WorkflowSessionNode
# WorkflowSchedule
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 1d29f7dbb..2ced61cbf 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Union, Mapping, Optional, cast
+from typing import Union, Optional
from datetime import datetime
from typing_extensions import Literal
@@ -25,13 +25,12 @@
chat_admin_issue_found_params,
chat_delete_input_file_params,
chat_update_visibility_params,
- chat_upload_input_file_params,
chat_grant_admin_override_params,
chat_update_session_favorite_params,
chat_copy_node_output_by_code_hash_params,
)
-from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr, omit, not_given
-from .._utils import extract_files, path_template, maybe_transform, deepcopy_minimal, async_maybe_transform
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
+from .._utils import path_template, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -76,7 +75,6 @@
from ..types.chat_revert_to_commit_response import ChatRevertToCommitResponse
from ..types.chat_delete_input_file_response import ChatDeleteInputFileResponse
from ..types.chat_get_partial_chats_response import ChatGetPartialChatsResponse
-from ..types.chat_upload_input_file_response import ChatUploadInputFileResponse
from ..types.chat_get_session_timeline_response import ChatGetSessionTimelineResponse
from ..types.chat_copy_node_output_by_code_hash_response import ChatCopyNodeOutputByCodeHashResponse
@@ -1262,56 +1260,6 @@ def update_visibility(
cast_to=UpdateVisibilityResponse,
)
- def upload_input_file(
- self,
- chat_id: str,
- *,
- content: FileTypes,
- content_type: str,
- file_name: str,
- # 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,
- ) -> ChatUploadInputFileResponse:
- """
- Upload an input file to a chat session's bucket storage
-
- Args:
- 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
- """
- if not chat_id:
- raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
- body = deepcopy_minimal(
- {
- "content": content,
- "content_type": content_type,
- "file_name": file_name,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- path_template("/chat/input-files/upload/{chat_id}", chat_id=chat_id),
- body=maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ChatUploadInputFileResponse,
- )
-
class AsyncChatResource(AsyncAPIResource):
@cached_property
@@ -2504,56 +2452,6 @@ async def update_visibility(
cast_to=UpdateVisibilityResponse,
)
- async def upload_input_file(
- self,
- chat_id: str,
- *,
- content: FileTypes,
- content_type: str,
- file_name: str,
- # 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,
- ) -> ChatUploadInputFileResponse:
- """
- Upload an input file to a chat session's bucket storage
-
- Args:
- 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
- """
- if not chat_id:
- raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
- body = deepcopy_minimal(
- {
- "content": content,
- "content_type": content_type,
- "file_name": file_name,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- path_template("/chat/input-files/upload/{chat_id}", chat_id=chat_id),
- body=await async_maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ChatUploadInputFileResponse,
- )
-
class ChatResourceWithRawResponse:
def __init__(self, chat: ChatResource) -> None:
@@ -2653,9 +2551,6 @@ def __init__(self, chat: ChatResource) -> None:
self.update_visibility = to_raw_response_wrapper(
chat.update_visibility,
)
- self.upload_input_file = to_raw_response_wrapper(
- chat.upload_input_file,
- )
class AsyncChatResourceWithRawResponse:
@@ -2756,9 +2651,6 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.update_visibility = async_to_raw_response_wrapper(
chat.update_visibility,
)
- self.upload_input_file = async_to_raw_response_wrapper(
- chat.upload_input_file,
- )
class ChatResourceWithStreamingResponse:
@@ -2859,9 +2751,6 @@ def __init__(self, chat: ChatResource) -> None:
self.update_visibility = to_streamed_response_wrapper(
chat.update_visibility,
)
- self.upload_input_file = to_streamed_response_wrapper(
- chat.upload_input_file,
- )
class AsyncChatResourceWithStreamingResponse:
@@ -2962,6 +2851,3 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.update_visibility = async_to_streamed_response_wrapper(
chat.update_visibility,
)
- self.upload_input_file = async_to_streamed_response_wrapper(
- chat.upload_input_file,
- )
diff --git a/src/structify/resources/documents.py b/src/structify/resources/documents.py
index 100fa7cf8..5076a058e 100644
--- a/src/structify/resources/documents.py
+++ b/src/structify/resources/documents.py
@@ -2,14 +2,13 @@
from __future__ import annotations
-from typing import Mapping, Optional, cast
-from typing_extensions import Literal
+from typing import Optional
import httpx
-from ..types import document_list_params, document_delete_params, document_upload_params, document_download_params
-from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, omit, not_given
-from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
+from ..types import document_list_params, document_delete_params, document_download_params
+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 (
@@ -156,66 +155,6 @@ def download(
cast_to=DocumentDownloadResponse,
)
- def upload(
- self,
- *,
- content: FileTypes,
- file_type: Literal["Text", "PDF", "SEC"],
- path: FileTypes,
- dataset: Optional[str] | Omit = omit,
- project_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.
- # 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:
- """
- Add a new file to the database
-
- Args:
- 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 {})}
- body = deepcopy_minimal(
- {
- "content": content,
- "file_type": file_type,
- "path": path,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["content"], ["path"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers["Content-Type"] = "multipart/form-data"
- return self._post(
- "/documents/upload",
- body=maybe_transform(body, document_upload_params.DocumentUploadParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=maybe_transform(
- {
- "dataset": dataset,
- "project_id": project_id,
- },
- document_upload_params.DocumentUploadParams,
- ),
- ),
- cast_to=NoneType,
- )
-
class AsyncDocumentsResource(AsyncAPIResource):
@cached_property
@@ -348,66 +287,6 @@ async def download(
cast_to=DocumentDownloadResponse,
)
- async def upload(
- self,
- *,
- content: FileTypes,
- file_type: Literal["Text", "PDF", "SEC"],
- path: FileTypes,
- dataset: Optional[str] | Omit = omit,
- project_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.
- # 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:
- """
- Add a new file to the database
-
- Args:
- 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 {})}
- body = deepcopy_minimal(
- {
- "content": content,
- "file_type": file_type,
- "path": path,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["content"], ["path"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers["Content-Type"] = "multipart/form-data"
- return await self._post(
- "/documents/upload",
- body=await async_maybe_transform(body, document_upload_params.DocumentUploadParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers,
- extra_query=extra_query,
- extra_body=extra_body,
- timeout=timeout,
- query=await async_maybe_transform(
- {
- "dataset": dataset,
- "project_id": project_id,
- },
- document_upload_params.DocumentUploadParams,
- ),
- ),
- cast_to=NoneType,
- )
-
class DocumentsResourceWithRawResponse:
def __init__(self, documents: DocumentsResource) -> None:
@@ -422,9 +301,6 @@ def __init__(self, documents: DocumentsResource) -> None:
self.download = to_raw_response_wrapper(
documents.download,
)
- self.upload = to_raw_response_wrapper(
- documents.upload,
- )
class AsyncDocumentsResourceWithRawResponse:
@@ -440,9 +316,6 @@ def __init__(self, documents: AsyncDocumentsResource) -> None:
self.download = async_to_raw_response_wrapper(
documents.download,
)
- self.upload = async_to_raw_response_wrapper(
- documents.upload,
- )
class DocumentsResourceWithStreamingResponse:
@@ -458,9 +331,6 @@ def __init__(self, documents: DocumentsResource) -> None:
self.download = to_streamed_response_wrapper(
documents.download,
)
- self.upload = to_streamed_response_wrapper(
- documents.upload,
- )
class AsyncDocumentsResourceWithStreamingResponse:
@@ -476,6 +346,3 @@ def __init__(self, documents: AsyncDocumentsResource) -> None:
self.download = async_to_streamed_response_wrapper(
documents.download,
)
- self.upload = async_to_streamed_response_wrapper(
- documents.upload,
- )
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 08f675436..2f9b16793 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Dict, Mapping, Iterable, Optional, cast
+from typing import Dict, Iterable, Optional
from typing_extensions import Literal, overload
import httpx
@@ -21,18 +21,10 @@
session_request_confirmation_params,
session_update_node_progress_params,
session_upload_dashboard_layout_params,
- session_upload_node_output_data_params,
session_upload_node_visualization_output_params,
)
-from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
-from .._utils import (
- extract_files,
- path_template,
- required_args,
- maybe_transform,
- deepcopy_minimal,
- async_maybe_transform,
-)
+from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from .._utils import path_template, required_args, maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -771,64 +763,6 @@ def upload_dashboard_layout(
cast_to=WorkflowSession,
)
- def upload_node_output_data(
- self,
- node_id: str,
- *,
- content: FileTypes,
- cache_final_rows: Optional[int] | Omit = omit,
- cache_final_size_bytes: Optional[int] | Omit = omit,
- cache_max_bytes: Optional[int] | Omit = omit,
- cache_original_rows: Optional[int] | Omit = omit,
- cache_original_size_bytes: Optional[int] | Omit = omit,
- cache_truncated: Optional[bool] | Omit = omit,
- output_schema: 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,
- ) -> WorkflowSessionNode:
- """
- Args:
- 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
- """
- if not node_id:
- raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
- body = deepcopy_minimal(
- {
- "content": content,
- "cache_final_rows": cache_final_rows,
- "cache_final_size_bytes": cache_final_size_bytes,
- "cache_max_bytes": cache_max_bytes,
- "cache_original_rows": cache_original_rows,
- "cache_original_size_bytes": cache_original_size_bytes,
- "cache_truncated": cache_truncated,
- "output_schema": output_schema,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return self._post(
- path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
- body=maybe_transform(body, session_upload_node_output_data_params.SessionUploadNodeOutputDataParams),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WorkflowSessionNode,
- )
-
def upload_node_visualization_output(
self,
node_id: str,
@@ -1570,66 +1504,6 @@ async def upload_dashboard_layout(
cast_to=WorkflowSession,
)
- async def upload_node_output_data(
- self,
- node_id: str,
- *,
- content: FileTypes,
- cache_final_rows: Optional[int] | Omit = omit,
- cache_final_size_bytes: Optional[int] | Omit = omit,
- cache_max_bytes: Optional[int] | Omit = omit,
- cache_original_rows: Optional[int] | Omit = omit,
- cache_original_size_bytes: Optional[int] | Omit = omit,
- cache_truncated: Optional[bool] | Omit = omit,
- output_schema: 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,
- ) -> WorkflowSessionNode:
- """
- Args:
- 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
- """
- if not node_id:
- raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
- body = deepcopy_minimal(
- {
- "content": content,
- "cache_final_rows": cache_final_rows,
- "cache_final_size_bytes": cache_final_size_bytes,
- "cache_max_bytes": cache_max_bytes,
- "cache_original_rows": cache_original_rows,
- "cache_original_size_bytes": cache_original_size_bytes,
- "cache_truncated": cache_truncated,
- "output_schema": output_schema,
- }
- )
- files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
- # It should be noted that the actual Content-Type header that will be
- # sent to the server will contain a `boundary` parameter, e.g.
- # multipart/form-data; boundary=---abc--
- extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
- return await self._post(
- path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
- body=await async_maybe_transform(
- body, session_upload_node_output_data_params.SessionUploadNodeOutputDataParams
- ),
- files=files,
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=WorkflowSessionNode,
- )
-
async def upload_node_visualization_output(
self,
node_id: str,
@@ -1723,9 +1597,6 @@ def __init__(self, sessions: SessionsResource) -> None:
self.upload_dashboard_layout = to_raw_response_wrapper(
sessions.upload_dashboard_layout,
)
- self.upload_node_output_data = to_raw_response_wrapper(
- sessions.upload_node_output_data,
- )
self.upload_node_visualization_output = to_raw_response_wrapper(
sessions.upload_node_visualization_output,
)
@@ -1787,9 +1658,6 @@ def __init__(self, sessions: AsyncSessionsResource) -> None:
self.upload_dashboard_layout = async_to_raw_response_wrapper(
sessions.upload_dashboard_layout,
)
- self.upload_node_output_data = async_to_raw_response_wrapper(
- sessions.upload_node_output_data,
- )
self.upload_node_visualization_output = async_to_raw_response_wrapper(
sessions.upload_node_visualization_output,
)
@@ -1851,9 +1719,6 @@ def __init__(self, sessions: SessionsResource) -> None:
self.upload_dashboard_layout = to_streamed_response_wrapper(
sessions.upload_dashboard_layout,
)
- self.upload_node_output_data = to_streamed_response_wrapper(
- sessions.upload_node_output_data,
- )
self.upload_node_visualization_output = to_streamed_response_wrapper(
sessions.upload_node_visualization_output,
)
@@ -1915,9 +1780,6 @@ def __init__(self, sessions: AsyncSessionsResource) -> None:
self.upload_dashboard_layout = async_to_streamed_response_wrapper(
sessions.upload_dashboard_layout,
)
- self.upload_node_output_data = async_to_streamed_response_wrapper(
- sessions.upload_node_output_data,
- )
self.upload_node_visualization_output = async_to_streamed_response_wrapper(
sessions.upload_node_visualization_output,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 3d7bb30bb..eabda1f97 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -161,7 +161,6 @@
from .dataset_match_response import DatasetMatchResponse as DatasetMatchResponse
from .document_delete_params import DocumentDeleteParams as DocumentDeleteParams
from .document_list_response import DocumentListResponse as DocumentListResponse
-from .document_upload_params import DocumentUploadParams as DocumentUploadParams
from .entity_delete_response import EntityDeleteResponse as EntityDeleteResponse
from .entity_derive_response import EntityDeriveResponse as EntityDeriveResponse
from .entity_search_response import EntitySearchResponse as EntitySearchResponse
@@ -283,7 +282,6 @@
from .chat_admin_issue_found_params import ChatAdminIssueFoundParams as ChatAdminIssueFoundParams
from .chat_delete_input_file_params import ChatDeleteInputFileParams as ChatDeleteInputFileParams
from .chat_update_visibility_params import ChatUpdateVisibilityParams as ChatUpdateVisibilityParams
-from .chat_upload_input_file_params import ChatUploadInputFileParams as ChatUploadInputFileParams
from .code_apply_manual_edit_params import CodeApplyManualEditParams as CodeApplyManualEditParams
from .connector_catalog_list_params import ConnectorCatalogListParams as ConnectorCatalogListParams
from .connector_table_path_response import ConnectorTablePathResponse as ConnectorTablePathResponse
@@ -316,7 +314,6 @@
from .workflow_schedule_pause_params import WorkflowSchedulePauseParams as WorkflowSchedulePauseParams
from .chat_delete_input_file_response import ChatDeleteInputFileResponse as ChatDeleteInputFileResponse
from .chat_get_partial_chats_response import ChatGetPartialChatsResponse as ChatGetPartialChatsResponse
-from .chat_upload_input_file_response import ChatUploadInputFileResponse as ChatUploadInputFileResponse
from .connector_catalog_list_response import ConnectorCatalogListResponse as ConnectorCatalogListResponse
from .entity_update_property_response import EntityUpdatePropertyResponse as EntityUpdatePropertyResponse
from .session_edit_node_output_params import SessionEditNodeOutputParams as SessionEditNodeOutputParams
@@ -377,9 +374,6 @@
from .session_upload_dashboard_layout_params import (
SessionUploadDashboardLayoutParams as SessionUploadDashboardLayoutParams,
)
-from .session_upload_node_output_data_params import (
- SessionUploadNodeOutputDataParams as SessionUploadNodeOutputDataParams,
-)
from .dataset_count_missing_embeddings_params import (
DatasetCountMissingEmbeddingsParams as DatasetCountMissingEmbeddingsParams,
)
diff --git a/src/structify/types/chat_upload_input_file_params.py b/src/structify/types/chat_upload_input_file_params.py
deleted file mode 100644
index a4a6eb732..000000000
--- a/src/structify/types/chat_upload_input_file_params.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["ChatUploadInputFileParams"]
-
-
-class ChatUploadInputFileParams(TypedDict, total=False):
- content: Required[FileTypes]
-
- content_type: Required[str]
-
- file_name: Required[str]
diff --git a/src/structify/types/chat_upload_input_file_response.py b/src/structify/types/chat_upload_input_file_response.py
deleted file mode 100644
index 29e08729c..000000000
--- a/src/structify/types/chat_upload_input_file_response.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from datetime import datetime
-
-from .._models import BaseModel
-
-__all__ = ["ChatUploadInputFileResponse", "File"]
-
-
-class File(BaseModel):
- chat_session_id: str
-
- content_type: str
-
- created_at: datetime
-
- file_size: int
-
- filename: str
-
-
-class ChatUploadInputFileResponse(BaseModel):
- file: File
diff --git a/src/structify/types/document_list_response.py b/src/structify/types/document_list_response.py
index aeb9c2ea5..062d7f758 100644
--- a/src/structify/types/document_list_response.py
+++ b/src/structify/types/document_list_response.py
@@ -16,6 +16,8 @@ class DocumentListResponseItem(BaseModel):
file_bytes: object
+ file_size: int
+
file_type: Literal["Text", "PDF", "SEC"]
name: str
diff --git a/src/structify/types/document_upload_params.py b/src/structify/types/document_upload_params.py
deleted file mode 100644
index 779402c07..000000000
--- a/src/structify/types/document_upload_params.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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
-
-from .._types import FileTypes
-
-__all__ = ["DocumentUploadParams"]
-
-
-class DocumentUploadParams(TypedDict, total=False):
- content: Required[FileTypes]
-
- file_type: Required[Literal["Text", "PDF", "SEC"]]
-
- path: Required[FileTypes]
-
- dataset: Optional[str]
-
- project_id: Optional[str]
diff --git a/src/structify/types/session_upload_node_output_data_params.py b/src/structify/types/session_upload_node_output_data_params.py
deleted file mode 100644
index dcc0b284c..000000000
--- a/src/structify/types/session_upload_node_output_data_params.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# 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 Required, TypedDict
-
-from .._types import FileTypes
-
-__all__ = ["SessionUploadNodeOutputDataParams"]
-
-
-class SessionUploadNodeOutputDataParams(TypedDict, total=False):
- content: Required[FileTypes]
-
- cache_final_rows: Optional[int]
-
- cache_final_size_bytes: Optional[int]
-
- cache_max_bytes: Optional[int]
-
- cache_original_rows: Optional[int]
-
- cache_original_size_bytes: Optional[int]
-
- cache_truncated: Optional[bool]
-
- output_schema: Optional[str]
diff --git a/src/structify/types/workflow_session_node.py b/src/structify/types/workflow_session_node.py
index 0f93d2b48..c3afbe1e2 100644
--- a/src/structify/types/workflow_session_node.py
+++ b/src/structify/types/workflow_session_node.py
@@ -66,6 +66,8 @@ class WorkflowSessionNode(BaseModel):
output_blob_name: Optional[str] = None
+ output_file_size: Optional[int] = None
+
output_schema: Optional[object] = None
progress: Optional[object] = None
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index c2800d934..1d4dc0ef9 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -36,7 +36,6 @@
ChatRevertToCommitResponse,
ChatDeleteInputFileResponse,
ChatGetPartialChatsResponse,
- ChatUploadInputFileResponse,
ChatGetSessionTimelineResponse,
ChatCopyNodeOutputByCodeHashResponse,
)
@@ -1565,56 +1564,6 @@ def test_path_params_update_visibility(self, client: Structify) -> None:
visibility="private",
)
- @parametrize
- def test_method_upload_input_file(self, client: Structify) -> None:
- chat = client.chat.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- )
- assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
-
- @parametrize
- def test_raw_response_upload_input_file(self, client: Structify) -> None:
- response = client.chat.with_raw_response.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = response.parse()
- assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
-
- @parametrize
- def test_streaming_response_upload_input_file(self, client: Structify) -> None:
- with client.chat.with_streaming_response.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = response.parse()
- assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_upload_input_file(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
- client.chat.with_raw_response.upload_input_file(
- chat_id="",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- )
-
class TestAsyncChat:
parametrize = pytest.mark.parametrize(
@@ -3133,53 +3082,3 @@ async def test_path_params_update_visibility(self, async_client: AsyncStructify)
session_id="",
visibility="private",
)
-
- @parametrize
- async def test_method_upload_input_file(self, async_client: AsyncStructify) -> None:
- chat = await async_client.chat.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- )
- assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
-
- @parametrize
- async def test_raw_response_upload_input_file(self, async_client: AsyncStructify) -> None:
- response = await async_client.chat.with_raw_response.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- chat = await response.parse()
- assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
-
- @parametrize
- async def test_streaming_response_upload_input_file(self, async_client: AsyncStructify) -> None:
- async with async_client.chat.with_streaming_response.upload_input_file(
- chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- chat = await response.parse()
- assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_upload_input_file(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
- await async_client.chat.with_raw_response.upload_input_file(
- chat_id="",
- content=b"Example data",
- content_type="content_type",
- file_name="file_name",
- )
diff --git a/tests/api_resources/test_documents.py b/tests/api_resources/test_documents.py
index 6562d8463..24a3b2129 100644
--- a/tests/api_resources/test_documents.py
+++ b/tests/api_resources/test_documents.py
@@ -115,54 +115,6 @@ def test_streaming_response_download(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
- @parametrize
- def test_method_upload(self, client: Structify) -> None:
- document = client.documents.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- )
- assert document is None
-
- @parametrize
- def test_method_upload_with_all_params(self, client: Structify) -> None:
- document = client.documents.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- dataset="dataset",
- project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert document is None
-
- @parametrize
- def test_raw_response_upload(self, client: Structify) -> None:
- response = client.documents.with_raw_response.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- document = response.parse()
- assert document is None
-
- @parametrize
- def test_streaming_response_upload(self, client: Structify) -> None:
- with client.documents.with_streaming_response.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- document = response.parse()
- assert document is None
-
- assert cast(Any, response.is_closed) is True
-
class TestAsyncDocuments:
parametrize = pytest.mark.parametrize(
@@ -263,51 +215,3 @@ async def test_streaming_response_download(self, async_client: AsyncStructify) -
assert_matches_type(DocumentDownloadResponse, document, path=["response"])
assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_method_upload(self, async_client: AsyncStructify) -> None:
- document = await async_client.documents.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- )
- assert document is None
-
- @parametrize
- async def test_method_upload_with_all_params(self, async_client: AsyncStructify) -> None:
- document = await async_client.documents.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- dataset="dataset",
- project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert document is None
-
- @parametrize
- async def test_raw_response_upload(self, async_client: AsyncStructify) -> None:
- response = await async_client.documents.with_raw_response.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- document = await response.parse()
- assert document is None
-
- @parametrize
- async def test_streaming_response_upload(self, async_client: AsyncStructify) -> None:
- async with async_client.documents.with_streaming_response.upload(
- content=b"Example data",
- file_type="Text",
- path=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- document = await response.parse()
- assert document is None
-
- assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index f960c82df..51d12e5bc 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -1190,63 +1190,6 @@ def test_path_params_upload_dashboard_layout_overload_2(self, client: Structify)
],
)
- @parametrize
- def test_method_upload_node_output_data(self, client: Structify) -> None:
- session = client.sessions.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- )
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- @parametrize
- def test_method_upload_node_output_data_with_all_params(self, client: Structify) -> None:
- session = client.sessions.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- cache_final_rows=0,
- cache_final_size_bytes=0,
- cache_max_bytes=0,
- cache_original_rows=0,
- cache_original_size_bytes=0,
- cache_truncated=True,
- output_schema="output_schema",
- )
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- @parametrize
- def test_raw_response_upload_node_output_data(self, client: Structify) -> None:
- response = client.sessions.with_raw_response.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- session = response.parse()
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- @parametrize
- def test_streaming_response_upload_node_output_data(self, client: Structify) -> None:
- with client.sessions.with_streaming_response.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- session = response.parse()
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_upload_node_output_data(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `node_id` but received ''"):
- client.sessions.with_raw_response.upload_node_output_data(
- node_id="",
- content=b"Example data",
- )
-
@parametrize
def test_method_upload_node_visualization_output(self, client: Structify) -> None:
session = client.sessions.upload_node_visualization_output(
@@ -2454,63 +2397,6 @@ async def test_path_params_upload_dashboard_layout_overload_2(self, async_client
],
)
- @parametrize
- async def test_method_upload_node_output_data(self, async_client: AsyncStructify) -> None:
- session = await async_client.sessions.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- )
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- @parametrize
- async def test_method_upload_node_output_data_with_all_params(self, async_client: AsyncStructify) -> None:
- session = await async_client.sessions.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- cache_final_rows=0,
- cache_final_size_bytes=0,
- cache_max_bytes=0,
- cache_original_rows=0,
- cache_original_size_bytes=0,
- cache_truncated=True,
- output_schema="output_schema",
- )
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- @parametrize
- async def test_raw_response_upload_node_output_data(self, async_client: AsyncStructify) -> None:
- response = await async_client.sessions.with_raw_response.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- session = await response.parse()
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- @parametrize
- async def test_streaming_response_upload_node_output_data(self, async_client: AsyncStructify) -> None:
- async with async_client.sessions.with_streaming_response.upload_node_output_data(
- node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- content=b"Example data",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- session = await response.parse()
- assert_matches_type(WorkflowSessionNode, session, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_upload_node_output_data(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `node_id` but received ''"):
- await async_client.sessions.with_raw_response.upload_node_output_data(
- node_id="",
- content=b"Example data",
- )
-
@parametrize
async def test_method_upload_node_visualization_output(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.upload_node_visualization_output(
From ca4fa72263d7eb09ba0aa91e2d0e32b1d724bbc1 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 01:37:13 +0000
Subject: [PATCH 086/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 5 +
src/structify/resources/admin/connector.py | 109 +++++++++++++++++-
.../resources/connectors/connectors.py | 15 +++
src/structify/types/admin/__init__.py | 5 +
.../connector_set_datahub_config_params.py | 23 ++++
.../types/admin/datahub_ingestion_key.py | 18 +++
.../types/admin/datahub_ingestion_type.py | 7 ++
.../types/admin/datahub_secret_map.py | 8 ++
.../types/admin/datahub_secret_map_param.py | 10 ++
src/structify/types/connector.py | 9 ++
.../types/connector_update_params.py | 9 ++
tests/api_resources/admin/test_connector.py | 85 +++++++++++++-
tests/api_resources/test_connectors.py | 4 +
14 files changed, 307 insertions(+), 8 deletions(-)
create mode 100644 src/structify/types/admin/connector_set_datahub_config_params.py
create mode 100644 src/structify/types/admin/datahub_ingestion_key.py
create mode 100644 src/structify/types/admin/datahub_ingestion_type.py
create mode 100644 src/structify/types/admin/datahub_secret_map.py
create mode 100644 src/structify/types/admin/datahub_secret_map_param.py
diff --git a/.stats.yml b/.stats.yml
index c38ce07d9..c8418851a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 246
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-8acf14fe5e003f7ba6a5297b607616f6b42ab5b9b6eb40dafaab336260d29f77.yml
-openapi_spec_hash: 5e7378a0d31076f6bbe2cb8d65f177d6
-config_hash: 63c3aa248700e46cfe93b79afa9f0065
+configured_endpoints: 247
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-e5efa58269adb246902abb6c9147b773feaa43106fdc3f8b3b9079a3f0d8bcaa.yml
+openapi_spec_hash: 6eaf8ce2fc511174280beaed259bb2bd
+config_hash: 98bcfffe700cc36ce7df38c8236cc621
diff --git a/api.md b/api.md
index 6183db669..3985dd8ad 100644
--- a/api.md
+++ b/api.md
@@ -436,12 +436,17 @@ from structify.types.admin import (
CloneConnectorItem,
CloneConnectorsRequest,
CloneConnectorsResponse,
+ DatahubIngestionKey,
+ DatahubIngestionType,
+ DatahubSecretMap,
+ SetDatahubConfigRequest,
)
```
Methods:
- client.admin.connector.clone(\*\*params) -> CloneConnectorsResponse
+- client.admin.connector.set_datahub_config(\*\*params) -> Connector
# Datasets
diff --git a/src/structify/resources/admin/connector.py b/src/structify/resources/admin/connector.py
index ab8d89fd8..7d57c20b7 100644
--- a/src/structify/resources/admin/connector.py
+++ b/src/structify/resources/admin/connector.py
@@ -2,11 +2,11 @@
from __future__ import annotations
-from typing import Iterable
+from typing import Iterable, Optional
import httpx
-from ..._types import Body, Query, Headers, NotGiven, not_given
+from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
from ..._utils import maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
@@ -16,8 +16,15 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ...types.admin import connector_clone_params
+from ...types.admin import (
+ DatahubIngestionType,
+ connector_clone_params,
+ connector_set_datahub_config_params,
+)
from ..._base_client import make_request_options
+from ...types.connector import Connector
+from ...types.admin.datahub_ingestion_type import DatahubIngestionType
+from ...types.admin.datahub_secret_map_param import DatahubSecretMapParam
from ...types.admin.clone_connectors_response import CloneConnectorsResponse
from ...types.admin.clone_connector_item_param import CloneConnectorItemParam
@@ -87,6 +94,48 @@ def clone(
cast_to=CloneConnectorsResponse,
)
+ def set_datahub_config(
+ self,
+ *,
+ connector_id: str,
+ datahub_ingestion_type: Optional[DatahubIngestionType] | Omit = omit,
+ datahub_secret_map: Optional[DatahubSecretMapParam] | 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,
+ ) -> Connector:
+ """
+ Args:
+ datahub_secret_map: Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+
+ 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
+ """
+ return self._post(
+ "/admin/connector/datahub-config",
+ body=maybe_transform(
+ {
+ "connector_id": connector_id,
+ "datahub_ingestion_type": datahub_ingestion_type,
+ "datahub_secret_map": datahub_secret_map,
+ },
+ connector_set_datahub_config_params.ConnectorSetDatahubConfigParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Connector,
+ )
+
class AsyncConnectorResource(AsyncAPIResource):
"""Admin endpoints"""
@@ -151,6 +200,48 @@ async def clone(
cast_to=CloneConnectorsResponse,
)
+ async def set_datahub_config(
+ self,
+ *,
+ connector_id: str,
+ datahub_ingestion_type: Optional[DatahubIngestionType] | Omit = omit,
+ datahub_secret_map: Optional[DatahubSecretMapParam] | 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,
+ ) -> Connector:
+ """
+ Args:
+ datahub_secret_map: Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+
+ 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
+ """
+ return await self._post(
+ "/admin/connector/datahub-config",
+ body=await async_maybe_transform(
+ {
+ "connector_id": connector_id,
+ "datahub_ingestion_type": datahub_ingestion_type,
+ "datahub_secret_map": datahub_secret_map,
+ },
+ connector_set_datahub_config_params.ConnectorSetDatahubConfigParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=Connector,
+ )
+
class ConnectorResourceWithRawResponse:
def __init__(self, connector: ConnectorResource) -> None:
@@ -159,6 +250,9 @@ def __init__(self, connector: ConnectorResource) -> None:
self.clone = to_raw_response_wrapper(
connector.clone,
)
+ self.set_datahub_config = to_raw_response_wrapper(
+ connector.set_datahub_config,
+ )
class AsyncConnectorResourceWithRawResponse:
@@ -168,6 +262,9 @@ def __init__(self, connector: AsyncConnectorResource) -> None:
self.clone = async_to_raw_response_wrapper(
connector.clone,
)
+ self.set_datahub_config = async_to_raw_response_wrapper(
+ connector.set_datahub_config,
+ )
class ConnectorResourceWithStreamingResponse:
@@ -177,6 +274,9 @@ def __init__(self, connector: ConnectorResource) -> None:
self.clone = to_streamed_response_wrapper(
connector.clone,
)
+ self.set_datahub_config = to_streamed_response_wrapper(
+ connector.set_datahub_config,
+ )
class AsyncConnectorResourceWithStreamingResponse:
@@ -186,3 +286,6 @@ def __init__(self, connector: AsyncConnectorResource) -> None:
self.clone = async_to_streamed_response_wrapper(
connector.clone,
)
+ self.set_datahub_config = async_to_streamed_response_wrapper(
+ connector.set_datahub_config,
+ )
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index fe84b0d2c..f456a28ab 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -83,6 +83,7 @@
from ...types.connector_summaries_response import ConnectorSummariesResponse
from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
+from ...types.admin.datahub_secret_map_param import DatahubSecretMapParam
from ...types.connector_list_stores_response import ConnectorListStoresResponse
from ...types.connector_search_tables_response import ConnectorSearchTablesResponse
from ...types.connector_add_schema_object_response import ConnectorAddSchemaObjectResponse
@@ -168,6 +169,8 @@ def update(
connector_id: str,
*,
connector_category: Optional[ConnectorCategory] | Omit = omit,
+ datahub_ingestion_type: Optional[str] | Omit = omit,
+ datahub_secret_map: Optional[DatahubSecretMapParam] | Omit = omit,
datahub_urn: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
known_connector_type: Optional[str] | Omit = omit,
@@ -187,6 +190,9 @@ def update(
) -> None:
"""
Args:
+ datahub_secret_map: Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -203,6 +209,8 @@ def update(
body=maybe_transform(
{
"connector_category": connector_category,
+ "datahub_ingestion_type": datahub_ingestion_type,
+ "datahub_secret_map": datahub_secret_map,
"datahub_urn": datahub_urn,
"description": description,
"known_connector_type": known_connector_type,
@@ -1400,6 +1408,8 @@ async def update(
connector_id: str,
*,
connector_category: Optional[ConnectorCategory] | Omit = omit,
+ datahub_ingestion_type: Optional[str] | Omit = omit,
+ datahub_secret_map: Optional[DatahubSecretMapParam] | Omit = omit,
datahub_urn: Optional[str] | Omit = omit,
description: Optional[str] | Omit = omit,
known_connector_type: Optional[str] | Omit = omit,
@@ -1419,6 +1429,9 @@ async def update(
) -> None:
"""
Args:
+ datahub_secret_map: Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+
extra_headers: Send extra headers
extra_query: Add additional query parameters to the request
@@ -1435,6 +1448,8 @@ async def update(
body=await async_maybe_transform(
{
"connector_category": connector_category,
+ "datahub_ingestion_type": datahub_ingestion_type,
+ "datahub_secret_map": datahub_secret_map,
"datahub_urn": datahub_urn,
"description": description,
"known_connector_type": known_connector_type,
diff --git a/src/structify/types/admin/__init__.py b/src/structify/types/admin/__init__.py
index 9c79effd6..d75a1972b 100644
--- a/src/structify/types/admin/__init__.py
+++ b/src/structify/types/admin/__init__.py
@@ -8,21 +8,25 @@
from .team_list_params import TeamListParams as TeamListParams
from .job_delete_params import JobDeleteParams as JobDeleteParams
from .job_list_response import JobListResponse as JobListResponse
+from .datahub_secret_map import DatahubSecretMap as DatahubSecretMap
from .team_list_response import TeamListResponse as TeamListResponse
from .user_create_params import UserCreateParams as UserCreateParams
from .user_list_response import UserListResponse as UserListResponse
from .sandbox_list_params import SandboxListParams as SandboxListParams
from .admin_dataset_return import AdminDatasetReturn as AdminDatasetReturn
from .impersonate_response import ImpersonateResponse as ImpersonateResponse
+from .datahub_ingestion_key import DatahubIngestionKey as DatahubIngestionKey
from .extend_trial_response import ExtendTrialResponse as ExtendTrialResponse
from .user_get_stats_params import UserGetStatsParams as UserGetStatsParams
from .connector_clone_params import ConnectorCloneParams as ConnectorCloneParams
+from .datahub_ingestion_type import DatahubIngestionType as DatahubIngestionType
from .expire_grants_response import ExpireGrantsResponse as ExpireGrantsResponse
from .grant_credits_response import GrantCreditsResponse as GrantCreditsResponse
from .team_add_member_params import TeamAddMemberParams as TeamAddMemberParams
from .job_kill_by_user_params import JobKillByUserParams as JobKillByUserParams
from .user_get_stats_response import UserGetStatsResponse as UserGetStatsResponse
from .user_impersonate_params import UserImpersonateParams as UserImpersonateParams
+from .datahub_secret_map_param import DatahubSecretMapParam as DatahubSecretMapParam
from .dataset_get_by_id_params import DatasetGetByIDParams as DatasetGetByIDParams
from .team_extend_trial_params import TeamExtendTrialParams as TeamExtendTrialParams
from .admin_add_member_response import AdminAddMemberResponse as AdminAddMemberResponse
@@ -51,6 +55,7 @@
from .functional_test_results_response import FunctionalTestResultsResponse as FunctionalTestResultsResponse
from .team_update_seats_override_params import TeamUpdateSeatsOverrideParams as TeamUpdateSeatsOverrideParams
from .functional_test_get_results_params import FunctionalTestGetResultsParams as FunctionalTestGetResultsParams
+from .connector_set_datahub_config_params import ConnectorSetDatahubConfigParams as ConnectorSetDatahubConfigParams
from .functional_test_update_results_params import (
FunctionalTestUpdateResultsParams as FunctionalTestUpdateResultsParams,
)
diff --git a/src/structify/types/admin/connector_set_datahub_config_params.py b/src/structify/types/admin/connector_set_datahub_config_params.py
new file mode 100644
index 000000000..c346ae395
--- /dev/null
+++ b/src/structify/types/admin/connector_set_datahub_config_params.py
@@ -0,0 +1,23 @@
+# 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 Required, TypedDict
+
+from .datahub_ingestion_type import DatahubIngestionType
+from .datahub_secret_map_param import DatahubSecretMapParam
+
+__all__ = ["ConnectorSetDatahubConfigParams"]
+
+
+class ConnectorSetDatahubConfigParams(TypedDict, total=False):
+ connector_id: Required[str]
+
+ datahub_ingestion_type: Optional[DatahubIngestionType]
+
+ datahub_secret_map: Optional[DatahubSecretMapParam]
+ """
+ Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+ """
diff --git a/src/structify/types/admin/datahub_ingestion_key.py b/src/structify/types/admin/datahub_ingestion_key.py
new file mode 100644
index 000000000..8981cd7ac
--- /dev/null
+++ b/src/structify/types/admin/datahub_ingestion_key.py
@@ -0,0 +1,18 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["DatahubIngestionKey"]
+
+DatahubIngestionKey: TypeAlias = Literal[
+ "host",
+ "port",
+ "database",
+ "username",
+ "password",
+ "account_id",
+ "warehouse",
+ "role",
+ "instance_url",
+ "access_token",
+]
diff --git a/src/structify/types/admin/datahub_ingestion_type.py b/src/structify/types/admin/datahub_ingestion_type.py
new file mode 100644
index 000000000..e5b679a16
--- /dev/null
+++ b/src/structify/types/admin/datahub_ingestion_type.py
@@ -0,0 +1,7 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["DatahubIngestionType"]
+
+DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot"]
diff --git a/src/structify/types/admin/datahub_secret_map.py b/src/structify/types/admin/datahub_secret_map.py
new file mode 100644
index 000000000..bf80a823b
--- /dev/null
+++ b/src/structify/types/admin/datahub_secret_map.py
@@ -0,0 +1,8 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Dict
+from typing_extensions import TypeAlias
+
+__all__ = ["DatahubSecretMap"]
+
+DatahubSecretMap: TypeAlias = Dict[str, str]
diff --git a/src/structify/types/admin/datahub_secret_map_param.py b/src/structify/types/admin/datahub_secret_map_param.py
new file mode 100644
index 000000000..6cd1d2874
--- /dev/null
+++ b/src/structify/types/admin/datahub_secret_map_param.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing import Dict
+from typing_extensions import TypeAlias
+
+__all__ = ["DatahubSecretMapParam"]
+
+DatahubSecretMapParam: TypeAlias = Dict[str, str]
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 4a006c785..32c1bae30 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -6,6 +6,7 @@
from .._models import BaseModel
from .connector_category import ConnectorCategory
+from .admin.datahub_secret_map import DatahubSecretMap
__all__ = ["Connector"]
@@ -29,6 +30,14 @@ class Connector(BaseModel):
connector_category: Optional[ConnectorCategory] = None
+ datahub_ingestion_type: Optional[str] = None
+
+ datahub_secret_map: Optional[DatahubSecretMap] = None
+ """
+ Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+ """
+
datahub_urn: Optional[str] = None
deleted_at: Optional[datetime] = None
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index d9de647ea..f9d31b52c 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -7,6 +7,7 @@
from .._types import SequenceNotStr
from .connector_category import ConnectorCategory
+from .admin.datahub_secret_map_param import DatahubSecretMapParam
__all__ = ["ConnectorUpdateParams"]
@@ -14,6 +15,14 @@
class ConnectorUpdateParams(TypedDict, total=False):
connector_category: Optional[ConnectorCategory]
+ datahub_ingestion_type: Optional[str]
+
+ datahub_secret_map: Optional[DatahubSecretMapParam]
+ """
+ Maps DatahubIngestionKey to the name of the connector secret that holds the
+ value.
+ """
+
datahub_urn: Optional[str]
description: Optional[str]
diff --git a/tests/api_resources/admin/test_connector.py b/tests/api_resources/admin/test_connector.py
index 7eee1bfba..b55aacde2 100644
--- a/tests/api_resources/admin/test_connector.py
+++ b/tests/api_resources/admin/test_connector.py
@@ -9,7 +9,10 @@
from structify import Structify, AsyncStructify
from tests.utils import assert_matches_type
-from structify.types.admin import CloneConnectorsResponse
+from structify.types import Connector
+from structify.types.admin import (
+ CloneConnectorsResponse,
+)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -75,6 +78,46 @@ def test_streaming_response_clone(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_set_datahub_config(self, client: Structify) -> None:
+ connector = client.admin.connector.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(Connector, connector, path=["response"])
+
+ @parametrize
+ def test_method_set_datahub_config_with_all_params(self, client: Structify) -> None:
+ connector = client.admin.connector.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ datahub_ingestion_type="postgres",
+ datahub_secret_map={"foo": "string"},
+ )
+ assert_matches_type(Connector, connector, path=["response"])
+
+ @parametrize
+ def test_raw_response_set_datahub_config(self, client: Structify) -> None:
+ response = client.admin.connector.with_raw_response.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert_matches_type(Connector, connector, path=["response"])
+
+ @parametrize
+ def test_streaming_response_set_datahub_config(self, client: Structify) -> None:
+ with client.admin.connector.with_streaming_response.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert_matches_type(Connector, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncConnector:
parametrize = pytest.mark.parametrize(
@@ -138,3 +181,43 @@ async def test_streaming_response_clone(self, async_client: AsyncStructify) -> N
assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_set_datahub_config(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.admin.connector.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(Connector, connector, path=["response"])
+
+ @parametrize
+ async def test_method_set_datahub_config_with_all_params(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.admin.connector.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ datahub_ingestion_type="postgres",
+ datahub_secret_map={"foo": "string"},
+ )
+ assert_matches_type(Connector, connector, path=["response"])
+
+ @parametrize
+ async def test_raw_response_set_datahub_config(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.connector.with_raw_response.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert_matches_type(Connector, connector, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_set_datahub_config(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.connector.with_streaming_response.set_datahub_config(
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert_matches_type(Connector, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index d8f4aab12..de2341a53 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -101,6 +101,8 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
connector = client.connectors.update(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
connector_category="RelationalDatabase",
+ datahub_ingestion_type="datahub_ingestion_type",
+ datahub_secret_map={"foo": "string"},
datahub_urn="datahub_urn",
description="description",
known_connector_type="known_connector_type",
@@ -1555,6 +1557,8 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
connector = await async_client.connectors.update(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
connector_category="RelationalDatabase",
+ datahub_ingestion_type="datahub_ingestion_type",
+ datahub_secret_map={"foo": "string"},
datahub_urn="datahub_urn",
description="description",
known_connector_type="known_connector_type",
From bde5a390b285b282578bb6b4857285b2abd23491 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 03:54:23 +0000
Subject: [PATCH 087/105] feat: Update from Structify backend changes
---
.stats.yml | 6 +-
README.md | 10 +-
api.md | 4 +
src/structify/resources/chat.py | 120 ++++++++++++++-
src/structify/resources/documents.py | 141 ++++++++++++++++-
src/structify/resources/sessions.py | 144 +++++++++++++++++-
src/structify/types/__init__.py | 6 +
.../types/admin/datahub_ingestion_key.py | 2 +
.../types/admin/datahub_ingestion_type.py | 2 +-
.../types/chat_upload_input_file_params.py | 17 +++
.../types/chat_upload_input_file_response.py | 23 +++
src/structify/types/document_list_response.py | 2 -
src/structify/types/document_upload_params.py | 22 +++
.../session_upload_node_output_data_params.py | 28 ++++
src/structify/types/workflow_session_node.py | 2 -
tests/api_resources/test_chat.py | 101 ++++++++++++
tests/api_resources/test_documents.py | 96 ++++++++++++
tests/api_resources/test_sessions.py | 114 ++++++++++++++
18 files changed, 817 insertions(+), 23 deletions(-)
create mode 100644 src/structify/types/chat_upload_input_file_params.py
create mode 100644 src/structify/types/chat_upload_input_file_response.py
create mode 100644 src/structify/types/document_upload_params.py
create mode 100644 src/structify/types/session_upload_node_output_data_params.py
diff --git a/.stats.yml b/.stats.yml
index c8418851a..8cf4e64df 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 247
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-e5efa58269adb246902abb6c9147b773feaa43106fdc3f8b3b9079a3f0d8bcaa.yml
-openapi_spec_hash: 6eaf8ce2fc511174280beaed259bb2bd
+configured_endpoints: 250
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c2c5af9cf676f34cbe61bda68172ce626e9168c76ecdf6470ed3de47cf414c8f.yml
+openapi_spec_hash: 0f2773018f65c15bb2f0e1846a18d1ab
config_hash: 98bcfffe700cc36ce7df38c8236cc621
diff --git a/README.md b/README.md
index debe126cf..2a8ad2bb6 100644
--- a/README.md
+++ b/README.md
@@ -195,11 +195,11 @@ from structify import Structify
client = Structify()
-client.connectors.upload_datahub_artifact(
- kind="kind",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- exploration_run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- file=Path("/path/to/file"),
+client.chat.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=Path("/path/to/file"),
+ content_type="content_type",
+ file_name="file_name",
)
```
diff --git a/api.md b/api.md
index 3985dd8ad..724bdd378 100644
--- a/api.md
+++ b/api.md
@@ -134,6 +134,7 @@ from structify.types import (
ChatLoadFilesResponse,
ChatLoadInputFilesResponse,
ChatRevertToCommitResponse,
+ ChatUploadInputFileResponse,
)
```
@@ -170,6 +171,7 @@ Methods:
- client.chat.update_session(session_id, \*\*params) -> ChatSession
- client.chat.update_session_favorite(session_id, \*\*params) -> ChatSession
- client.chat.update_visibility(session_id, \*\*params) -> UpdateVisibilityResponse
+- client.chat.upload_input_file(chat_id, \*\*params) -> ChatUploadInputFileResponse
# Teams
@@ -524,6 +526,7 @@ Methods:
- client.documents.list(\*\*params) -> DocumentListResponse
- client.documents.delete(\*\*params) -> None
- client.documents.download(\*\*params) -> DocumentDownloadResponse
+- client.documents.upload(\*\*params) -> None
# Jobs
@@ -643,6 +646,7 @@ Methods:
- client.sessions.update_node(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.update_node_progress(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.upload_dashboard_layout(session_id, \*\*params) -> WorkflowSession
+- client.sessions.upload_node_output_data(node_id, \*\*params) -> WorkflowSessionNode
- client.sessions.upload_node_visualization_output(node_id, \*\*params) -> WorkflowSessionNode
# WorkflowSchedule
diff --git a/src/structify/resources/chat.py b/src/structify/resources/chat.py
index 2ced61cbf..1d29f7dbb 100644
--- a/src/structify/resources/chat.py
+++ b/src/structify/resources/chat.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Union, Optional
+from typing import Union, Mapping, Optional, cast
from datetime import datetime
from typing_extensions import Literal
@@ -25,12 +25,13 @@
chat_admin_issue_found_params,
chat_delete_input_file_params,
chat_update_visibility_params,
+ chat_upload_input_file_params,
chat_grant_admin_override_params,
chat_update_session_favorite_params,
chat_copy_node_output_by_code_hash_params,
)
-from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
-from .._utils import path_template, maybe_transform, async_maybe_transform
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, SequenceNotStr, omit, not_given
+from .._utils import extract_files, path_template, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -75,6 +76,7 @@
from ..types.chat_revert_to_commit_response import ChatRevertToCommitResponse
from ..types.chat_delete_input_file_response import ChatDeleteInputFileResponse
from ..types.chat_get_partial_chats_response import ChatGetPartialChatsResponse
+from ..types.chat_upload_input_file_response import ChatUploadInputFileResponse
from ..types.chat_get_session_timeline_response import ChatGetSessionTimelineResponse
from ..types.chat_copy_node_output_by_code_hash_response import ChatCopyNodeOutputByCodeHashResponse
@@ -1260,6 +1262,56 @@ def update_visibility(
cast_to=UpdateVisibilityResponse,
)
+ def upload_input_file(
+ self,
+ chat_id: str,
+ *,
+ content: FileTypes,
+ content_type: str,
+ file_name: str,
+ # 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,
+ ) -> ChatUploadInputFileResponse:
+ """
+ Upload an input file to a chat session's bucket storage
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "content_type": content_type,
+ "file_name": file_name,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ path_template("/chat/input-files/upload/{chat_id}", chat_id=chat_id),
+ body=maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatUploadInputFileResponse,
+ )
+
class AsyncChatResource(AsyncAPIResource):
@cached_property
@@ -2452,6 +2504,56 @@ async def update_visibility(
cast_to=UpdateVisibilityResponse,
)
+ async def upload_input_file(
+ self,
+ chat_id: str,
+ *,
+ content: FileTypes,
+ content_type: str,
+ file_name: str,
+ # 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,
+ ) -> ChatUploadInputFileResponse:
+ """
+ Upload an input file to a chat session's bucket storage
+
+ Args:
+ 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
+ """
+ if not chat_id:
+ raise ValueError(f"Expected a non-empty value for `chat_id` but received {chat_id!r}")
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "content_type": content_type,
+ "file_name": file_name,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ path_template("/chat/input-files/upload/{chat_id}", chat_id=chat_id),
+ body=await async_maybe_transform(body, chat_upload_input_file_params.ChatUploadInputFileParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ChatUploadInputFileResponse,
+ )
+
class ChatResourceWithRawResponse:
def __init__(self, chat: ChatResource) -> None:
@@ -2551,6 +2653,9 @@ def __init__(self, chat: ChatResource) -> None:
self.update_visibility = to_raw_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = to_raw_response_wrapper(
+ chat.upload_input_file,
+ )
class AsyncChatResourceWithRawResponse:
@@ -2651,6 +2756,9 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.update_visibility = async_to_raw_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = async_to_raw_response_wrapper(
+ chat.upload_input_file,
+ )
class ChatResourceWithStreamingResponse:
@@ -2751,6 +2859,9 @@ def __init__(self, chat: ChatResource) -> None:
self.update_visibility = to_streamed_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = to_streamed_response_wrapper(
+ chat.upload_input_file,
+ )
class AsyncChatResourceWithStreamingResponse:
@@ -2851,3 +2962,6 @@ def __init__(self, chat: AsyncChatResource) -> None:
self.update_visibility = async_to_streamed_response_wrapper(
chat.update_visibility,
)
+ self.upload_input_file = async_to_streamed_response_wrapper(
+ chat.upload_input_file,
+ )
diff --git a/src/structify/resources/documents.py b/src/structify/resources/documents.py
index 5076a058e..100fa7cf8 100644
--- a/src/structify/resources/documents.py
+++ b/src/structify/resources/documents.py
@@ -2,13 +2,14 @@
from __future__ import annotations
-from typing import Optional
+from typing import Mapping, Optional, cast
+from typing_extensions import Literal
import httpx
-from ..types import document_list_params, document_delete_params, document_download_params
-from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
-from .._utils import maybe_transform, async_maybe_transform
+from ..types import document_list_params, document_delete_params, document_upload_params, document_download_params
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, FileTypes, omit, not_given
+from .._utils import extract_files, maybe_transform, deepcopy_minimal, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -155,6 +156,66 @@ def download(
cast_to=DocumentDownloadResponse,
)
+ def upload(
+ self,
+ *,
+ content: FileTypes,
+ file_type: Literal["Text", "PDF", "SEC"],
+ path: FileTypes,
+ dataset: Optional[str] | Omit = omit,
+ project_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.
+ # 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:
+ """
+ Add a new file to the database
+
+ Args:
+ 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 {})}
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "file_type": file_type,
+ "path": path,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"], ["path"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return self._post(
+ "/documents/upload",
+ body=maybe_transform(body, document_upload_params.DocumentUploadParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=maybe_transform(
+ {
+ "dataset": dataset,
+ "project_id": project_id,
+ },
+ document_upload_params.DocumentUploadParams,
+ ),
+ ),
+ cast_to=NoneType,
+ )
+
class AsyncDocumentsResource(AsyncAPIResource):
@cached_property
@@ -287,6 +348,66 @@ async def download(
cast_to=DocumentDownloadResponse,
)
+ async def upload(
+ self,
+ *,
+ content: FileTypes,
+ file_type: Literal["Text", "PDF", "SEC"],
+ path: FileTypes,
+ dataset: Optional[str] | Omit = omit,
+ project_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.
+ # 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:
+ """
+ Add a new file to the database
+
+ Args:
+ 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 {})}
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "file_type": file_type,
+ "path": path,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"], ["path"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers["Content-Type"] = "multipart/form-data"
+ return await self._post(
+ "/documents/upload",
+ body=await async_maybe_transform(body, document_upload_params.DocumentUploadParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers,
+ extra_query=extra_query,
+ extra_body=extra_body,
+ timeout=timeout,
+ query=await async_maybe_transform(
+ {
+ "dataset": dataset,
+ "project_id": project_id,
+ },
+ document_upload_params.DocumentUploadParams,
+ ),
+ ),
+ cast_to=NoneType,
+ )
+
class DocumentsResourceWithRawResponse:
def __init__(self, documents: DocumentsResource) -> None:
@@ -301,6 +422,9 @@ def __init__(self, documents: DocumentsResource) -> None:
self.download = to_raw_response_wrapper(
documents.download,
)
+ self.upload = to_raw_response_wrapper(
+ documents.upload,
+ )
class AsyncDocumentsResourceWithRawResponse:
@@ -316,6 +440,9 @@ def __init__(self, documents: AsyncDocumentsResource) -> None:
self.download = async_to_raw_response_wrapper(
documents.download,
)
+ self.upload = async_to_raw_response_wrapper(
+ documents.upload,
+ )
class DocumentsResourceWithStreamingResponse:
@@ -331,6 +458,9 @@ def __init__(self, documents: DocumentsResource) -> None:
self.download = to_streamed_response_wrapper(
documents.download,
)
+ self.upload = to_streamed_response_wrapper(
+ documents.upload,
+ )
class AsyncDocumentsResourceWithStreamingResponse:
@@ -346,3 +476,6 @@ def __init__(self, documents: AsyncDocumentsResource) -> None:
self.download = async_to_streamed_response_wrapper(
documents.download,
)
+ self.upload = async_to_streamed_response_wrapper(
+ documents.upload,
+ )
diff --git a/src/structify/resources/sessions.py b/src/structify/resources/sessions.py
index 2f9b16793..08f675436 100644
--- a/src/structify/resources/sessions.py
+++ b/src/structify/resources/sessions.py
@@ -2,7 +2,7 @@
from __future__ import annotations
-from typing import Dict, Iterable, Optional
+from typing import Dict, Mapping, Iterable, Optional, cast
from typing_extensions import Literal, overload
import httpx
@@ -21,10 +21,18 @@
session_request_confirmation_params,
session_update_node_progress_params,
session_upload_dashboard_layout_params,
+ session_upload_node_output_data_params,
session_upload_node_visualization_output_params,
)
-from .._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from .._utils import path_template, required_args, maybe_transform, async_maybe_transform
+from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given
+from .._utils import (
+ extract_files,
+ path_template,
+ required_args,
+ maybe_transform,
+ deepcopy_minimal,
+ async_maybe_transform,
+)
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
from .._response import (
@@ -763,6 +771,64 @@ def upload_dashboard_layout(
cast_to=WorkflowSession,
)
+ def upload_node_output_data(
+ self,
+ node_id: str,
+ *,
+ content: FileTypes,
+ cache_final_rows: Optional[int] | Omit = omit,
+ cache_final_size_bytes: Optional[int] | Omit = omit,
+ cache_max_bytes: Optional[int] | Omit = omit,
+ cache_original_rows: Optional[int] | Omit = omit,
+ cache_original_size_bytes: Optional[int] | Omit = omit,
+ cache_truncated: Optional[bool] | Omit = omit,
+ output_schema: 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,
+ ) -> WorkflowSessionNode:
+ """
+ Args:
+ 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
+ """
+ if not node_id:
+ raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "cache_final_rows": cache_final_rows,
+ "cache_final_size_bytes": cache_final_size_bytes,
+ "cache_max_bytes": cache_max_bytes,
+ "cache_original_rows": cache_original_rows,
+ "cache_original_size_bytes": cache_original_size_bytes,
+ "cache_truncated": cache_truncated,
+ "output_schema": output_schema,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return self._post(
+ path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
+ body=maybe_transform(body, session_upload_node_output_data_params.SessionUploadNodeOutputDataParams),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=WorkflowSessionNode,
+ )
+
def upload_node_visualization_output(
self,
node_id: str,
@@ -1504,6 +1570,66 @@ async def upload_dashboard_layout(
cast_to=WorkflowSession,
)
+ async def upload_node_output_data(
+ self,
+ node_id: str,
+ *,
+ content: FileTypes,
+ cache_final_rows: Optional[int] | Omit = omit,
+ cache_final_size_bytes: Optional[int] | Omit = omit,
+ cache_max_bytes: Optional[int] | Omit = omit,
+ cache_original_rows: Optional[int] | Omit = omit,
+ cache_original_size_bytes: Optional[int] | Omit = omit,
+ cache_truncated: Optional[bool] | Omit = omit,
+ output_schema: 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,
+ ) -> WorkflowSessionNode:
+ """
+ Args:
+ 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
+ """
+ if not node_id:
+ raise ValueError(f"Expected a non-empty value for `node_id` but received {node_id!r}")
+ body = deepcopy_minimal(
+ {
+ "content": content,
+ "cache_final_rows": cache_final_rows,
+ "cache_final_size_bytes": cache_final_size_bytes,
+ "cache_max_bytes": cache_max_bytes,
+ "cache_original_rows": cache_original_rows,
+ "cache_original_size_bytes": cache_original_size_bytes,
+ "cache_truncated": cache_truncated,
+ "output_schema": output_schema,
+ }
+ )
+ files = extract_files(cast(Mapping[str, object], body), paths=[["content"]])
+ # It should be noted that the actual Content-Type header that will be
+ # sent to the server will contain a `boundary` parameter, e.g.
+ # multipart/form-data; boundary=---abc--
+ extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})}
+ return await self._post(
+ path_template("/sessions/nodes/{node_id}/output_data", node_id=node_id),
+ body=await async_maybe_transform(
+ body, session_upload_node_output_data_params.SessionUploadNodeOutputDataParams
+ ),
+ files=files,
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=WorkflowSessionNode,
+ )
+
async def upload_node_visualization_output(
self,
node_id: str,
@@ -1597,6 +1723,9 @@ def __init__(self, sessions: SessionsResource) -> None:
self.upload_dashboard_layout = to_raw_response_wrapper(
sessions.upload_dashboard_layout,
)
+ self.upload_node_output_data = to_raw_response_wrapper(
+ sessions.upload_node_output_data,
+ )
self.upload_node_visualization_output = to_raw_response_wrapper(
sessions.upload_node_visualization_output,
)
@@ -1658,6 +1787,9 @@ def __init__(self, sessions: AsyncSessionsResource) -> None:
self.upload_dashboard_layout = async_to_raw_response_wrapper(
sessions.upload_dashboard_layout,
)
+ self.upload_node_output_data = async_to_raw_response_wrapper(
+ sessions.upload_node_output_data,
+ )
self.upload_node_visualization_output = async_to_raw_response_wrapper(
sessions.upload_node_visualization_output,
)
@@ -1719,6 +1851,9 @@ def __init__(self, sessions: SessionsResource) -> None:
self.upload_dashboard_layout = to_streamed_response_wrapper(
sessions.upload_dashboard_layout,
)
+ self.upload_node_output_data = to_streamed_response_wrapper(
+ sessions.upload_node_output_data,
+ )
self.upload_node_visualization_output = to_streamed_response_wrapper(
sessions.upload_node_visualization_output,
)
@@ -1780,6 +1915,9 @@ def __init__(self, sessions: AsyncSessionsResource) -> None:
self.upload_dashboard_layout = async_to_streamed_response_wrapper(
sessions.upload_dashboard_layout,
)
+ self.upload_node_output_data = async_to_streamed_response_wrapper(
+ sessions.upload_node_output_data,
+ )
self.upload_node_visualization_output = async_to_streamed_response_wrapper(
sessions.upload_node_visualization_output,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index eabda1f97..3d7bb30bb 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -161,6 +161,7 @@
from .dataset_match_response import DatasetMatchResponse as DatasetMatchResponse
from .document_delete_params import DocumentDeleteParams as DocumentDeleteParams
from .document_list_response import DocumentListResponse as DocumentListResponse
+from .document_upload_params import DocumentUploadParams as DocumentUploadParams
from .entity_delete_response import EntityDeleteResponse as EntityDeleteResponse
from .entity_derive_response import EntityDeriveResponse as EntityDeriveResponse
from .entity_search_response import EntitySearchResponse as EntitySearchResponse
@@ -282,6 +283,7 @@
from .chat_admin_issue_found_params import ChatAdminIssueFoundParams as ChatAdminIssueFoundParams
from .chat_delete_input_file_params import ChatDeleteInputFileParams as ChatDeleteInputFileParams
from .chat_update_visibility_params import ChatUpdateVisibilityParams as ChatUpdateVisibilityParams
+from .chat_upload_input_file_params import ChatUploadInputFileParams as ChatUploadInputFileParams
from .code_apply_manual_edit_params import CodeApplyManualEditParams as CodeApplyManualEditParams
from .connector_catalog_list_params import ConnectorCatalogListParams as ConnectorCatalogListParams
from .connector_table_path_response import ConnectorTablePathResponse as ConnectorTablePathResponse
@@ -314,6 +316,7 @@
from .workflow_schedule_pause_params import WorkflowSchedulePauseParams as WorkflowSchedulePauseParams
from .chat_delete_input_file_response import ChatDeleteInputFileResponse as ChatDeleteInputFileResponse
from .chat_get_partial_chats_response import ChatGetPartialChatsResponse as ChatGetPartialChatsResponse
+from .chat_upload_input_file_response import ChatUploadInputFileResponse as ChatUploadInputFileResponse
from .connector_catalog_list_response import ConnectorCatalogListResponse as ConnectorCatalogListResponse
from .entity_update_property_response import EntityUpdatePropertyResponse as EntityUpdatePropertyResponse
from .session_edit_node_output_params import SessionEditNodeOutputParams as SessionEditNodeOutputParams
@@ -374,6 +377,9 @@
from .session_upload_dashboard_layout_params import (
SessionUploadDashboardLayoutParams as SessionUploadDashboardLayoutParams,
)
+from .session_upload_node_output_data_params import (
+ SessionUploadNodeOutputDataParams as SessionUploadNodeOutputDataParams,
+)
from .dataset_count_missing_embeddings_params import (
DatasetCountMissingEmbeddingsParams as DatasetCountMissingEmbeddingsParams,
)
diff --git a/src/structify/types/admin/datahub_ingestion_key.py b/src/structify/types/admin/datahub_ingestion_key.py
index 8981cd7ac..4fd0234de 100644
--- a/src/structify/types/admin/datahub_ingestion_key.py
+++ b/src/structify/types/admin/datahub_ingestion_key.py
@@ -15,4 +15,6 @@
"role",
"instance_url",
"access_token",
+ "project_id",
+ "credential_json",
]
diff --git a/src/structify/types/admin/datahub_ingestion_type.py b/src/structify/types/admin/datahub_ingestion_type.py
index e5b679a16..592994fdf 100644
--- a/src/structify/types/admin/datahub_ingestion_type.py
+++ b/src/structify/types/admin/datahub_ingestion_type.py
@@ -4,4 +4,4 @@
__all__ = ["DatahubIngestionType"]
-DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot"]
+DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot", "bigquery"]
diff --git a/src/structify/types/chat_upload_input_file_params.py b/src/structify/types/chat_upload_input_file_params.py
new file mode 100644
index 000000000..a4a6eb732
--- /dev/null
+++ b/src/structify/types/chat_upload_input_file_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["ChatUploadInputFileParams"]
+
+
+class ChatUploadInputFileParams(TypedDict, total=False):
+ content: Required[FileTypes]
+
+ content_type: Required[str]
+
+ file_name: Required[str]
diff --git a/src/structify/types/chat_upload_input_file_response.py b/src/structify/types/chat_upload_input_file_response.py
new file mode 100644
index 000000000..29e08729c
--- /dev/null
+++ b/src/structify/types/chat_upload_input_file_response.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from datetime import datetime
+
+from .._models import BaseModel
+
+__all__ = ["ChatUploadInputFileResponse", "File"]
+
+
+class File(BaseModel):
+ chat_session_id: str
+
+ content_type: str
+
+ created_at: datetime
+
+ file_size: int
+
+ filename: str
+
+
+class ChatUploadInputFileResponse(BaseModel):
+ file: File
diff --git a/src/structify/types/document_list_response.py b/src/structify/types/document_list_response.py
index 062d7f758..aeb9c2ea5 100644
--- a/src/structify/types/document_list_response.py
+++ b/src/structify/types/document_list_response.py
@@ -16,8 +16,6 @@ class DocumentListResponseItem(BaseModel):
file_bytes: object
- file_size: int
-
file_type: Literal["Text", "PDF", "SEC"]
name: str
diff --git a/src/structify/types/document_upload_params.py b/src/structify/types/document_upload_params.py
new file mode 100644
index 000000000..779402c07
--- /dev/null
+++ b/src/structify/types/document_upload_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
+
+from .._types import FileTypes
+
+__all__ = ["DocumentUploadParams"]
+
+
+class DocumentUploadParams(TypedDict, total=False):
+ content: Required[FileTypes]
+
+ file_type: Required[Literal["Text", "PDF", "SEC"]]
+
+ path: Required[FileTypes]
+
+ dataset: Optional[str]
+
+ project_id: Optional[str]
diff --git a/src/structify/types/session_upload_node_output_data_params.py b/src/structify/types/session_upload_node_output_data_params.py
new file mode 100644
index 000000000..dcc0b284c
--- /dev/null
+++ b/src/structify/types/session_upload_node_output_data_params.py
@@ -0,0 +1,28 @@
+# 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 Required, TypedDict
+
+from .._types import FileTypes
+
+__all__ = ["SessionUploadNodeOutputDataParams"]
+
+
+class SessionUploadNodeOutputDataParams(TypedDict, total=False):
+ content: Required[FileTypes]
+
+ cache_final_rows: Optional[int]
+
+ cache_final_size_bytes: Optional[int]
+
+ cache_max_bytes: Optional[int]
+
+ cache_original_rows: Optional[int]
+
+ cache_original_size_bytes: Optional[int]
+
+ cache_truncated: Optional[bool]
+
+ output_schema: Optional[str]
diff --git a/src/structify/types/workflow_session_node.py b/src/structify/types/workflow_session_node.py
index c3afbe1e2..0f93d2b48 100644
--- a/src/structify/types/workflow_session_node.py
+++ b/src/structify/types/workflow_session_node.py
@@ -66,8 +66,6 @@ class WorkflowSessionNode(BaseModel):
output_blob_name: Optional[str] = None
- output_file_size: Optional[int] = None
-
output_schema: Optional[object] = None
progress: Optional[object] = None
diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py
index 1d4dc0ef9..c2800d934 100644
--- a/tests/api_resources/test_chat.py
+++ b/tests/api_resources/test_chat.py
@@ -36,6 +36,7 @@
ChatRevertToCommitResponse,
ChatDeleteInputFileResponse,
ChatGetPartialChatsResponse,
+ ChatUploadInputFileResponse,
ChatGetSessionTimelineResponse,
ChatCopyNodeOutputByCodeHashResponse,
)
@@ -1564,6 +1565,56 @@ def test_path_params_update_visibility(self, client: Structify) -> None:
visibility="private",
)
+ @parametrize
+ def test_method_upload_input_file(self, client: Structify) -> None:
+ chat = client.chat.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ )
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ def test_raw_response_upload_input_file(self, client: Structify) -> None:
+ response = client.chat.with_raw_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ def test_streaming_response_upload_input_file(self, client: Structify) -> None:
+ with client.chat.with_streaming_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_input_file(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ client.chat.with_raw_response.upload_input_file(
+ chat_id="",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ )
+
class TestAsyncChat:
parametrize = pytest.mark.parametrize(
@@ -3082,3 +3133,53 @@ async def test_path_params_update_visibility(self, async_client: AsyncStructify)
session_id="",
visibility="private",
)
+
+ @parametrize
+ async def test_method_upload_input_file(self, async_client: AsyncStructify) -> None:
+ chat = await async_client.chat.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ )
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_raw_response_upload_input_file(self, async_client: AsyncStructify) -> None:
+ response = await async_client.chat.with_raw_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ chat = await response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_upload_input_file(self, async_client: AsyncStructify) -> None:
+ async with async_client.chat.with_streaming_response.upload_input_file(
+ chat_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ chat = await response.parse()
+ assert_matches_type(ChatUploadInputFileResponse, chat, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_input_file(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `chat_id` but received ''"):
+ await async_client.chat.with_raw_response.upload_input_file(
+ chat_id="",
+ content=b"Example data",
+ content_type="content_type",
+ file_name="file_name",
+ )
diff --git a/tests/api_resources/test_documents.py b/tests/api_resources/test_documents.py
index 24a3b2129..6562d8463 100644
--- a/tests/api_resources/test_documents.py
+++ b/tests/api_resources/test_documents.py
@@ -115,6 +115,54 @@ def test_streaming_response_download(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_upload(self, client: Structify) -> None:
+ document = client.documents.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ )
+ assert document is None
+
+ @parametrize
+ def test_method_upload_with_all_params(self, client: Structify) -> None:
+ document = client.documents.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ dataset="dataset",
+ project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert document is None
+
+ @parametrize
+ def test_raw_response_upload(self, client: Structify) -> None:
+ response = client.documents.with_raw_response.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ document = response.parse()
+ assert document is None
+
+ @parametrize
+ def test_streaming_response_upload(self, client: Structify) -> None:
+ with client.documents.with_streaming_response.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ document = response.parse()
+ assert document is None
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncDocuments:
parametrize = pytest.mark.parametrize(
@@ -215,3 +263,51 @@ async def test_streaming_response_download(self, async_client: AsyncStructify) -
assert_matches_type(DocumentDownloadResponse, document, path=["response"])
assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_upload(self, async_client: AsyncStructify) -> None:
+ document = await async_client.documents.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ )
+ assert document is None
+
+ @parametrize
+ async def test_method_upload_with_all_params(self, async_client: AsyncStructify) -> None:
+ document = await async_client.documents.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ dataset="dataset",
+ project_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert document is None
+
+ @parametrize
+ async def test_raw_response_upload(self, async_client: AsyncStructify) -> None:
+ response = await async_client.documents.with_raw_response.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ document = await response.parse()
+ assert document is None
+
+ @parametrize
+ async def test_streaming_response_upload(self, async_client: AsyncStructify) -> None:
+ async with async_client.documents.with_streaming_response.upload(
+ content=b"Example data",
+ file_type="Text",
+ path=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ document = await response.parse()
+ assert document is None
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_sessions.py b/tests/api_resources/test_sessions.py
index 51d12e5bc..f960c82df 100644
--- a/tests/api_resources/test_sessions.py
+++ b/tests/api_resources/test_sessions.py
@@ -1190,6 +1190,63 @@ def test_path_params_upload_dashboard_layout_overload_2(self, client: Structify)
],
)
+ @parametrize
+ def test_method_upload_node_output_data(self, client: Structify) -> None:
+ session = client.sessions.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ )
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ @parametrize
+ def test_method_upload_node_output_data_with_all_params(self, client: Structify) -> None:
+ session = client.sessions.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ cache_final_rows=0,
+ cache_final_size_bytes=0,
+ cache_max_bytes=0,
+ cache_original_rows=0,
+ cache_original_size_bytes=0,
+ cache_truncated=True,
+ output_schema="output_schema",
+ )
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ @parametrize
+ def test_raw_response_upload_node_output_data(self, client: Structify) -> None:
+ response = client.sessions.with_raw_response.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = response.parse()
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ @parametrize
+ def test_streaming_response_upload_node_output_data(self, client: Structify) -> None:
+ with client.sessions.with_streaming_response.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = response.parse()
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_upload_node_output_data(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `node_id` but received ''"):
+ client.sessions.with_raw_response.upload_node_output_data(
+ node_id="",
+ content=b"Example data",
+ )
+
@parametrize
def test_method_upload_node_visualization_output(self, client: Structify) -> None:
session = client.sessions.upload_node_visualization_output(
@@ -2397,6 +2454,63 @@ async def test_path_params_upload_dashboard_layout_overload_2(self, async_client
],
)
+ @parametrize
+ async def test_method_upload_node_output_data(self, async_client: AsyncStructify) -> None:
+ session = await async_client.sessions.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ )
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ @parametrize
+ async def test_method_upload_node_output_data_with_all_params(self, async_client: AsyncStructify) -> None:
+ session = await async_client.sessions.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ cache_final_rows=0,
+ cache_final_size_bytes=0,
+ cache_max_bytes=0,
+ cache_original_rows=0,
+ cache_original_size_bytes=0,
+ cache_truncated=True,
+ output_schema="output_schema",
+ )
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ @parametrize
+ async def test_raw_response_upload_node_output_data(self, async_client: AsyncStructify) -> None:
+ response = await async_client.sessions.with_raw_response.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ session = await response.parse()
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_upload_node_output_data(self, async_client: AsyncStructify) -> None:
+ async with async_client.sessions.with_streaming_response.upload_node_output_data(
+ node_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ content=b"Example data",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ session = await response.parse()
+ assert_matches_type(WorkflowSessionNode, session, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_upload_node_output_data(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `node_id` but received ''"):
+ await async_client.sessions.with_raw_response.upload_node_output_data(
+ node_id="",
+ content=b"Example data",
+ )
+
@parametrize
async def test_method_upload_node_visualization_output(self, async_client: AsyncStructify) -> None:
session = await async_client.sessions.upload_node_visualization_output(
From a1eb77bd78add7544ae5bc0d72535d317ee23098 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 04:11:13 +0000
Subject: [PATCH 088/105] feat: Update from Structify backend changes
---
.stats.yml | 4 +-
api.md | 3 +-
.../resources/connectors/connectors.py | 11 ++--
src/structify/types/__init__.py | 1 +
.../types/connector_explore_response.py | 57 +++++++++++++++++++
tests/api_resources/test_connectors.py | 17 +++---
6 files changed, 76 insertions(+), 17 deletions(-)
create mode 100644 src/structify/types/connector_explore_response.py
diff --git a/.stats.yml b/.stats.yml
index 8cf4e64df..4a4baa0e3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 250
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c2c5af9cf676f34cbe61bda68172ce626e9168c76ecdf6470ed3de47cf414c8f.yml
-openapi_spec_hash: 0f2773018f65c15bb2f0e1846a18d1ab
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-5e25a73fe9df102e8855ef44e83b7d489dc4bb51c4a478f32fbc075aa80bf6b5.yml
+openapi_spec_hash: 89865e9329e6d87eaebc500a72865904
config_hash: 98bcfffe700cc36ce7df38c8236cc621
diff --git a/api.md b/api.md
index 724bdd378..b4482edb7 100644
--- a/api.md
+++ b/api.md
@@ -723,6 +723,7 @@ from structify.types import (
UpdateTableRequest,
UpdateTableResponse,
ConnectorAddSchemaObjectResponse,
+ ConnectorExploreResponse,
ConnectorGetResponse,
ConnectorGetClarificationRequestsResponse,
ConnectorListStoresResponse,
@@ -743,7 +744,7 @@ Methods:
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
- client.connectors.download_datahub_artifact(kind, \*, connector_id, \*\*params) -> BinaryAPIResponse
-- client.connectors.explore(connector_id, \*\*params) -> None
+- client.connectors.explore(connector_id, \*\*params) -> ConnectorExploreResponse
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
- client.connectors.get_exploration_runs(connector_id) -> ExplorationRunsResponse
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index f456a28ab..3ade55306 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -80,6 +80,7 @@
from ...types.explore_status_response import ExploreStatusResponse
from ...types.connector_store_response import ConnectorStoreResponse
from ...types.exploration_runs_response import ExplorationRunsResponse
+from ...types.connector_explore_response import ConnectorExploreResponse
from ...types.connector_summaries_response import ConnectorSummariesResponse
from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
@@ -746,7 +747,7 @@ def explore(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
+ ) -> ConnectorExploreResponse:
"""
Args:
only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
@@ -761,7 +762,6 @@ def explore(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=maybe_transform(
@@ -776,7 +776,7 @@ def explore(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NoneType,
+ cast_to=ConnectorExploreResponse,
)
def get(
@@ -1985,7 +1985,7 @@ async def explore(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
+ ) -> ConnectorExploreResponse:
"""
Args:
only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
@@ -2000,7 +2000,6 @@ async def explore(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=await async_maybe_transform(
@@ -2015,7 +2014,7 @@ async def explore(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NoneType,
+ cast_to=ConnectorExploreResponse,
)
async def get(
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 3d7bb30bb..f870fc69a 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -233,6 +233,7 @@
from .chat_session_with_messages import ChatSessionWithMessages as ChatSessionWithMessages
from .chat_update_session_params import ChatUpdateSessionParams as ChatUpdateSessionParams
from .connector_credential_field import ConnectorCredentialField as ConnectorCredentialField
+from .connector_explore_response import ConnectorExploreResponse as ConnectorExploreResponse
from .connector_summaries_params import ConnectorSummariesParams as ConnectorSummariesParams
from .create_match_jobs_response import CreateMatchJobsResponse as CreateMatchJobsResponse
from .document_download_response import DocumentDownloadResponse as DocumentDownloadResponse
diff --git a/src/structify/types/connector_explore_response.py b/src/structify/types/connector_explore_response.py
new file mode 100644
index 000000000..f6dbedfce
--- /dev/null
+++ b/src/structify/types/connector_explore_response.py
@@ -0,0 +1,57 @@
+# 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__ = ["ConnectorExploreResponse"]
+
+
+class ConnectorExploreResponse(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+
+ max_steps_without_save: int
+
+ membership_id: str
+
+ status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ updated_at: datetime
+
+ use_proxy: bool
+
+ user_id: str
+
+ dataset_id: Optional[str] = None
+
+ exploration_run_id: Optional[str] = None
+
+ max_errors: Optional[int] = None
+
+ max_execution_time_secs: Optional[int] = None
+
+ max_total_steps: Optional[int] = None
+
+ message: Optional[str] = None
+ """A message about the status of the job at completion"""
+
+ node_id: Optional[str] = None
+
+ parameters: Optional[object] = None
+ """Proto for JobInput"""
+
+ reason: Optional[str] = None
+ """A reason for the job's existence"""
+
+ run_started_time: Optional[datetime] = None
+ """What time did the job start running?"""
+
+ run_time_milliseconds: Optional[int] = None
+
+ seeded_kg_search_term: Optional[str] = None
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index de2341a53..1befcd4de 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -21,6 +21,7 @@
ExploreStatusResponse,
ConnectorStoreResponse,
ExplorationRunsResponse,
+ ConnectorExploreResponse,
ConnectorSummariesResponse,
ConnectorTablePathResponse,
DeleteSchemaObjectResponse,
@@ -831,7 +832,7 @@ def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
def test_method_explore_with_all_params(self, client: Structify) -> None:
@@ -842,7 +843,7 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
def test_raw_response_explore(self, client: Structify) -> None:
@@ -853,7 +854,7 @@ def test_raw_response_explore(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
def test_streaming_response_explore(self, client: Structify) -> None:
@@ -864,7 +865,7 @@ def test_streaming_response_explore(self, client: Structify) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -2293,7 +2294,7 @@ async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
async def test_method_explore_with_all_params(self, async_client: AsyncStructify) -> None:
@@ -2304,7 +2305,7 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
async def test_raw_response_explore(self, async_client: AsyncStructify) -> None:
@@ -2315,7 +2316,7 @@ async def test_raw_response_explore(self, async_client: AsyncStructify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
async def test_streaming_response_explore(self, async_client: AsyncStructify) -> None:
@@ -2326,7 +2327,7 @@ async def test_streaming_response_explore(self, async_client: AsyncStructify) ->
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
From cb2bde357153c0bc2d0b145868e0d62915f4f952 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 05:17:09 +0000
Subject: [PATCH 089/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 5 +-
src/structify/resources/admin/connector.py | 77 ++++++++++++++++++-
.../resources/connectors/connectors.py | 11 +--
src/structify/types/__init__.py | 1 -
src/structify/types/admin/__init__.py | 1 +
.../admin/admin_list_connectors_response.py | 12 +++
.../types/admin/datahub_ingestion_key.py | 2 -
.../types/admin/datahub_ingestion_type.py | 2 +-
.../types/connector_explore_response.py | 57 --------------
tests/api_resources/admin/test_connector.py | 77 +++++++++++++++++++
tests/api_resources/test_connectors.py | 17 ++--
12 files changed, 188 insertions(+), 82 deletions(-)
create mode 100644 src/structify/types/admin/admin_list_connectors_response.py
delete mode 100644 src/structify/types/connector_explore_response.py
diff --git a/.stats.yml b/.stats.yml
index 4a4baa0e3..27e5bd71a 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 250
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-5e25a73fe9df102e8855ef44e83b7d489dc4bb51c4a478f32fbc075aa80bf6b5.yml
-openapi_spec_hash: 89865e9329e6d87eaebc500a72865904
-config_hash: 98bcfffe700cc36ce7df38c8236cc621
+configured_endpoints: 251
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-f791c970b5dbb7a2e5ac0b76a9894dd5be7b8f1fc6f91b4db166139f44b78e0b.yml
+openapi_spec_hash: a8294a59cc9239d17694c5126c0ca1b3
+config_hash: 6e85cc97157c6ec93ae6393081d7dd2a
diff --git a/api.md b/api.md
index b4482edb7..6d3fd1939 100644
--- a/api.md
+++ b/api.md
@@ -435,6 +435,7 @@ Types:
```python
from structify.types.admin import (
+ AdminListConnectorsResponse,
CloneConnectorItem,
CloneConnectorsRequest,
CloneConnectorsResponse,
@@ -448,6 +449,7 @@ from structify.types.admin import (
Methods:
- client.admin.connector.clone(\*\*params) -> CloneConnectorsResponse
+- client.admin.connector.list_team_connectors(team_id) -> AdminListConnectorsResponse
- client.admin.connector.set_datahub_config(\*\*params) -> Connector
# Datasets
@@ -723,7 +725,6 @@ from structify.types import (
UpdateTableRequest,
UpdateTableResponse,
ConnectorAddSchemaObjectResponse,
- ConnectorExploreResponse,
ConnectorGetResponse,
ConnectorGetClarificationRequestsResponse,
ConnectorListStoresResponse,
@@ -744,7 +745,7 @@ Methods:
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
- client.connectors.download_datahub_artifact(kind, \*, connector_id, \*\*params) -> BinaryAPIResponse
-- client.connectors.explore(connector_id, \*\*params) -> ConnectorExploreResponse
+- client.connectors.explore(connector_id, \*\*params) -> None
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
- client.connectors.get_exploration_runs(connector_id) -> ExplorationRunsResponse
diff --git a/src/structify/resources/admin/connector.py b/src/structify/resources/admin/connector.py
index 7d57c20b7..ad0a27d0a 100644
--- a/src/structify/resources/admin/connector.py
+++ b/src/structify/resources/admin/connector.py
@@ -7,7 +7,7 @@
import httpx
from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
-from ..._utils import maybe_transform, async_maybe_transform
+from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
from ..._response import (
@@ -27,6 +27,7 @@
from ...types.admin.datahub_secret_map_param import DatahubSecretMapParam
from ...types.admin.clone_connectors_response import CloneConnectorsResponse
from ...types.admin.clone_connector_item_param import CloneConnectorItemParam
+from ...types.admin.admin_list_connectors_response import AdminListConnectorsResponse
__all__ = ["ConnectorResource", "AsyncConnectorResource"]
@@ -94,6 +95,37 @@ def clone(
cast_to=CloneConnectorsResponse,
)
+ def list_team_connectors(
+ self,
+ team_id: str,
+ *,
+ # 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,
+ ) -> AdminListConnectorsResponse:
+ """
+ Args:
+ 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
+ """
+ if not team_id:
+ raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
+ return self._get(
+ path_template("/admin/connector/team/{team_id}", team_id=team_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AdminListConnectorsResponse,
+ )
+
def set_datahub_config(
self,
*,
@@ -200,6 +232,37 @@ async def clone(
cast_to=CloneConnectorsResponse,
)
+ async def list_team_connectors(
+ self,
+ team_id: str,
+ *,
+ # 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,
+ ) -> AdminListConnectorsResponse:
+ """
+ Args:
+ 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
+ """
+ if not team_id:
+ raise ValueError(f"Expected a non-empty value for `team_id` but received {team_id!r}")
+ return await self._get(
+ path_template("/admin/connector/team/{team_id}", team_id=team_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=AdminListConnectorsResponse,
+ )
+
async def set_datahub_config(
self,
*,
@@ -250,6 +313,9 @@ def __init__(self, connector: ConnectorResource) -> None:
self.clone = to_raw_response_wrapper(
connector.clone,
)
+ self.list_team_connectors = to_raw_response_wrapper(
+ connector.list_team_connectors,
+ )
self.set_datahub_config = to_raw_response_wrapper(
connector.set_datahub_config,
)
@@ -262,6 +328,9 @@ def __init__(self, connector: AsyncConnectorResource) -> None:
self.clone = async_to_raw_response_wrapper(
connector.clone,
)
+ self.list_team_connectors = async_to_raw_response_wrapper(
+ connector.list_team_connectors,
+ )
self.set_datahub_config = async_to_raw_response_wrapper(
connector.set_datahub_config,
)
@@ -274,6 +343,9 @@ def __init__(self, connector: ConnectorResource) -> None:
self.clone = to_streamed_response_wrapper(
connector.clone,
)
+ self.list_team_connectors = to_streamed_response_wrapper(
+ connector.list_team_connectors,
+ )
self.set_datahub_config = to_streamed_response_wrapper(
connector.set_datahub_config,
)
@@ -286,6 +358,9 @@ def __init__(self, connector: AsyncConnectorResource) -> None:
self.clone = async_to_streamed_response_wrapper(
connector.clone,
)
+ self.list_team_connectors = async_to_streamed_response_wrapper(
+ connector.list_team_connectors,
+ )
self.set_datahub_config = async_to_streamed_response_wrapper(
connector.set_datahub_config,
)
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 3ade55306..f456a28ab 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -80,7 +80,6 @@
from ...types.explore_status_response import ExploreStatusResponse
from ...types.connector_store_response import ConnectorStoreResponse
from ...types.exploration_runs_response import ExplorationRunsResponse
-from ...types.connector_explore_response import ConnectorExploreResponse
from ...types.connector_summaries_response import ConnectorSummariesResponse
from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
@@ -747,7 +746,7 @@ def explore(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ConnectorExploreResponse:
+ ) -> None:
"""
Args:
only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
@@ -762,6 +761,7 @@ def explore(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=maybe_transform(
@@ -776,7 +776,7 @@ def explore(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ConnectorExploreResponse,
+ cast_to=NoneType,
)
def get(
@@ -1985,7 +1985,7 @@ async def explore(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ConnectorExploreResponse:
+ ) -> None:
"""
Args:
only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
@@ -2000,6 +2000,7 @@ async def explore(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=await async_maybe_transform(
@@ -2014,7 +2015,7 @@ async def explore(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ConnectorExploreResponse,
+ cast_to=NoneType,
)
async def get(
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index f870fc69a..3d7bb30bb 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -233,7 +233,6 @@
from .chat_session_with_messages import ChatSessionWithMessages as ChatSessionWithMessages
from .chat_update_session_params import ChatUpdateSessionParams as ChatUpdateSessionParams
from .connector_credential_field import ConnectorCredentialField as ConnectorCredentialField
-from .connector_explore_response import ConnectorExploreResponse as ConnectorExploreResponse
from .connector_summaries_params import ConnectorSummariesParams as ConnectorSummariesParams
from .create_match_jobs_response import CreateMatchJobsResponse as CreateMatchJobsResponse
from .document_download_response import DocumentDownloadResponse as DocumentDownloadResponse
diff --git a/src/structify/types/admin/__init__.py b/src/structify/types/admin/__init__.py
index d75a1972b..00baacd28 100644
--- a/src/structify/types/admin/__init__.py
+++ b/src/structify/types/admin/__init__.py
@@ -48,6 +48,7 @@
from .create_subscription_response import CreateSubscriptionResponse as CreateSubscriptionResponse
from .functional_test_create_params import FunctionalTestCreateParams as FunctionalTestCreateParams
from .functional_test_list_response import FunctionalTestListResponse as FunctionalTestListResponse
+from .admin_list_connectors_response import AdminListConnectorsResponse as AdminListConnectorsResponse
from .update_seats_override_response import UpdateSeatsOverrideResponse as UpdateSeatsOverrideResponse
from .team_cancel_subscription_params import TeamCancelSubscriptionParams as TeamCancelSubscriptionParams
from .team_create_subscription_params import TeamCreateSubscriptionParams as TeamCreateSubscriptionParams
diff --git a/src/structify/types/admin/admin_list_connectors_response.py b/src/structify/types/admin/admin_list_connectors_response.py
new file mode 100644
index 000000000..6c4e75926
--- /dev/null
+++ b/src/structify/types/admin/admin_list_connectors_response.py
@@ -0,0 +1,12 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+from ..connector import Connector
+
+__all__ = ["AdminListConnectorsResponse"]
+
+
+class AdminListConnectorsResponse(BaseModel):
+ connectors: List[Connector]
diff --git a/src/structify/types/admin/datahub_ingestion_key.py b/src/structify/types/admin/datahub_ingestion_key.py
index 4fd0234de..8981cd7ac 100644
--- a/src/structify/types/admin/datahub_ingestion_key.py
+++ b/src/structify/types/admin/datahub_ingestion_key.py
@@ -15,6 +15,4 @@
"role",
"instance_url",
"access_token",
- "project_id",
- "credential_json",
]
diff --git a/src/structify/types/admin/datahub_ingestion_type.py b/src/structify/types/admin/datahub_ingestion_type.py
index 592994fdf..e5b679a16 100644
--- a/src/structify/types/admin/datahub_ingestion_type.py
+++ b/src/structify/types/admin/datahub_ingestion_type.py
@@ -4,4 +4,4 @@
__all__ = ["DatahubIngestionType"]
-DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot", "bigquery"]
+DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot"]
diff --git a/src/structify/types/connector_explore_response.py b/src/structify/types/connector_explore_response.py
deleted file mode 100644
index f6dbedfce..000000000
--- a/src/structify/types/connector_explore_response.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# 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__ = ["ConnectorExploreResponse"]
-
-
-class ConnectorExploreResponse(BaseModel):
- id: str
-
- created_at: datetime
-
- job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
-
- max_steps_without_save: int
-
- membership_id: str
-
- status: Literal["Queued", "Running", "Completed", "Failed"]
-
- updated_at: datetime
-
- use_proxy: bool
-
- user_id: str
-
- dataset_id: Optional[str] = None
-
- exploration_run_id: Optional[str] = None
-
- max_errors: Optional[int] = None
-
- max_execution_time_secs: Optional[int] = None
-
- max_total_steps: Optional[int] = None
-
- message: Optional[str] = None
- """A message about the status of the job at completion"""
-
- node_id: Optional[str] = None
-
- parameters: Optional[object] = None
- """Proto for JobInput"""
-
- reason: Optional[str] = None
- """A reason for the job's existence"""
-
- run_started_time: Optional[datetime] = None
- """What time did the job start running?"""
-
- run_time_milliseconds: Optional[int] = None
-
- seeded_kg_search_term: Optional[str] = None
diff --git a/tests/api_resources/admin/test_connector.py b/tests/api_resources/admin/test_connector.py
index b55aacde2..da0a98af9 100644
--- a/tests/api_resources/admin/test_connector.py
+++ b/tests/api_resources/admin/test_connector.py
@@ -12,6 +12,7 @@
from structify.types import Connector
from structify.types.admin import (
CloneConnectorsResponse,
+ AdminListConnectorsResponse,
)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -78,6 +79,44 @@ def test_streaming_response_clone(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_list_team_connectors(self, client: Structify) -> None:
+ connector = client.admin.connector.list_team_connectors(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(AdminListConnectorsResponse, connector, path=["response"])
+
+ @parametrize
+ def test_raw_response_list_team_connectors(self, client: Structify) -> None:
+ response = client.admin.connector.with_raw_response.list_team_connectors(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert_matches_type(AdminListConnectorsResponse, connector, path=["response"])
+
+ @parametrize
+ def test_streaming_response_list_team_connectors(self, client: Structify) -> None:
+ with client.admin.connector.with_streaming_response.list_team_connectors(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert_matches_type(AdminListConnectorsResponse, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_list_team_connectors(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `team_id` but received ''"):
+ client.admin.connector.with_raw_response.list_team_connectors(
+ "",
+ )
+
@parametrize
def test_method_set_datahub_config(self, client: Structify) -> None:
connector = client.admin.connector.set_datahub_config(
@@ -182,6 +221,44 @@ async def test_streaming_response_clone(self, async_client: AsyncStructify) -> N
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_list_team_connectors(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.admin.connector.list_team_connectors(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(AdminListConnectorsResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_raw_response_list_team_connectors(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.connector.with_raw_response.list_team_connectors(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert_matches_type(AdminListConnectorsResponse, connector, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_list_team_connectors(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.connector.with_streaming_response.list_team_connectors(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert_matches_type(AdminListConnectorsResponse, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_list_team_connectors(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `team_id` but received ''"):
+ await async_client.admin.connector.with_raw_response.list_team_connectors(
+ "",
+ )
+
@parametrize
async def test_method_set_datahub_config(self, async_client: AsyncStructify) -> None:
connector = await async_client.admin.connector.set_datahub_config(
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index 1befcd4de..de2341a53 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -21,7 +21,6 @@
ExploreStatusResponse,
ConnectorStoreResponse,
ExplorationRunsResponse,
- ConnectorExploreResponse,
ConnectorSummariesResponse,
ConnectorTablePathResponse,
DeleteSchemaObjectResponse,
@@ -832,7 +831,7 @@ def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
@parametrize
def test_method_explore_with_all_params(self, client: Structify) -> None:
@@ -843,7 +842,7 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
@parametrize
def test_raw_response_explore(self, client: Structify) -> None:
@@ -854,7 +853,7 @@ def test_raw_response_explore(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
@parametrize
def test_streaming_response_explore(self, client: Structify) -> None:
@@ -865,7 +864,7 @@ def test_streaming_response_explore(self, client: Structify) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
assert cast(Any, response.is_closed) is True
@@ -2294,7 +2293,7 @@ async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
@parametrize
async def test_method_explore_with_all_params(self, async_client: AsyncStructify) -> None:
@@ -2305,7 +2304,7 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
@parametrize
async def test_raw_response_explore(self, async_client: AsyncStructify) -> None:
@@ -2316,7 +2315,7 @@ async def test_raw_response_explore(self, async_client: AsyncStructify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
@parametrize
async def test_streaming_response_explore(self, async_client: AsyncStructify) -> None:
@@ -2327,7 +2326,7 @@ async def test_streaming_response_explore(self, async_client: AsyncStructify) ->
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
+ assert connector is None
assert cast(Any, response.is_closed) is True
From 01356050e6b8ca81b73063513a3620830ce2d84f Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 16:09:19 +0000
Subject: [PATCH 090/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 10 +-
.../resources/connectors/connectors.py | 106 ++++++++++++--
src/structify/types/__init__.py | 5 +-
.../types/admin/datahub_ingestion_key.py | 2 +
.../types/admin/datahub_ingestion_type.py | 2 +-
.../types/connector_explore_response.py | 57 ++++++++
src/structify/types/datahub_progress.py | 23 ++++
src/structify/types/exploration_progress.py | 15 ++
.../types/explore_status_response.py | 15 --
src/structify/types/phase_activity.py | 24 ++++
tests/api_resources/test_connectors.py | 130 +++++++++++++++---
12 files changed, 346 insertions(+), 51 deletions(-)
create mode 100644 src/structify/types/connector_explore_response.py
create mode 100644 src/structify/types/datahub_progress.py
create mode 100644 src/structify/types/exploration_progress.py
delete mode 100644 src/structify/types/explore_status_response.py
create mode 100644 src/structify/types/phase_activity.py
diff --git a/.stats.yml b/.stats.yml
index 27e5bd71a..921ff3ac3 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 251
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-f791c970b5dbb7a2e5ac0b76a9894dd5be7b8f1fc6f91b4db166139f44b78e0b.yml
-openapi_spec_hash: a8294a59cc9239d17694c5126c0ca1b3
-config_hash: 6e85cc97157c6ec93ae6393081d7dd2a
+configured_endpoints: 252
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c535d4924329e4b892148f99a7d743ef0f28ef5d19b01e100593287ee846ed9a.yml
+openapi_spec_hash: 2960b9bd3ce9340081b522dcef2d6de3
+config_hash: b9cb71996ee8a3461255fb22782b1cd2
diff --git a/api.md b/api.md
index 6d3fd1939..2c80fa4f1 100644
--- a/api.md
+++ b/api.md
@@ -708,23 +708,26 @@ from structify.types import (
ConnectorWithSnippets,
CreateConnectorRequest,
CreateSecretRequest,
+ DatahubProgress,
DeleteSchemaObjectRequest,
DeleteSchemaObjectResponse,
ExplorationPhaseID,
+ ExplorationProgress,
ExplorationRun,
ExplorationRunsResponse,
ExplorationStatus,
ExploreConnectorRequest,
- ExploreStatusResponse,
ExplorerChatResponse,
ListTablesResponse,
LlmInformationStore,
+ PhaseActivity,
SchemaObjectID,
UpdateColumnRequest,
UpdateConnectorRequest,
UpdateTableRequest,
UpdateTableResponse,
ConnectorAddSchemaObjectResponse,
+ ConnectorExploreResponse,
ConnectorGetResponse,
ConnectorGetClarificationRequestsResponse,
ConnectorListStoresResponse,
@@ -745,11 +748,12 @@ Methods:
- client.connectors.delete_schema_object(connector_id, \*\*params) -> DeleteSchemaObjectResponse
- client.connectors.delete_secret(secret_name, \*, connector_id) -> None
- client.connectors.download_datahub_artifact(kind, \*, connector_id, \*\*params) -> BinaryAPIResponse
-- client.connectors.explore(connector_id, \*\*params) -> None
+- client.connectors.explore(connector_id, \*\*params) -> ConnectorExploreResponse
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
+- client.connectors.get_exploration_progress(run_id, \*, connector_id) -> ExplorationProgress
- client.connectors.get_exploration_runs(connector_id) -> ExplorationRunsResponse
-- client.connectors.get_exploration_status(connector_id) -> ExploreStatusResponse
+- client.connectors.get_exploration_status(connector_id) -> Optional[ExplorationRun]
- client.connectors.get_explorer_chat(connector_id, \*\*params) -> ExplorerChatResponse
- client.connectors.get_store(connector_id) -> ConnectorStoreResponse
- client.connectors.get_table_path(table_id) -> ConnectorTablePathResponse
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index f456a28ab..41f1af838 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -71,15 +71,17 @@
)
from ..._base_client import AsyncPaginator, make_request_options
from ...types.connector import Connector
+from ...types.exploration_run import ExplorationRun
from ...types.connector_category import ConnectorCategory
+from ...types.exploration_progress import ExplorationProgress
from ...types.list_tables_response import ListTablesResponse
from ...types.update_table_response import UpdateTableResponse
from ...types.connector_get_response import ConnectorGetResponse
from ...types.connector_with_secrets import ConnectorWithSecrets
from ...types.explorer_chat_response import ExplorerChatResponse
-from ...types.explore_status_response import ExploreStatusResponse
from ...types.connector_store_response import ConnectorStoreResponse
from ...types.exploration_runs_response import ExplorationRunsResponse
+from ...types.connector_explore_response import ConnectorExploreResponse
from ...types.connector_summaries_response import ConnectorSummariesResponse
from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
@@ -746,7 +748,7 @@ def explore(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
+ ) -> ConnectorExploreResponse:
"""
Args:
only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
@@ -761,7 +763,6 @@ def explore(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return self._post(
path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=maybe_transform(
@@ -776,7 +777,7 @@ def explore(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NoneType,
+ cast_to=ConnectorExploreResponse,
)
def get(
@@ -843,6 +844,42 @@ def get_clarification_requests(
cast_to=ConnectorGetClarificationRequestsResponse,
)
+ def get_exploration_progress(
+ self,
+ run_id: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> ExplorationProgress:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return self._get(
+ path_template(
+ "/connectors/{connector_id}/explore/runs/{run_id}/progress", connector_id=connector_id, run_id=run_id
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExplorationProgress,
+ )
+
def get_exploration_runs(
self,
connector_id: str,
@@ -886,7 +923,7 @@ def get_exploration_status(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExploreStatusResponse:
+ ) -> Optional[ExplorationRun]:
"""
Args:
extra_headers: Send extra headers
@@ -904,7 +941,7 @@ def get_exploration_status(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExploreStatusResponse,
+ cast_to=ExplorationRun,
)
def get_explorer_chat(
@@ -1985,7 +2022,7 @@ async def explore(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> None:
+ ) -> ConnectorExploreResponse:
"""
Args:
only_do_datahub: If true, run only DataHub ingestion without queuing Diego annotation jobs.
@@ -2000,7 +2037,6 @@ async def explore(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- extra_headers = {"Accept": "*/*", **(extra_headers or {})}
return await self._post(
path_template("/connectors/{connector_id}/explore", connector_id=connector_id),
body=await async_maybe_transform(
@@ -2015,7 +2051,7 @@ async def explore(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=NoneType,
+ cast_to=ConnectorExploreResponse,
)
async def get(
@@ -2082,6 +2118,42 @@ async def get_clarification_requests(
cast_to=ConnectorGetClarificationRequestsResponse,
)
+ async def get_exploration_progress(
+ self,
+ run_id: str,
+ *,
+ connector_id: str,
+ # 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,
+ ) -> ExplorationProgress:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
+ return await self._get(
+ path_template(
+ "/connectors/{connector_id}/explore/runs/{run_id}/progress", connector_id=connector_id, run_id=run_id
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExplorationProgress,
+ )
+
async def get_exploration_runs(
self,
connector_id: str,
@@ -2125,7 +2197,7 @@ async def get_exploration_status(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExploreStatusResponse:
+ ) -> Optional[ExplorationRun]:
"""
Args:
extra_headers: Send extra headers
@@ -2143,7 +2215,7 @@ async def get_exploration_status(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExploreStatusResponse,
+ cast_to=ExplorationRun,
)
async def get_explorer_chat(
@@ -2618,6 +2690,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_clarification_requests = to_raw_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_progress = to_raw_response_wrapper(
+ connectors.get_exploration_progress,
+ )
self.get_exploration_runs = to_raw_response_wrapper(
connectors.get_exploration_runs,
)
@@ -2707,6 +2782,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_clarification_requests = async_to_raw_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_progress = async_to_raw_response_wrapper(
+ connectors.get_exploration_progress,
+ )
self.get_exploration_runs = async_to_raw_response_wrapper(
connectors.get_exploration_runs,
)
@@ -2796,6 +2874,9 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_clarification_requests = to_streamed_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_progress = to_streamed_response_wrapper(
+ connectors.get_exploration_progress,
+ )
self.get_exploration_runs = to_streamed_response_wrapper(
connectors.get_exploration_runs,
)
@@ -2885,6 +2966,9 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_clarification_requests = async_to_streamed_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_progress = async_to_streamed_response_wrapper(
+ connectors.get_exploration_progress,
+ )
self.get_exploration_runs = async_to_streamed_response_wrapper(
connectors.get_exploration_runs,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 3d7bb30bb..9b5de4d86 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -38,6 +38,7 @@
from .dashboard_page import DashboardPage as DashboardPage
from .dashboard_spec import DashboardSpec as DashboardSpec
from .job_event_body import JobEventBody as JobEventBody
+from .phase_activity import PhaseActivity as PhaseActivity
from .project_member import ProjectMember as ProjectMember
from .strategy_param import StrategyParam as StrategyParam
from .team_with_role import TeamWithRole as TeamWithRole
@@ -58,6 +59,7 @@
from .viz_param_param import VizParamParam as VizParamParam
from .viz_query_param import VizQueryParam as VizQueryParam
from .chat_copy_params import ChatCopyParams as ChatCopyParams
+from .datahub_progress import DatahubProgress as DatahubProgress
from .job_get_response import JobGetResponse as JobGetResponse
from .save_requirement import SaveRequirement as SaveRequirement
from .viz_date_control import VizDateControl as VizDateControl
@@ -127,6 +129,7 @@
from .entity_verify_params import EntityVerifyParams as EntityVerifyParams
from .entity_view_response import EntityViewResponse as EntityViewResponse
from .exploration_phase_id import ExplorationPhaseID as ExplorationPhaseID
+from .exploration_progress import ExplorationProgress as ExplorationProgress
from .list_tables_response import ListTablesResponse as ListTablesResponse
from .project_get_response import ProjectGetResponse as ProjectGetResponse
from .scrape_list_response import ScrapeListResponse as ScrapeListResponse
@@ -185,7 +188,6 @@
from .entity_add_batch_params import EntityAddBatchParams as EntityAddBatchParams
from .entity_list_jobs_params import EntityListJobsParams as EntityListJobsParams
from .entity_summarize_params import EntitySummarizeParams as EntitySummarizeParams
-from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
from .template_question_param import TemplateQuestionParam as TemplateQuestionParam
from .trigger_review_response import TriggerReviewResponse as TriggerReviewResponse
@@ -233,6 +235,7 @@
from .chat_session_with_messages import ChatSessionWithMessages as ChatSessionWithMessages
from .chat_update_session_params import ChatUpdateSessionParams as ChatUpdateSessionParams
from .connector_credential_field import ConnectorCredentialField as ConnectorCredentialField
+from .connector_explore_response import ConnectorExploreResponse as ConnectorExploreResponse
from .connector_summaries_params import ConnectorSummariesParams as ConnectorSummariesParams
from .create_match_jobs_response import CreateMatchJobsResponse as CreateMatchJobsResponse
from .document_download_response import DocumentDownloadResponse as DocumentDownloadResponse
diff --git a/src/structify/types/admin/datahub_ingestion_key.py b/src/structify/types/admin/datahub_ingestion_key.py
index 8981cd7ac..4fd0234de 100644
--- a/src/structify/types/admin/datahub_ingestion_key.py
+++ b/src/structify/types/admin/datahub_ingestion_key.py
@@ -15,4 +15,6 @@
"role",
"instance_url",
"access_token",
+ "project_id",
+ "credential_json",
]
diff --git a/src/structify/types/admin/datahub_ingestion_type.py b/src/structify/types/admin/datahub_ingestion_type.py
index e5b679a16..592994fdf 100644
--- a/src/structify/types/admin/datahub_ingestion_type.py
+++ b/src/structify/types/admin/datahub_ingestion_type.py
@@ -4,4 +4,4 @@
__all__ = ["DatahubIngestionType"]
-DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot"]
+DatahubIngestionType: TypeAlias = Literal["postgres", "snowflake", "salesforce", "hubspot", "bigquery"]
diff --git a/src/structify/types/connector_explore_response.py b/src/structify/types/connector_explore_response.py
new file mode 100644
index 000000000..f6dbedfce
--- /dev/null
+++ b/src/structify/types/connector_explore_response.py
@@ -0,0 +1,57 @@
+# 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__ = ["ConnectorExploreResponse"]
+
+
+class ConnectorExploreResponse(BaseModel):
+ id: str
+
+ created_at: datetime
+
+ job_type: Literal["Web", "Pdf", "Derive", "Scrape", "Match", "ConnectorExplore", "DatahubIngestion"]
+
+ max_steps_without_save: int
+
+ membership_id: str
+
+ status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ updated_at: datetime
+
+ use_proxy: bool
+
+ user_id: str
+
+ dataset_id: Optional[str] = None
+
+ exploration_run_id: Optional[str] = None
+
+ max_errors: Optional[int] = None
+
+ max_execution_time_secs: Optional[int] = None
+
+ max_total_steps: Optional[int] = None
+
+ message: Optional[str] = None
+ """A message about the status of the job at completion"""
+
+ node_id: Optional[str] = None
+
+ parameters: Optional[object] = None
+ """Proto for JobInput"""
+
+ reason: Optional[str] = None
+ """A reason for the job's existence"""
+
+ run_started_time: Optional[datetime] = None
+ """What time did the job start running?"""
+
+ run_time_milliseconds: Optional[int] = None
+
+ seeded_kg_search_term: Optional[str] = None
diff --git a/src/structify/types/datahub_progress.py b/src/structify/types/datahub_progress.py
new file mode 100644
index 000000000..7b4561117
--- /dev/null
+++ b/src/structify/types/datahub_progress.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["DatahubProgress"]
+
+
+class DatahubProgress(BaseModel):
+ databases_created: int
+
+ job_id: str
+
+ job_status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ pages_fetched: int
+
+ schemas_created: int
+
+ tables_processed: int
+
+ total_datasets: int
diff --git a/src/structify/types/exploration_progress.py b/src/structify/types/exploration_progress.py
new file mode 100644
index 000000000..2b3d4f515
--- /dev/null
+++ b/src/structify/types/exploration_progress.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .phase_activity import PhaseActivity
+from .datahub_progress import DatahubProgress
+
+__all__ = ["ExplorationProgress"]
+
+
+class ExplorationProgress(BaseModel):
+ phases: List[PhaseActivity]
+
+ datahub: Optional[DatahubProgress] = None
diff --git a/src/structify/types/explore_status_response.py b/src/structify/types/explore_status_response.py
deleted file mode 100644
index 4275c265a..000000000
--- a/src/structify/types/explore_status_response.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-from datetime import datetime
-
-from .._models import BaseModel
-from .exploration_status import ExplorationStatus
-
-__all__ = ["ExploreStatusResponse"]
-
-
-class ExploreStatusResponse(BaseModel):
- status: ExplorationStatus
-
- started_at: Optional[datetime] = None
diff --git a/src/structify/types/phase_activity.py b/src/structify/types/phase_activity.py
new file mode 100644
index 000000000..63e43ac12
--- /dev/null
+++ b/src/structify/types/phase_activity.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .exploration_phase_id import ExplorationPhaseID
+
+__all__ = ["PhaseActivity"]
+
+
+class PhaseActivity(BaseModel):
+ job_id: str
+
+ phase_id: ExplorationPhaseID
+ """Identifies the phase of connector exploration
+
+ This enum is used to track which phase of exploration a chat session belongs to.
+ It's stored as JSONB in the database to allow for flexible phase identification.
+ """
+
+ status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ chat_id: Optional[str] = None
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index de2341a53..df8f6815f 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import os
-from typing import Any, cast
+from typing import Any, Optional, cast
import httpx
import pytest
@@ -13,14 +13,16 @@
from tests.utils import assert_matches_type
from structify.types import (
Connector,
+ ExplorationRun,
ListTablesResponse,
+ ExplorationProgress,
UpdateTableResponse,
ConnectorGetResponse,
ConnectorWithSecrets,
ExplorerChatResponse,
- ExploreStatusResponse,
ConnectorStoreResponse,
ExplorationRunsResponse,
+ ConnectorExploreResponse,
ConnectorSummariesResponse,
ConnectorTablePathResponse,
DeleteSchemaObjectResponse,
@@ -831,7 +833,7 @@ def test_method_explore(self, client: Structify) -> None:
connector = client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
def test_method_explore_with_all_params(self, client: Structify) -> None:
@@ -842,7 +844,7 @@ def test_method_explore_with_all_params(self, client: Structify) -> None:
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
def test_raw_response_explore(self, client: Structify) -> None:
@@ -853,7 +855,7 @@ def test_raw_response_explore(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
def test_streaming_response_explore(self, client: Structify) -> None:
@@ -864,7 +866,7 @@ def test_streaming_response_explore(self, client: Structify) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -951,6 +953,54 @@ def test_path_params_get_clarification_requests(self, client: Structify) -> None
"",
)
+ @parametrize
+ def test_method_get_exploration_progress(self, client: Structify) -> None:
+ connector = client.connectors.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_exploration_progress(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_exploration_progress(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get_exploration_progress(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ client.connectors.with_raw_response.get_exploration_progress(
+ run_id="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
def test_method_get_exploration_runs(self, client: Structify) -> None:
connector = client.connectors.get_exploration_runs(
@@ -994,7 +1044,7 @@ def test_method_get_exploration_status(self, client: Structify) -> None:
connector = client.connectors.get_exploration_status(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
@parametrize
def test_raw_response_get_exploration_status(self, client: Structify) -> None:
@@ -1005,7 +1055,7 @@ def test_raw_response_get_exploration_status(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
@parametrize
def test_streaming_response_get_exploration_status(self, client: Structify) -> None:
@@ -1016,7 +1066,7 @@ def test_streaming_response_get_exploration_status(self, client: Structify) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -2293,7 +2343,7 @@ async def test_method_explore(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.explore(
connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
async def test_method_explore_with_all_params(self, async_client: AsyncStructify) -> None:
@@ -2304,7 +2354,7 @@ async def test_method_explore_with_all_params(self, async_client: AsyncStructify
schema_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
table_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
async def test_raw_response_explore(self, async_client: AsyncStructify) -> None:
@@ -2315,7 +2365,7 @@ async def test_raw_response_explore(self, async_client: AsyncStructify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
@parametrize
async def test_streaming_response_explore(self, async_client: AsyncStructify) -> None:
@@ -2326,7 +2376,7 @@ async def test_streaming_response_explore(self, async_client: AsyncStructify) ->
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert connector is None
+ assert_matches_type(ConnectorExploreResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -2413,6 +2463,54 @@ async def test_path_params_get_clarification_requests(self, async_client: AsyncS
"",
)
+ @parametrize
+ async def test_method_get_exploration_progress(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_exploration_progress(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_exploration_progress(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get_exploration_progress(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.get_exploration_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ await async_client.connectors.with_raw_response.get_exploration_progress(
+ run_id="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
@parametrize
async def test_method_get_exploration_runs(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.get_exploration_runs(
@@ -2456,7 +2554,7 @@ async def test_method_get_exploration_status(self, async_client: AsyncStructify)
connector = await async_client.connectors.get_exploration_status(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
@parametrize
async def test_raw_response_get_exploration_status(self, async_client: AsyncStructify) -> None:
@@ -2467,7 +2565,7 @@ async def test_raw_response_get_exploration_status(self, async_client: AsyncStru
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
@parametrize
async def test_streaming_response_get_exploration_status(self, async_client: AsyncStructify) -> None:
@@ -2478,7 +2576,7 @@ async def test_streaming_response_get_exploration_status(self, async_client: Asy
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
assert cast(Any, response.is_closed) is True
From 856162a9e8724dda056be17cf39157a3a2d2b733 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 18:06:13 +0000
Subject: [PATCH 091/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 6 +
src/structify/resources/user/user.py | 128 ++++++++++++++++
src/structify/types/__init__.py | 5 +
.../types/get_onboarding_answers_response.py | 10 ++
src/structify/types/onboarding_answers.py | 23 +++
.../types/onboarding_answers_param.py | 26 ++++
.../types/save_onboarding_answers_response.py | 10 ++
.../user_save_onboarding_answers_params.py | 13 ++
tests/api_resources/test_user.py | 144 ++++++++++++++++++
10 files changed, 369 insertions(+), 4 deletions(-)
create mode 100644 src/structify/types/get_onboarding_answers_response.py
create mode 100644 src/structify/types/onboarding_answers.py
create mode 100644 src/structify/types/onboarding_answers_param.py
create mode 100644 src/structify/types/save_onboarding_answers_response.py
create mode 100644 src/structify/types/user_save_onboarding_answers_params.py
diff --git a/.stats.yml b/.stats.yml
index 921ff3ac3..90e6e1219 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 252
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c535d4924329e4b892148f99a7d743ef0f28ef5d19b01e100593287ee846ed9a.yml
-openapi_spec_hash: 2960b9bd3ce9340081b522dcef2d6de3
-config_hash: b9cb71996ee8a3461255fb22782b1cd2
+configured_endpoints: 254
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-29c9300e82024cc61290d30aa7ac019896b932a90ba4457df9c66aed0368d5d3.yml
+openapi_spec_hash: 4704e4a255a7a8be08dbdb46adb5ccb3
+config_hash: e0609ead5e3e0971211fd2441e2be818
diff --git a/api.md b/api.md
index 2c80fa4f1..855728067 100644
--- a/api.md
+++ b/api.md
@@ -19,9 +19,13 @@ Types:
```python
from structify.types import (
EnrichUserParams,
+ GetOnboardingAnswersResponse,
JwtToAPITokenRequest,
+ OnboardingAnswers,
RefreshSessionRequest,
RefreshSessionResponse,
+ SaveOnboardingAnswersRequest,
+ SaveOnboardingAnswersResponse,
SurveySubmissionRequest,
SurveySubmissionResponse,
TokenResponse,
@@ -36,8 +40,10 @@ Methods:
- client.user.update(\*\*params) -> User
- client.user.enrich(\*\*params) -> None
+- client.user.get_onboarding_answers() -> GetOnboardingAnswersResponse
- client.user.info() -> UserInfo
- client.user.refresh(\*\*params) -> RefreshSessionResponse
+- client.user.save_onboarding_answers(\*\*params) -> SaveOnboardingAnswersResponse
- client.user.survey_submit(\*\*params) -> SurveySubmissionResponse
- client.user.transactions() -> UserTransactionsResponse
- client.user.usage(\*\*params) -> UserUsageResponse
diff --git a/src/structify/resources/user/user.py b/src/structify/resources/user/user.py
index 354969852..9d97998a5 100644
--- a/src/structify/resources/user/user.py
+++ b/src/structify/resources/user/user.py
@@ -20,6 +20,7 @@
user_update_params,
user_refresh_params,
user_survey_submit_params,
+ user_save_onboarding_answers_params,
)
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from ..._utils import maybe_transform, async_maybe_transform
@@ -43,9 +44,12 @@
from ...types.user_info import UserInfo
from ...types.admin.user import User
from ...types.user_usage_response import UserUsageResponse
+from ...types.onboarding_answers_param import OnboardingAnswersParam
from ...types.refresh_session_response import RefreshSessionResponse
from ...types.survey_submission_response import SurveySubmissionResponse
from ...types.user_transactions_response import UserTransactionsResponse
+from ...types.get_onboarding_answers_response import GetOnboardingAnswersResponse
+from ...types.save_onboarding_answers_response import SaveOnboardingAnswersResponse
__all__ = ["UserResource", "AsyncUserResource"]
@@ -149,6 +153,24 @@ def enrich(
cast_to=NoneType,
)
+ def get_onboarding_answers(
+ self,
+ *,
+ # 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,
+ ) -> GetOnboardingAnswersResponse:
+ return self._get(
+ "/user/onboarding/answers",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=GetOnboardingAnswersResponse,
+ )
+
def info(
self,
*,
@@ -209,6 +231,38 @@ def refresh(
cast_to=RefreshSessionResponse,
)
+ def save_onboarding_answers(
+ self,
+ *,
+ answers: OnboardingAnswersParam,
+ # 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,
+ ) -> SaveOnboardingAnswersResponse:
+ """
+ Args:
+ 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
+ """
+ return self._put(
+ "/user/onboarding/answers",
+ body=maybe_transform(
+ {"answers": answers}, user_save_onboarding_answers_params.UserSaveOnboardingAnswersParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SaveOnboardingAnswersResponse,
+ )
+
def survey_submit(
self,
*,
@@ -396,6 +450,24 @@ async def enrich(
cast_to=NoneType,
)
+ async def get_onboarding_answers(
+ self,
+ *,
+ # 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,
+ ) -> GetOnboardingAnswersResponse:
+ return await self._get(
+ "/user/onboarding/answers",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=GetOnboardingAnswersResponse,
+ )
+
async def info(
self,
*,
@@ -456,6 +528,38 @@ async def refresh(
cast_to=RefreshSessionResponse,
)
+ async def save_onboarding_answers(
+ self,
+ *,
+ answers: OnboardingAnswersParam,
+ # 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,
+ ) -> SaveOnboardingAnswersResponse:
+ """
+ Args:
+ 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
+ """
+ return await self._put(
+ "/user/onboarding/answers",
+ body=await async_maybe_transform(
+ {"answers": answers}, user_save_onboarding_answers_params.UserSaveOnboardingAnswersParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SaveOnboardingAnswersResponse,
+ )
+
async def survey_submit(
self,
*,
@@ -554,12 +658,18 @@ def __init__(self, user: UserResource) -> None:
self.enrich = to_raw_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = to_raw_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = to_raw_response_wrapper(
user.info,
)
self.refresh = to_raw_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = to_raw_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = to_raw_response_wrapper(
user.survey_submit,
)
@@ -590,12 +700,18 @@ def __init__(self, user: AsyncUserResource) -> None:
self.enrich = async_to_raw_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = async_to_raw_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = async_to_raw_response_wrapper(
user.info,
)
self.refresh = async_to_raw_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = async_to_raw_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = async_to_raw_response_wrapper(
user.survey_submit,
)
@@ -626,12 +742,18 @@ def __init__(self, user: UserResource) -> None:
self.enrich = to_streamed_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = to_streamed_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = to_streamed_response_wrapper(
user.info,
)
self.refresh = to_streamed_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = to_streamed_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = to_streamed_response_wrapper(
user.survey_submit,
)
@@ -662,12 +784,18 @@ def __init__(self, user: AsyncUserResource) -> None:
self.enrich = async_to_streamed_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = async_to_streamed_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = async_to_streamed_response_wrapper(
user.info,
)
self.refresh = async_to_streamed_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = async_to_streamed_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = async_to_streamed_response_wrapper(
user.survey_submit,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 9b5de4d86..38bb16c7b 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -84,6 +84,7 @@
from .entity_view_params import EntityViewParams as EntityViewParams
from .exploration_status import ExplorationStatus as ExplorationStatus
from .merge_config_param import MergeConfigParam as MergeConfigParam
+from .onboarding_answers import OnboardingAnswers as OnboardingAnswers
from .parquet_edit_param import ParquetEditParam as ParquetEditParam
from .project_visibility import ProjectVisibility as ProjectVisibility
from .relationship_param import RelationshipParam as RelationshipParam
@@ -202,6 +203,7 @@
from .entity_get_merges_params import EntityGetMergesParams as EntityGetMergesParams
from .list_dashboards_response import ListDashboardsResponse as ListDashboardsResponse
from .match_create_jobs_params import MatchCreateJobsParams as MatchCreateJobsParams
+from .onboarding_answers_param import OnboardingAnswersParam as OnboardingAnswersParam
from .refresh_session_response import RefreshSessionResponse as RefreshSessionResponse
from .session_kill_jobs_params import SessionKillJobsParams as SessionKillJobsParams
from .simulate_prompt_response import SimulatePromptResponse as SimulatePromptResponse
@@ -322,6 +324,7 @@
from .chat_upload_input_file_response import ChatUploadInputFileResponse as ChatUploadInputFileResponse
from .connector_catalog_list_response import ConnectorCatalogListResponse as ConnectorCatalogListResponse
from .entity_update_property_response import EntityUpdatePropertyResponse as EntityUpdatePropertyResponse
+from .get_onboarding_answers_response import GetOnboardingAnswersResponse as GetOnboardingAnswersResponse
from .session_edit_node_output_params import SessionEditNodeOutputParams as SessionEditNodeOutputParams
from .workflow_schedule_create_params import WorkflowScheduleCreateParams as WorkflowScheduleCreateParams
from .workflow_schedule_update_params import WorkflowScheduleUpdateParams as WorkflowScheduleUpdateParams
@@ -332,6 +335,7 @@
from .entity_get_local_subgraph_params import EntityGetLocalSubgraphParams as EntityGetLocalSubgraphParams
from .nango_list_integrations_response import NangoListIntegrationsResponse as NangoListIntegrationsResponse
from .project_collaborator_input_param import ProjectCollaboratorInputParam as ProjectCollaboratorInputParam
+from .save_onboarding_answers_response import SaveOnboardingAnswersResponse as SaveOnboardingAnswersResponse
from .connector_auth_method_with_fields import ConnectorAuthMethodWithFields as ConnectorAuthMethodWithFields
from .dataset_reorder_properties_params import DatasetReorderPropertiesParams as DatasetReorderPropertiesParams
from .dataset_set_primary_column_params import DatasetSetPrimaryColumnParams as DatasetSetPrimaryColumnParams
@@ -359,6 +363,7 @@
from .session_request_confirmation_params import SessionRequestConfirmationParams as SessionRequestConfirmationParams
from .session_update_node_progress_params import SessionUpdateNodeProgressParams as SessionUpdateNodeProgressParams
from .structure_enhance_property_response import StructureEnhancePropertyResponse as StructureEnhancePropertyResponse
+from .user_save_onboarding_answers_params import UserSaveOnboardingAnswersParams as UserSaveOnboardingAnswersParams
from .connector_add_schema_object_response import ConnectorAddSchemaObjectResponse as ConnectorAddSchemaObjectResponse
from .dataset_enrichment_progress_response import DatasetEnrichmentProgressResponse as DatasetEnrichmentProgressResponse
from .structure_find_relationship_response import StructureFindRelationshipResponse as StructureFindRelationshipResponse
diff --git a/src/structify/types/get_onboarding_answers_response.py b/src/structify/types/get_onboarding_answers_response.py
new file mode 100644
index 000000000..cada36acc
--- /dev/null
+++ b/src/structify/types/get_onboarding_answers_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .onboarding_answers import OnboardingAnswers
+
+__all__ = ["GetOnboardingAnswersResponse"]
+
+
+class GetOnboardingAnswersResponse(BaseModel):
+ answers: OnboardingAnswers
diff --git a/src/structify/types/onboarding_answers.py b/src/structify/types/onboarding_answers.py
new file mode 100644
index 000000000..d3d0be2a2
--- /dev/null
+++ b/src/structify/types/onboarding_answers.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+
+__all__ = ["OnboardingAnswers"]
+
+
+class OnboardingAnswers(BaseModel):
+ company_name: Optional[str] = None
+
+ connected_connector_ids: Optional[List[str]] = None
+
+ full_name: Optional[str] = None
+
+ primary_goal: Optional[str] = None
+
+ recommended_template_id: Optional[str] = None
+
+ role: Optional[str] = None
+
+ systems_to_connect: Optional[List[str]] = None
diff --git a/src/structify/types/onboarding_answers_param.py b/src/structify/types/onboarding_answers_param.py
new file mode 100644
index 000000000..b3e43f9f8
--- /dev/null
+++ b/src/structify/types/onboarding_answers_param.py
@@ -0,0 +1,26 @@
+# 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
+
+from .._types import SequenceNotStr
+
+__all__ = ["OnboardingAnswersParam"]
+
+
+class OnboardingAnswersParam(TypedDict, total=False):
+ company_name: Optional[str]
+
+ connected_connector_ids: Optional[SequenceNotStr[str]]
+
+ full_name: Optional[str]
+
+ primary_goal: Optional[str]
+
+ recommended_template_id: Optional[str]
+
+ role: Optional[str]
+
+ systems_to_connect: Optional[SequenceNotStr[str]]
diff --git a/src/structify/types/save_onboarding_answers_response.py b/src/structify/types/save_onboarding_answers_response.py
new file mode 100644
index 000000000..03ee078f3
--- /dev/null
+++ b/src/structify/types/save_onboarding_answers_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .onboarding_answers import OnboardingAnswers
+
+__all__ = ["SaveOnboardingAnswersResponse"]
+
+
+class SaveOnboardingAnswersResponse(BaseModel):
+ answers: OnboardingAnswers
diff --git a/src/structify/types/user_save_onboarding_answers_params.py b/src/structify/types/user_save_onboarding_answers_params.py
new file mode 100644
index 000000000..4689e70ae
--- /dev/null
+++ b/src/structify/types/user_save_onboarding_answers_params.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .onboarding_answers_param import OnboardingAnswersParam
+
+__all__ = ["UserSaveOnboardingAnswersParams"]
+
+
+class UserSaveOnboardingAnswersParams(TypedDict, total=False):
+ answers: Required[OnboardingAnswersParam]
diff --git a/tests/api_resources/test_user.py b/tests/api_resources/test_user.py
index 57a4dcc64..063cd0063 100644
--- a/tests/api_resources/test_user.py
+++ b/tests/api_resources/test_user.py
@@ -15,6 +15,8 @@
RefreshSessionResponse,
SurveySubmissionResponse,
UserTransactionsResponse,
+ GetOnboardingAnswersResponse,
+ SaveOnboardingAnswersResponse,
)
from structify.types.admin import User
@@ -117,6 +119,31 @@ def test_streaming_response_enrich(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_get_onboarding_answers(self, client: Structify) -> None:
+ user = client.user.get_onboarding_answers()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_onboarding_answers(self, client: Structify) -> None:
+ response = client.user.with_raw_response.get_onboarding_answers()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_onboarding_answers(self, client: Structify) -> None:
+ with client.user.with_streaming_response.get_onboarding_answers() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_info(self, client: Structify) -> None:
user = client.user.info()
@@ -176,6 +203,52 @@ def test_streaming_response_refresh(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_save_onboarding_answers(self, client: Structify) -> None:
+ user = client.user.save_onboarding_answers(
+ answers={},
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_method_save_onboarding_answers_with_all_params(self, client: Structify) -> None:
+ user = client.user.save_onboarding_answers(
+ answers={
+ "company_name": "company_name",
+ "connected_connector_ids": ["string"],
+ "full_name": "full_name",
+ "primary_goal": "primary_goal",
+ "recommended_template_id": "recommended_template_id",
+ "role": "role",
+ "systems_to_connect": ["string"],
+ },
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_raw_response_save_onboarding_answers(self, client: Structify) -> None:
+ response = client.user.with_raw_response.save_onboarding_answers(
+ answers={},
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_streaming_response_save_onboarding_answers(self, client: Structify) -> None:
+ with client.user.with_streaming_response.save_onboarding_answers(
+ answers={},
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_survey_submit(self, client: Structify) -> None:
user = client.user.survey_submit(
@@ -363,6 +436,31 @@ async def test_streaming_response_enrich(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ user = await async_client.user.get_onboarding_answers()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ response = await async_client.user.with_raw_response.get_onboarding_answers()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ async with async_client.user.with_streaming_response.get_onboarding_answers() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_info(self, async_client: AsyncStructify) -> None:
user = await async_client.user.info()
@@ -422,6 +520,52 @@ async def test_streaming_response_refresh(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ user = await async_client.user.save_onboarding_answers(
+ answers={},
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_method_save_onboarding_answers_with_all_params(self, async_client: AsyncStructify) -> None:
+ user = await async_client.user.save_onboarding_answers(
+ answers={
+ "company_name": "company_name",
+ "connected_connector_ids": ["string"],
+ "full_name": "full_name",
+ "primary_goal": "primary_goal",
+ "recommended_template_id": "recommended_template_id",
+ "role": "role",
+ "systems_to_connect": ["string"],
+ },
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_raw_response_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ response = await async_client.user.with_raw_response.save_onboarding_answers(
+ answers={},
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ async with async_client.user.with_streaming_response.save_onboarding_answers(
+ answers={},
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_survey_submit(self, async_client: AsyncStructify) -> None:
user = await async_client.user.survey_submit(
From 9ccbf40f09c05630249647b7f4a24ee75de96159 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 18:45:59 +0000
Subject: [PATCH 092/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 13 +-
.../resources/connectors/connectors.py | 99 ++----------
src/structify/resources/user/user.py | 128 ----------------
src/structify/types/__init__.py | 9 +-
src/structify/types/connector.py | 4 +
.../types/connector_update_params.py | 2 +
src/structify/types/datahub_progress.py | 23 ---
src/structify/types/exploration_progress.py | 15 --
.../types/explore_status_response.py | 15 ++
.../types/get_onboarding_answers_response.py | 10 --
src/structify/types/onboarding_answers.py | 23 ---
.../types/onboarding_answers_param.py | 26 ----
src/structify/types/phase_activity.py | 24 ---
.../types/save_onboarding_answers_response.py | 10 --
.../user_save_onboarding_answers_params.py | 13 --
tests/api_resources/test_connectors.py | 115 ++------------
tests/api_resources/test_user.py | 144 ------------------
18 files changed, 47 insertions(+), 634 deletions(-)
delete mode 100644 src/structify/types/datahub_progress.py
delete mode 100644 src/structify/types/exploration_progress.py
create mode 100644 src/structify/types/explore_status_response.py
delete mode 100644 src/structify/types/get_onboarding_answers_response.py
delete mode 100644 src/structify/types/onboarding_answers.py
delete mode 100644 src/structify/types/onboarding_answers_param.py
delete mode 100644 src/structify/types/phase_activity.py
delete mode 100644 src/structify/types/save_onboarding_answers_response.py
delete mode 100644 src/structify/types/user_save_onboarding_answers_params.py
diff --git a/.stats.yml b/.stats.yml
index 90e6e1219..641fb2fb2 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-29c9300e82024cc61290d30aa7ac019896b932a90ba4457df9c66aed0368d5d3.yml
-openapi_spec_hash: 4704e4a255a7a8be08dbdb46adb5ccb3
-config_hash: e0609ead5e3e0971211fd2441e2be818
+configured_endpoints: 251
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-1f7572604421e48e11f40908896f9b7f7d077e73193d8c9ba325c709b3b1b8f8.yml
+openapi_spec_hash: 7f417ecadbcbb7dde9b8620259fb28ec
+config_hash: 6e85cc97157c6ec93ae6393081d7dd2a
diff --git a/api.md b/api.md
index 855728067..618ea3143 100644
--- a/api.md
+++ b/api.md
@@ -19,13 +19,9 @@ Types:
```python
from structify.types import (
EnrichUserParams,
- GetOnboardingAnswersResponse,
JwtToAPITokenRequest,
- OnboardingAnswers,
RefreshSessionRequest,
RefreshSessionResponse,
- SaveOnboardingAnswersRequest,
- SaveOnboardingAnswersResponse,
SurveySubmissionRequest,
SurveySubmissionResponse,
TokenResponse,
@@ -40,10 +36,8 @@ Methods:
- client.user.update(\*\*params) -> User
- client.user.enrich(\*\*params) -> None
-- client.user.get_onboarding_answers() -> GetOnboardingAnswersResponse
- client.user.info() -> UserInfo
- client.user.refresh(\*\*params) -> RefreshSessionResponse
-- client.user.save_onboarding_answers(\*\*params) -> SaveOnboardingAnswersResponse
- client.user.survey_submit(\*\*params) -> SurveySubmissionResponse
- client.user.transactions() -> UserTransactionsResponse
- client.user.usage(\*\*params) -> UserUsageResponse
@@ -714,19 +708,17 @@ from structify.types import (
ConnectorWithSnippets,
CreateConnectorRequest,
CreateSecretRequest,
- DatahubProgress,
DeleteSchemaObjectRequest,
DeleteSchemaObjectResponse,
ExplorationPhaseID,
- ExplorationProgress,
ExplorationRun,
ExplorationRunsResponse,
ExplorationStatus,
ExploreConnectorRequest,
+ ExploreStatusResponse,
ExplorerChatResponse,
ListTablesResponse,
LlmInformationStore,
- PhaseActivity,
SchemaObjectID,
UpdateColumnRequest,
UpdateConnectorRequest,
@@ -757,9 +749,8 @@ Methods:
- client.connectors.explore(connector_id, \*\*params) -> ConnectorExploreResponse
- client.connectors.get(connector_id) -> ConnectorGetResponse
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
-- client.connectors.get_exploration_progress(run_id, \*, connector_id) -> ExplorationProgress
- client.connectors.get_exploration_runs(connector_id) -> ExplorationRunsResponse
-- client.connectors.get_exploration_status(connector_id) -> Optional[ExplorationRun]
+- client.connectors.get_exploration_status(connector_id) -> ExploreStatusResponse
- client.connectors.get_explorer_chat(connector_id, \*\*params) -> ExplorerChatResponse
- client.connectors.get_store(connector_id) -> ConnectorStoreResponse
- client.connectors.get_table_path(table_id) -> ConnectorTablePathResponse
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 41f1af838..919b5bb2c 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -71,14 +71,13 @@
)
from ..._base_client import AsyncPaginator, make_request_options
from ...types.connector import Connector
-from ...types.exploration_run import ExplorationRun
from ...types.connector_category import ConnectorCategory
-from ...types.exploration_progress import ExplorationProgress
from ...types.list_tables_response import ListTablesResponse
from ...types.update_table_response import UpdateTableResponse
from ...types.connector_get_response import ConnectorGetResponse
from ...types.connector_with_secrets import ConnectorWithSecrets
from ...types.explorer_chat_response import ExplorerChatResponse
+from ...types.explore_status_response import ExploreStatusResponse
from ...types.connector_store_response import ConnectorStoreResponse
from ...types.exploration_runs_response import ExplorationRunsResponse
from ...types.connector_explore_response import ConnectorExploreResponse
@@ -180,6 +179,7 @@ def update(
nango_connection_id: Optional[str] | Omit = omit,
oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
owner_user_id: Optional[str] | Omit = omit,
+ refresh_cron_schedule: Optional[str] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
user_ids: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -220,6 +220,7 @@ def update(
"nango_connection_id": nango_connection_id,
"oauth_scopes": oauth_scopes,
"owner_user_id": owner_user_id,
+ "refresh_cron_schedule": refresh_cron_schedule,
"team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
"user_ids": user_ids,
@@ -844,42 +845,6 @@ def get_clarification_requests(
cast_to=ConnectorGetClarificationRequestsResponse,
)
- def get_exploration_progress(
- self,
- run_id: str,
- *,
- connector_id: str,
- # 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,
- ) -> ExplorationProgress:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return self._get(
- path_template(
- "/connectors/{connector_id}/explore/runs/{run_id}/progress", connector_id=connector_id, run_id=run_id
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExplorationProgress,
- )
-
def get_exploration_runs(
self,
connector_id: str,
@@ -923,7 +888,7 @@ def get_exploration_status(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Optional[ExplorationRun]:
+ ) -> ExploreStatusResponse:
"""
Args:
extra_headers: Send extra headers
@@ -941,7 +906,7 @@ def get_exploration_status(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExplorationRun,
+ cast_to=ExploreStatusResponse,
)
def get_explorer_chat(
@@ -1454,6 +1419,7 @@ async def update(
nango_connection_id: Optional[str] | Omit = omit,
oauth_scopes: Optional[SequenceNotStr[Optional[str]]] | Omit = omit,
owner_user_id: Optional[str] | Omit = omit,
+ refresh_cron_schedule: Optional[str] | Omit = omit,
team_visibility: Optional[Literal["Team", "Private"]] | Omit = omit,
usage_snippet_override: Optional[str] | Omit = omit,
user_ids: Optional[SequenceNotStr[str]] | Omit = omit,
@@ -1494,6 +1460,7 @@ async def update(
"nango_connection_id": nango_connection_id,
"oauth_scopes": oauth_scopes,
"owner_user_id": owner_user_id,
+ "refresh_cron_schedule": refresh_cron_schedule,
"team_visibility": team_visibility,
"usage_snippet_override": usage_snippet_override,
"user_ids": user_ids,
@@ -2118,42 +2085,6 @@ async def get_clarification_requests(
cast_to=ConnectorGetClarificationRequestsResponse,
)
- async def get_exploration_progress(
- self,
- run_id: str,
- *,
- connector_id: str,
- # 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,
- ) -> ExplorationProgress:
- """
- Args:
- 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
- """
- if not connector_id:
- raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
- if not run_id:
- raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
- return await self._get(
- path_template(
- "/connectors/{connector_id}/explore/runs/{run_id}/progress", connector_id=connector_id, run_id=run_id
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=ExplorationProgress,
- )
-
async def get_exploration_runs(
self,
connector_id: str,
@@ -2197,7 +2128,7 @@ async def get_exploration_status(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> Optional[ExplorationRun]:
+ ) -> ExploreStatusResponse:
"""
Args:
extra_headers: Send extra headers
@@ -2215,7 +2146,7 @@ async def get_exploration_status(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExplorationRun,
+ cast_to=ExploreStatusResponse,
)
async def get_explorer_chat(
@@ -2690,9 +2621,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_clarification_requests = to_raw_response_wrapper(
connectors.get_clarification_requests,
)
- self.get_exploration_progress = to_raw_response_wrapper(
- connectors.get_exploration_progress,
- )
self.get_exploration_runs = to_raw_response_wrapper(
connectors.get_exploration_runs,
)
@@ -2782,9 +2710,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_clarification_requests = async_to_raw_response_wrapper(
connectors.get_clarification_requests,
)
- self.get_exploration_progress = async_to_raw_response_wrapper(
- connectors.get_exploration_progress,
- )
self.get_exploration_runs = async_to_raw_response_wrapper(
connectors.get_exploration_runs,
)
@@ -2874,9 +2799,6 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get_clarification_requests = to_streamed_response_wrapper(
connectors.get_clarification_requests,
)
- self.get_exploration_progress = to_streamed_response_wrapper(
- connectors.get_exploration_progress,
- )
self.get_exploration_runs = to_streamed_response_wrapper(
connectors.get_exploration_runs,
)
@@ -2966,9 +2888,6 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get_clarification_requests = async_to_streamed_response_wrapper(
connectors.get_clarification_requests,
)
- self.get_exploration_progress = async_to_streamed_response_wrapper(
- connectors.get_exploration_progress,
- )
self.get_exploration_runs = async_to_streamed_response_wrapper(
connectors.get_exploration_runs,
)
diff --git a/src/structify/resources/user/user.py b/src/structify/resources/user/user.py
index 9d97998a5..354969852 100644
--- a/src/structify/resources/user/user.py
+++ b/src/structify/resources/user/user.py
@@ -20,7 +20,6 @@
user_update_params,
user_refresh_params,
user_survey_submit_params,
- user_save_onboarding_answers_params,
)
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from ..._utils import maybe_transform, async_maybe_transform
@@ -44,12 +43,9 @@
from ...types.user_info import UserInfo
from ...types.admin.user import User
from ...types.user_usage_response import UserUsageResponse
-from ...types.onboarding_answers_param import OnboardingAnswersParam
from ...types.refresh_session_response import RefreshSessionResponse
from ...types.survey_submission_response import SurveySubmissionResponse
from ...types.user_transactions_response import UserTransactionsResponse
-from ...types.get_onboarding_answers_response import GetOnboardingAnswersResponse
-from ...types.save_onboarding_answers_response import SaveOnboardingAnswersResponse
__all__ = ["UserResource", "AsyncUserResource"]
@@ -153,24 +149,6 @@ def enrich(
cast_to=NoneType,
)
- def get_onboarding_answers(
- self,
- *,
- # 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,
- ) -> GetOnboardingAnswersResponse:
- return self._get(
- "/user/onboarding/answers",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=GetOnboardingAnswersResponse,
- )
-
def info(
self,
*,
@@ -231,38 +209,6 @@ def refresh(
cast_to=RefreshSessionResponse,
)
- def save_onboarding_answers(
- self,
- *,
- answers: OnboardingAnswersParam,
- # 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,
- ) -> SaveOnboardingAnswersResponse:
- """
- Args:
- 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
- """
- return self._put(
- "/user/onboarding/answers",
- body=maybe_transform(
- {"answers": answers}, user_save_onboarding_answers_params.UserSaveOnboardingAnswersParams
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=SaveOnboardingAnswersResponse,
- )
-
def survey_submit(
self,
*,
@@ -450,24 +396,6 @@ async def enrich(
cast_to=NoneType,
)
- async def get_onboarding_answers(
- self,
- *,
- # 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,
- ) -> GetOnboardingAnswersResponse:
- return await self._get(
- "/user/onboarding/answers",
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=GetOnboardingAnswersResponse,
- )
-
async def info(
self,
*,
@@ -528,38 +456,6 @@ async def refresh(
cast_to=RefreshSessionResponse,
)
- async def save_onboarding_answers(
- self,
- *,
- answers: OnboardingAnswersParam,
- # 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,
- ) -> SaveOnboardingAnswersResponse:
- """
- Args:
- 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
- """
- return await self._put(
- "/user/onboarding/answers",
- body=await async_maybe_transform(
- {"answers": answers}, user_save_onboarding_answers_params.UserSaveOnboardingAnswersParams
- ),
- options=make_request_options(
- extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
- ),
- cast_to=SaveOnboardingAnswersResponse,
- )
-
async def survey_submit(
self,
*,
@@ -658,18 +554,12 @@ def __init__(self, user: UserResource) -> None:
self.enrich = to_raw_response_wrapper(
user.enrich,
)
- self.get_onboarding_answers = to_raw_response_wrapper(
- user.get_onboarding_answers,
- )
self.info = to_raw_response_wrapper(
user.info,
)
self.refresh = to_raw_response_wrapper(
user.refresh,
)
- self.save_onboarding_answers = to_raw_response_wrapper(
- user.save_onboarding_answers,
- )
self.survey_submit = to_raw_response_wrapper(
user.survey_submit,
)
@@ -700,18 +590,12 @@ def __init__(self, user: AsyncUserResource) -> None:
self.enrich = async_to_raw_response_wrapper(
user.enrich,
)
- self.get_onboarding_answers = async_to_raw_response_wrapper(
- user.get_onboarding_answers,
- )
self.info = async_to_raw_response_wrapper(
user.info,
)
self.refresh = async_to_raw_response_wrapper(
user.refresh,
)
- self.save_onboarding_answers = async_to_raw_response_wrapper(
- user.save_onboarding_answers,
- )
self.survey_submit = async_to_raw_response_wrapper(
user.survey_submit,
)
@@ -742,18 +626,12 @@ def __init__(self, user: UserResource) -> None:
self.enrich = to_streamed_response_wrapper(
user.enrich,
)
- self.get_onboarding_answers = to_streamed_response_wrapper(
- user.get_onboarding_answers,
- )
self.info = to_streamed_response_wrapper(
user.info,
)
self.refresh = to_streamed_response_wrapper(
user.refresh,
)
- self.save_onboarding_answers = to_streamed_response_wrapper(
- user.save_onboarding_answers,
- )
self.survey_submit = to_streamed_response_wrapper(
user.survey_submit,
)
@@ -784,18 +662,12 @@ def __init__(self, user: AsyncUserResource) -> None:
self.enrich = async_to_streamed_response_wrapper(
user.enrich,
)
- self.get_onboarding_answers = async_to_streamed_response_wrapper(
- user.get_onboarding_answers,
- )
self.info = async_to_streamed_response_wrapper(
user.info,
)
self.refresh = async_to_streamed_response_wrapper(
user.refresh,
)
- self.save_onboarding_answers = async_to_streamed_response_wrapper(
- user.save_onboarding_answers,
- )
self.survey_submit = async_to_streamed_response_wrapper(
user.survey_submit,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index 38bb16c7b..f870fc69a 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -38,7 +38,6 @@
from .dashboard_page import DashboardPage as DashboardPage
from .dashboard_spec import DashboardSpec as DashboardSpec
from .job_event_body import JobEventBody as JobEventBody
-from .phase_activity import PhaseActivity as PhaseActivity
from .project_member import ProjectMember as ProjectMember
from .strategy_param import StrategyParam as StrategyParam
from .team_with_role import TeamWithRole as TeamWithRole
@@ -59,7 +58,6 @@
from .viz_param_param import VizParamParam as VizParamParam
from .viz_query_param import VizQueryParam as VizQueryParam
from .chat_copy_params import ChatCopyParams as ChatCopyParams
-from .datahub_progress import DatahubProgress as DatahubProgress
from .job_get_response import JobGetResponse as JobGetResponse
from .save_requirement import SaveRequirement as SaveRequirement
from .viz_date_control import VizDateControl as VizDateControl
@@ -84,7 +82,6 @@
from .entity_view_params import EntityViewParams as EntityViewParams
from .exploration_status import ExplorationStatus as ExplorationStatus
from .merge_config_param import MergeConfigParam as MergeConfigParam
-from .onboarding_answers import OnboardingAnswers as OnboardingAnswers
from .parquet_edit_param import ParquetEditParam as ParquetEditParam
from .project_visibility import ProjectVisibility as ProjectVisibility
from .relationship_param import RelationshipParam as RelationshipParam
@@ -130,7 +127,6 @@
from .entity_verify_params import EntityVerifyParams as EntityVerifyParams
from .entity_view_response import EntityViewResponse as EntityViewResponse
from .exploration_phase_id import ExplorationPhaseID as ExplorationPhaseID
-from .exploration_progress import ExplorationProgress as ExplorationProgress
from .list_tables_response import ListTablesResponse as ListTablesResponse
from .project_get_response import ProjectGetResponse as ProjectGetResponse
from .scrape_list_response import ScrapeListResponse as ScrapeListResponse
@@ -189,6 +185,7 @@
from .entity_add_batch_params import EntityAddBatchParams as EntityAddBatchParams
from .entity_list_jobs_params import EntityListJobsParams as EntityListJobsParams
from .entity_summarize_params import EntitySummarizeParams as EntitySummarizeParams
+from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
from .template_question_param import TemplateQuestionParam as TemplateQuestionParam
from .trigger_review_response import TriggerReviewResponse as TriggerReviewResponse
@@ -203,7 +200,6 @@
from .entity_get_merges_params import EntityGetMergesParams as EntityGetMergesParams
from .list_dashboards_response import ListDashboardsResponse as ListDashboardsResponse
from .match_create_jobs_params import MatchCreateJobsParams as MatchCreateJobsParams
-from .onboarding_answers_param import OnboardingAnswersParam as OnboardingAnswersParam
from .refresh_session_response import RefreshSessionResponse as RefreshSessionResponse
from .session_kill_jobs_params import SessionKillJobsParams as SessionKillJobsParams
from .simulate_prompt_response import SimulatePromptResponse as SimulatePromptResponse
@@ -324,7 +320,6 @@
from .chat_upload_input_file_response import ChatUploadInputFileResponse as ChatUploadInputFileResponse
from .connector_catalog_list_response import ConnectorCatalogListResponse as ConnectorCatalogListResponse
from .entity_update_property_response import EntityUpdatePropertyResponse as EntityUpdatePropertyResponse
-from .get_onboarding_answers_response import GetOnboardingAnswersResponse as GetOnboardingAnswersResponse
from .session_edit_node_output_params import SessionEditNodeOutputParams as SessionEditNodeOutputParams
from .workflow_schedule_create_params import WorkflowScheduleCreateParams as WorkflowScheduleCreateParams
from .workflow_schedule_update_params import WorkflowScheduleUpdateParams as WorkflowScheduleUpdateParams
@@ -335,7 +330,6 @@
from .entity_get_local_subgraph_params import EntityGetLocalSubgraphParams as EntityGetLocalSubgraphParams
from .nango_list_integrations_response import NangoListIntegrationsResponse as NangoListIntegrationsResponse
from .project_collaborator_input_param import ProjectCollaboratorInputParam as ProjectCollaboratorInputParam
-from .save_onboarding_answers_response import SaveOnboardingAnswersResponse as SaveOnboardingAnswersResponse
from .connector_auth_method_with_fields import ConnectorAuthMethodWithFields as ConnectorAuthMethodWithFields
from .dataset_reorder_properties_params import DatasetReorderPropertiesParams as DatasetReorderPropertiesParams
from .dataset_set_primary_column_params import DatasetSetPrimaryColumnParams as DatasetSetPrimaryColumnParams
@@ -363,7 +357,6 @@
from .session_request_confirmation_params import SessionRequestConfirmationParams as SessionRequestConfirmationParams
from .session_update_node_progress_params import SessionUpdateNodeProgressParams as SessionUpdateNodeProgressParams
from .structure_enhance_property_response import StructureEnhancePropertyResponse as StructureEnhancePropertyResponse
-from .user_save_onboarding_answers_params import UserSaveOnboardingAnswersParams as UserSaveOnboardingAnswersParams
from .connector_add_schema_object_response import ConnectorAddSchemaObjectResponse as ConnectorAddSchemaObjectResponse
from .dataset_enrichment_progress_response import DatasetEnrichmentProgressResponse as DatasetEnrichmentProgressResponse
from .structure_find_relationship_response import StructureFindRelationshipResponse as StructureFindRelationshipResponse
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 32c1bae30..63f742487 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -48,4 +48,8 @@ class Connector(BaseModel):
oauth_scopes: Optional[List[Optional[str]]] = None
+ refresh_cron_schedule: Optional[str] = None
+
+ refresh_next_run_at: Optional[datetime] = None
+
usage_snippet_override: Optional[str] = None
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index f9d31b52c..af460319e 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -37,6 +37,8 @@ class ConnectorUpdateParams(TypedDict, total=False):
owner_user_id: Optional[str]
+ refresh_cron_schedule: Optional[str]
+
team_visibility: Optional[Literal["Team", "Private"]]
usage_snippet_override: Optional[str]
diff --git a/src/structify/types/datahub_progress.py b/src/structify/types/datahub_progress.py
deleted file mode 100644
index 7b4561117..000000000
--- a/src/structify/types/datahub_progress.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing_extensions import Literal
-
-from .._models import BaseModel
-
-__all__ = ["DatahubProgress"]
-
-
-class DatahubProgress(BaseModel):
- databases_created: int
-
- job_id: str
-
- job_status: Literal["Queued", "Running", "Completed", "Failed"]
-
- pages_fetched: int
-
- schemas_created: int
-
- tables_processed: int
-
- total_datasets: int
diff --git a/src/structify/types/exploration_progress.py b/src/structify/types/exploration_progress.py
deleted file mode 100644
index 2b3d4f515..000000000
--- a/src/structify/types/exploration_progress.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from .._models import BaseModel
-from .phase_activity import PhaseActivity
-from .datahub_progress import DatahubProgress
-
-__all__ = ["ExplorationProgress"]
-
-
-class ExplorationProgress(BaseModel):
- phases: List[PhaseActivity]
-
- datahub: Optional[DatahubProgress] = None
diff --git a/src/structify/types/explore_status_response.py b/src/structify/types/explore_status_response.py
new file mode 100644
index 000000000..4275c265a
--- /dev/null
+++ b/src/structify/types/explore_status_response.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from .._models import BaseModel
+from .exploration_status import ExplorationStatus
+
+__all__ = ["ExploreStatusResponse"]
+
+
+class ExploreStatusResponse(BaseModel):
+ status: ExplorationStatus
+
+ started_at: Optional[datetime] = None
diff --git a/src/structify/types/get_onboarding_answers_response.py b/src/structify/types/get_onboarding_answers_response.py
deleted file mode 100644
index cada36acc..000000000
--- a/src/structify/types/get_onboarding_answers_response.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .._models import BaseModel
-from .onboarding_answers import OnboardingAnswers
-
-__all__ = ["GetOnboardingAnswersResponse"]
-
-
-class GetOnboardingAnswersResponse(BaseModel):
- answers: OnboardingAnswers
diff --git a/src/structify/types/onboarding_answers.py b/src/structify/types/onboarding_answers.py
deleted file mode 100644
index d3d0be2a2..000000000
--- a/src/structify/types/onboarding_answers.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import List, Optional
-
-from .._models import BaseModel
-
-__all__ = ["OnboardingAnswers"]
-
-
-class OnboardingAnswers(BaseModel):
- company_name: Optional[str] = None
-
- connected_connector_ids: Optional[List[str]] = None
-
- full_name: Optional[str] = None
-
- primary_goal: Optional[str] = None
-
- recommended_template_id: Optional[str] = None
-
- role: Optional[str] = None
-
- systems_to_connect: Optional[List[str]] = None
diff --git a/src/structify/types/onboarding_answers_param.py b/src/structify/types/onboarding_answers_param.py
deleted file mode 100644
index b3e43f9f8..000000000
--- a/src/structify/types/onboarding_answers_param.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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
-
-from .._types import SequenceNotStr
-
-__all__ = ["OnboardingAnswersParam"]
-
-
-class OnboardingAnswersParam(TypedDict, total=False):
- company_name: Optional[str]
-
- connected_connector_ids: Optional[SequenceNotStr[str]]
-
- full_name: Optional[str]
-
- primary_goal: Optional[str]
-
- recommended_template_id: Optional[str]
-
- role: Optional[str]
-
- systems_to_connect: Optional[SequenceNotStr[str]]
diff --git a/src/structify/types/phase_activity.py b/src/structify/types/phase_activity.py
deleted file mode 100644
index 63e43ac12..000000000
--- a/src/structify/types/phase_activity.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-from typing_extensions import Literal
-
-from .._models import BaseModel
-from .exploration_phase_id import ExplorationPhaseID
-
-__all__ = ["PhaseActivity"]
-
-
-class PhaseActivity(BaseModel):
- job_id: str
-
- phase_id: ExplorationPhaseID
- """Identifies the phase of connector exploration
-
- This enum is used to track which phase of exploration a chat session belongs to.
- It's stored as JSONB in the database to allow for flexible phase identification.
- """
-
- status: Literal["Queued", "Running", "Completed", "Failed"]
-
- chat_id: Optional[str] = None
diff --git a/src/structify/types/save_onboarding_answers_response.py b/src/structify/types/save_onboarding_answers_response.py
deleted file mode 100644
index 03ee078f3..000000000
--- a/src/structify/types/save_onboarding_answers_response.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from .._models import BaseModel
-from .onboarding_answers import OnboardingAnswers
-
-__all__ = ["SaveOnboardingAnswersResponse"]
-
-
-class SaveOnboardingAnswersResponse(BaseModel):
- answers: OnboardingAnswers
diff --git a/src/structify/types/user_save_onboarding_answers_params.py b/src/structify/types/user_save_onboarding_answers_params.py
deleted file mode 100644
index 4689e70ae..000000000
--- a/src/structify/types/user_save_onboarding_answers_params.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from __future__ import annotations
-
-from typing_extensions import Required, TypedDict
-
-from .onboarding_answers_param import OnboardingAnswersParam
-
-__all__ = ["UserSaveOnboardingAnswersParams"]
-
-
-class UserSaveOnboardingAnswersParams(TypedDict, total=False):
- answers: Required[OnboardingAnswersParam]
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index df8f6815f..134428572 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import os
-from typing import Any, Optional, cast
+from typing import Any, cast
import httpx
import pytest
@@ -13,13 +13,12 @@
from tests.utils import assert_matches_type
from structify.types import (
Connector,
- ExplorationRun,
ListTablesResponse,
- ExplorationProgress,
UpdateTableResponse,
ConnectorGetResponse,
ConnectorWithSecrets,
ExplorerChatResponse,
+ ExploreStatusResponse,
ConnectorStoreResponse,
ExplorationRunsResponse,
ConnectorExploreResponse,
@@ -112,6 +111,7 @@ def test_method_update_with_all_params(self, client: Structify) -> None:
nango_connection_id="nango_connection_id",
oauth_scopes=["string"],
owner_user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ refresh_cron_schedule="refresh_cron_schedule",
team_visibility="Team",
usage_snippet_override="usage_snippet_override",
user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
@@ -953,54 +953,6 @@ def test_path_params_get_clarification_requests(self, client: Structify) -> None
"",
)
- @parametrize
- def test_method_get_exploration_progress(self, client: Structify) -> None:
- connector = client.connectors.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(ExplorationProgress, connector, path=["response"])
-
- @parametrize
- def test_raw_response_get_exploration_progress(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- connector = response.parse()
- assert_matches_type(ExplorationProgress, connector, path=["response"])
-
- @parametrize
- def test_streaming_response_get_exploration_progress(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- connector = response.parse()
- assert_matches_type(ExplorationProgress, connector, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- def test_path_params_get_exploration_progress(self, client: Structify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- client.connectors.with_raw_response.get_exploration_progress(
- run_id="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
@parametrize
def test_method_get_exploration_runs(self, client: Structify) -> None:
connector = client.connectors.get_exploration_runs(
@@ -1044,7 +996,7 @@ def test_method_get_exploration_status(self, client: Structify) -> None:
connector = client.connectors.get_exploration_status(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+ assert_matches_type(ExploreStatusResponse, connector, path=["response"])
@parametrize
def test_raw_response_get_exploration_status(self, client: Structify) -> None:
@@ -1055,7 +1007,7 @@ def test_raw_response_get_exploration_status(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+ assert_matches_type(ExploreStatusResponse, connector, path=["response"])
@parametrize
def test_streaming_response_get_exploration_status(self, client: Structify) -> None:
@@ -1066,7 +1018,7 @@ def test_streaming_response_get_exploration_status(self, client: Structify) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+ assert_matches_type(ExploreStatusResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -1616,6 +1568,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncStructify)
nango_connection_id="nango_connection_id",
oauth_scopes=["string"],
owner_user_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ refresh_cron_schedule="refresh_cron_schedule",
team_visibility="Team",
usage_snippet_override="usage_snippet_override",
user_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"],
@@ -2463,54 +2416,6 @@ async def test_path_params_get_clarification_requests(self, async_client: AsyncS
"",
)
- @parametrize
- async def test_method_get_exploration_progress(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
- assert_matches_type(ExplorationProgress, connector, path=["response"])
-
- @parametrize
- async def test_raw_response_get_exploration_progress(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- connector = await response.parse()
- assert_matches_type(ExplorationProgress, connector, path=["response"])
-
- @parametrize
- async def test_streaming_response_get_exploration_progress(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- connector = await response.parse()
- assert_matches_type(ExplorationProgress, connector, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
- @parametrize
- async def test_path_params_get_exploration_progress(self, async_client: AsyncStructify) -> None:
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.get_exploration_progress(
- run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- connector_id="",
- )
-
- with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
- await async_client.connectors.with_raw_response.get_exploration_progress(
- run_id="",
- connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
- )
-
@parametrize
async def test_method_get_exploration_runs(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.get_exploration_runs(
@@ -2554,7 +2459,7 @@ async def test_method_get_exploration_status(self, async_client: AsyncStructify)
connector = await async_client.connectors.get_exploration_status(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+ assert_matches_type(ExploreStatusResponse, connector, path=["response"])
@parametrize
async def test_raw_response_get_exploration_status(self, async_client: AsyncStructify) -> None:
@@ -2565,7 +2470,7 @@ async def test_raw_response_get_exploration_status(self, async_client: AsyncStru
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+ assert_matches_type(ExploreStatusResponse, connector, path=["response"])
@parametrize
async def test_streaming_response_get_exploration_status(self, async_client: AsyncStructify) -> None:
@@ -2576,7 +2481,7 @@ async def test_streaming_response_get_exploration_status(self, async_client: Asy
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+ assert_matches_type(ExploreStatusResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_user.py b/tests/api_resources/test_user.py
index 063cd0063..57a4dcc64 100644
--- a/tests/api_resources/test_user.py
+++ b/tests/api_resources/test_user.py
@@ -15,8 +15,6 @@
RefreshSessionResponse,
SurveySubmissionResponse,
UserTransactionsResponse,
- GetOnboardingAnswersResponse,
- SaveOnboardingAnswersResponse,
)
from structify.types.admin import User
@@ -119,31 +117,6 @@ def test_streaming_response_enrich(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
- @parametrize
- def test_method_get_onboarding_answers(self, client: Structify) -> None:
- user = client.user.get_onboarding_answers()
- assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- def test_raw_response_get_onboarding_answers(self, client: Structify) -> None:
- response = client.user.with_raw_response.get_onboarding_answers()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- user = response.parse()
- assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- def test_streaming_response_get_onboarding_answers(self, client: Structify) -> None:
- with client.user.with_streaming_response.get_onboarding_answers() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- user = response.parse()
- assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@parametrize
def test_method_info(self, client: Structify) -> None:
user = client.user.info()
@@ -203,52 +176,6 @@ def test_streaming_response_refresh(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
- @parametrize
- def test_method_save_onboarding_answers(self, client: Structify) -> None:
- user = client.user.save_onboarding_answers(
- answers={},
- )
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- def test_method_save_onboarding_answers_with_all_params(self, client: Structify) -> None:
- user = client.user.save_onboarding_answers(
- answers={
- "company_name": "company_name",
- "connected_connector_ids": ["string"],
- "full_name": "full_name",
- "primary_goal": "primary_goal",
- "recommended_template_id": "recommended_template_id",
- "role": "role",
- "systems_to_connect": ["string"],
- },
- )
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- def test_raw_response_save_onboarding_answers(self, client: Structify) -> None:
- response = client.user.with_raw_response.save_onboarding_answers(
- answers={},
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- user = response.parse()
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- def test_streaming_response_save_onboarding_answers(self, client: Structify) -> None:
- with client.user.with_streaming_response.save_onboarding_answers(
- answers={},
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- user = response.parse()
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@parametrize
def test_method_survey_submit(self, client: Structify) -> None:
user = client.user.survey_submit(
@@ -436,31 +363,6 @@ async def test_streaming_response_enrich(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
- @parametrize
- async def test_method_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
- user = await async_client.user.get_onboarding_answers()
- assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- async def test_raw_response_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
- response = await async_client.user.with_raw_response.get_onboarding_answers()
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- user = await response.parse()
- assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- async def test_streaming_response_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
- async with async_client.user.with_streaming_response.get_onboarding_answers() as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- user = await response.parse()
- assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@parametrize
async def test_method_info(self, async_client: AsyncStructify) -> None:
user = await async_client.user.info()
@@ -520,52 +422,6 @@ async def test_streaming_response_refresh(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
- @parametrize
- async def test_method_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
- user = await async_client.user.save_onboarding_answers(
- answers={},
- )
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- async def test_method_save_onboarding_answers_with_all_params(self, async_client: AsyncStructify) -> None:
- user = await async_client.user.save_onboarding_answers(
- answers={
- "company_name": "company_name",
- "connected_connector_ids": ["string"],
- "full_name": "full_name",
- "primary_goal": "primary_goal",
- "recommended_template_id": "recommended_template_id",
- "role": "role",
- "systems_to_connect": ["string"],
- },
- )
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- async def test_raw_response_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
- response = await async_client.user.with_raw_response.save_onboarding_answers(
- answers={},
- )
-
- assert response.is_closed is True
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
- user = await response.parse()
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- @parametrize
- async def test_streaming_response_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
- async with async_client.user.with_streaming_response.save_onboarding_answers(
- answers={},
- ) as response:
- assert not response.is_closed
- assert response.http_request.headers.get("X-Stainless-Lang") == "python"
-
- user = await response.parse()
- assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
-
- assert cast(Any, response.is_closed) is True
-
@parametrize
async def test_method_survey_submit(self, async_client: AsyncStructify) -> None:
user = await async_client.user.survey_submit(
From 7300ef146472dae2bc013c407e3dc21806adb8ba Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 21:22:28 +0000
Subject: [PATCH 093/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 19 +-
src/structify/resources/admin/connector.py | 18 +-
.../resources/connectors/connectors.py | 157 +++++++++++---
src/structify/resources/user/user.py | 128 +++++++++++
src/structify/types/__init__.py | 11 +-
src/structify/types/admin/__init__.py | 4 +-
...esponse.py => connector_clone_response.py} | 4 +-
.../connector_set_datahub_config_params.py | 2 +-
src/structify/types/connector.py | 2 +-
.../types/connector_update_params.py | 2 +-
src/structify/types/datahub_progress.py | 23 ++
.../types/{admin => }/datahub_secret_map.py | 0
.../{admin => }/datahub_secret_map_param.py | 0
src/structify/types/exploration_progress.py | 15 ++
.../types/explore_status_response.py | 15 --
.../types/get_onboarding_answers_response.py | 10 +
src/structify/types/onboarding_answers.py | 23 ++
.../types/onboarding_answers_param.py | 26 +++
src/structify/types/phase_activity.py | 24 ++
.../types/save_onboarding_answers_response.py | 10 +
.../user_save_onboarding_answers_params.py | 13 ++
tests/api_resources/admin/test_connector.py | 14 +-
tests/api_resources/test_connectors.py | 205 +++++++++++++-----
tests/api_resources/test_user.py | 144 ++++++++++++
25 files changed, 736 insertions(+), 141 deletions(-)
rename src/structify/types/admin/{clone_connectors_response.py => connector_clone_response.py} (72%)
create mode 100644 src/structify/types/datahub_progress.py
rename src/structify/types/{admin => }/datahub_secret_map.py (100%)
rename src/structify/types/{admin => }/datahub_secret_map_param.py (100%)
create mode 100644 src/structify/types/exploration_progress.py
delete mode 100644 src/structify/types/explore_status_response.py
create mode 100644 src/structify/types/get_onboarding_answers_response.py
create mode 100644 src/structify/types/onboarding_answers.py
create mode 100644 src/structify/types/onboarding_answers_param.py
create mode 100644 src/structify/types/phase_activity.py
create mode 100644 src/structify/types/save_onboarding_answers_response.py
create mode 100644 src/structify/types/user_save_onboarding_answers_params.py
diff --git a/.stats.yml b/.stats.yml
index 641fb2fb2..c6069314d 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 251
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-1f7572604421e48e11f40908896f9b7f7d077e73193d8c9ba325c709b3b1b8f8.yml
-openapi_spec_hash: 7f417ecadbcbb7dde9b8620259fb28ec
-config_hash: 6e85cc97157c6ec93ae6393081d7dd2a
+configured_endpoints: 254
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c7eee6a00ed99a6b5fcbd38a11eef4eb3f1889d40e801d47abddf53e0c59e94a.yml
+openapi_spec_hash: e6a3b10a0046edf68b1db030a8db0ad6
+config_hash: de97841de67eb76e2acd3a5a6b67a26d
diff --git a/api.md b/api.md
index 618ea3143..c1d1335c2 100644
--- a/api.md
+++ b/api.md
@@ -19,9 +19,13 @@ Types:
```python
from structify.types import (
EnrichUserParams,
+ GetOnboardingAnswersResponse,
JwtToAPITokenRequest,
+ OnboardingAnswers,
RefreshSessionRequest,
RefreshSessionResponse,
+ SaveOnboardingAnswersRequest,
+ SaveOnboardingAnswersResponse,
SurveySubmissionRequest,
SurveySubmissionResponse,
TokenResponse,
@@ -36,8 +40,10 @@ Methods:
- client.user.update(\*\*params) -> User
- client.user.enrich(\*\*params) -> None
+- client.user.get_onboarding_answers() -> GetOnboardingAnswersResponse
- client.user.info() -> UserInfo
- client.user.refresh(\*\*params) -> RefreshSessionResponse
+- client.user.save_onboarding_answers(\*\*params) -> SaveOnboardingAnswersResponse
- client.user.survey_submit(\*\*params) -> SurveySubmissionResponse
- client.user.transactions() -> UserTransactionsResponse
- client.user.usage(\*\*params) -> UserUsageResponse
@@ -438,17 +444,16 @@ from structify.types.admin import (
AdminListConnectorsResponse,
CloneConnectorItem,
CloneConnectorsRequest,
- CloneConnectorsResponse,
DatahubIngestionKey,
DatahubIngestionType,
- DatahubSecretMap,
SetDatahubConfigRequest,
+ ConnectorCloneResponse,
)
```
Methods:
-- client.admin.connector.clone(\*\*params) -> CloneConnectorsResponse
+- client.admin.connector.clone(\*\*params) -> ConnectorCloneResponse
- client.admin.connector.list_team_connectors(team_id) -> AdminListConnectorsResponse
- client.admin.connector.set_datahub_config(\*\*params) -> Connector
@@ -708,17 +713,20 @@ from structify.types import (
ConnectorWithSnippets,
CreateConnectorRequest,
CreateSecretRequest,
+ DatahubProgress,
+ DatahubSecretMap,
DeleteSchemaObjectRequest,
DeleteSchemaObjectResponse,
ExplorationPhaseID,
+ ExplorationProgress,
ExplorationRun,
ExplorationRunsResponse,
ExplorationStatus,
ExploreConnectorRequest,
- ExploreStatusResponse,
ExplorerChatResponse,
ListTablesResponse,
LlmInformationStore,
+ PhaseActivity,
SchemaObjectID,
UpdateColumnRequest,
UpdateConnectorRequest,
@@ -748,9 +756,10 @@ Methods:
- client.connectors.download_datahub_artifact(kind, \*, connector_id, \*\*params) -> BinaryAPIResponse
- client.connectors.explore(connector_id, \*\*params) -> ConnectorExploreResponse
- client.connectors.get(connector_id) -> ConnectorGetResponse
+- client.connectors.get_active_exploration_run(connector_id) -> Optional[ExplorationRun]
- client.connectors.get_clarification_requests(connector_id) -> ConnectorGetClarificationRequestsResponse
+- client.connectors.get_exploration_run_progress(run_id, \*, connector_id) -> ExplorationProgress
- client.connectors.get_exploration_runs(connector_id) -> ExplorationRunsResponse
-- client.connectors.get_exploration_status(connector_id) -> ExploreStatusResponse
- client.connectors.get_explorer_chat(connector_id, \*\*params) -> ExplorerChatResponse
- client.connectors.get_store(connector_id) -> ConnectorStoreResponse
- client.connectors.get_table_path(table_id) -> ConnectorTablePathResponse
diff --git a/src/structify/resources/admin/connector.py b/src/structify/resources/admin/connector.py
index ad0a27d0a..0c05e7d0b 100644
--- a/src/structify/resources/admin/connector.py
+++ b/src/structify/resources/admin/connector.py
@@ -16,16 +16,12 @@
async_to_raw_response_wrapper,
async_to_streamed_response_wrapper,
)
-from ...types.admin import (
- DatahubIngestionType,
- connector_clone_params,
- connector_set_datahub_config_params,
-)
+from ...types.admin import DatahubIngestionType, connector_clone_params, connector_set_datahub_config_params
from ..._base_client import make_request_options
from ...types.connector import Connector
+from ...types.datahub_secret_map_param import DatahubSecretMapParam
from ...types.admin.datahub_ingestion_type import DatahubIngestionType
-from ...types.admin.datahub_secret_map_param import DatahubSecretMapParam
-from ...types.admin.clone_connectors_response import CloneConnectorsResponse
+from ...types.admin.connector_clone_response import ConnectorCloneResponse
from ...types.admin.clone_connector_item_param import CloneConnectorItemParam
from ...types.admin.admin_list_connectors_response import AdminListConnectorsResponse
@@ -67,7 +63,7 @@ def clone(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CloneConnectorsResponse:
+ ) -> ConnectorCloneResponse:
"""
Args:
extra_headers: Send extra headers
@@ -92,7 +88,7 @@ def clone(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=CloneConnectorsResponse,
+ cast_to=ConnectorCloneResponse,
)
def list_team_connectors(
@@ -204,7 +200,7 @@ async def clone(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> CloneConnectorsResponse:
+ ) -> ConnectorCloneResponse:
"""
Args:
extra_headers: Send extra headers
@@ -229,7 +225,7 @@ async def clone(
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=CloneConnectorsResponse,
+ cast_to=ConnectorCloneResponse,
)
async def list_team_connectors(
diff --git a/src/structify/resources/connectors/connectors.py b/src/structify/resources/connectors/connectors.py
index 919b5bb2c..b169f12fb 100644
--- a/src/structify/resources/connectors/connectors.py
+++ b/src/structify/resources/connectors/connectors.py
@@ -71,20 +71,21 @@
)
from ..._base_client import AsyncPaginator, make_request_options
from ...types.connector import Connector
+from ...types.exploration_run import ExplorationRun
from ...types.connector_category import ConnectorCategory
+from ...types.exploration_progress import ExplorationProgress
from ...types.list_tables_response import ListTablesResponse
from ...types.update_table_response import UpdateTableResponse
from ...types.connector_get_response import ConnectorGetResponse
from ...types.connector_with_secrets import ConnectorWithSecrets
from ...types.explorer_chat_response import ExplorerChatResponse
-from ...types.explore_status_response import ExploreStatusResponse
from ...types.connector_store_response import ConnectorStoreResponse
+from ...types.datahub_secret_map_param import DatahubSecretMapParam
from ...types.exploration_runs_response import ExplorationRunsResponse
from ...types.connector_explore_response import ConnectorExploreResponse
from ...types.connector_summaries_response import ConnectorSummariesResponse
from ...types.connector_table_path_response import ConnectorTablePathResponse
from ...types.delete_schema_object_response import DeleteSchemaObjectResponse
-from ...types.admin.datahub_secret_map_param import DatahubSecretMapParam
from ...types.connector_list_stores_response import ConnectorListStoresResponse
from ...types.connector_search_tables_response import ConnectorSearchTablesResponse
from ...types.connector_add_schema_object_response import ConnectorAddSchemaObjectResponse
@@ -812,6 +813,37 @@ def get(
cast_to=ConnectorGetResponse,
)
+ def get_active_exploration_run(
+ self,
+ connector_id: str,
+ *,
+ # 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,
+ ) -> Optional[ExplorationRun]:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ return self._get(
+ path_template("/connectors/{connector_id}/explore/active-run", connector_id=connector_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExplorationRun,
+ )
+
def get_clarification_requests(
self,
connector_id: str,
@@ -845,20 +877,19 @@ def get_clarification_requests(
cast_to=ConnectorGetClarificationRequestsResponse,
)
- def get_exploration_runs(
+ def get_exploration_run_progress(
self,
- connector_id: str,
+ run_id: str,
*,
+ connector_id: str,
# 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,
- ) -> ExplorationRunsResponse:
+ ) -> ExplorationProgress:
"""
- Get all exploration runs for a connector (requires debug permission)
-
Args:
extra_headers: Send extra headers
@@ -870,15 +901,19 @@ def get_exploration_runs(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
return self._get(
- path_template("/connectors/{connector_id}/explore/runs", connector_id=connector_id),
+ path_template(
+ "/connectors/{connector_id}/explore/runs/{run_id}/progress", connector_id=connector_id, run_id=run_id
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExplorationRunsResponse,
+ cast_to=ExplorationProgress,
)
- def get_exploration_status(
+ def get_exploration_runs(
self,
connector_id: str,
*,
@@ -888,8 +923,10 @@ def get_exploration_status(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExploreStatusResponse:
+ ) -> ExplorationRunsResponse:
"""
+ Get all exploration runs for a connector (requires debug permission)
+
Args:
extra_headers: Send extra headers
@@ -902,11 +939,11 @@ def get_exploration_status(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return self._get(
- path_template("/connectors/{connector_id}/explore/status", connector_id=connector_id),
+ path_template("/connectors/{connector_id}/explore/runs", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExploreStatusResponse,
+ cast_to=ExplorationRunsResponse,
)
def get_explorer_chat(
@@ -2052,6 +2089,37 @@ async def get(
cast_to=ConnectorGetResponse,
)
+ async def get_active_exploration_run(
+ self,
+ connector_id: str,
+ *,
+ # 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,
+ ) -> Optional[ExplorationRun]:
+ """
+ Args:
+ 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
+ """
+ if not connector_id:
+ raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ return await self._get(
+ path_template("/connectors/{connector_id}/explore/active-run", connector_id=connector_id),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=ExplorationRun,
+ )
+
async def get_clarification_requests(
self,
connector_id: str,
@@ -2085,20 +2153,19 @@ async def get_clarification_requests(
cast_to=ConnectorGetClarificationRequestsResponse,
)
- async def get_exploration_runs(
+ async def get_exploration_run_progress(
self,
- connector_id: str,
+ run_id: str,
*,
+ connector_id: str,
# 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,
- ) -> ExplorationRunsResponse:
+ ) -> ExplorationProgress:
"""
- Get all exploration runs for a connector (requires debug permission)
-
Args:
extra_headers: Send extra headers
@@ -2110,15 +2177,19 @@ async def get_exploration_runs(
"""
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
+ if not run_id:
+ raise ValueError(f"Expected a non-empty value for `run_id` but received {run_id!r}")
return await self._get(
- path_template("/connectors/{connector_id}/explore/runs", connector_id=connector_id),
+ path_template(
+ "/connectors/{connector_id}/explore/runs/{run_id}/progress", connector_id=connector_id, run_id=run_id
+ ),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExplorationRunsResponse,
+ cast_to=ExplorationProgress,
)
- async def get_exploration_status(
+ async def get_exploration_runs(
self,
connector_id: str,
*,
@@ -2128,8 +2199,10 @@ async def get_exploration_status(
extra_query: Query | None = None,
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
- ) -> ExploreStatusResponse:
+ ) -> ExplorationRunsResponse:
"""
+ Get all exploration runs for a connector (requires debug permission)
+
Args:
extra_headers: Send extra headers
@@ -2142,11 +2215,11 @@ async def get_exploration_status(
if not connector_id:
raise ValueError(f"Expected a non-empty value for `connector_id` but received {connector_id!r}")
return await self._get(
- path_template("/connectors/{connector_id}/explore/status", connector_id=connector_id),
+ path_template("/connectors/{connector_id}/explore/runs", connector_id=connector_id),
options=make_request_options(
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
),
- cast_to=ExploreStatusResponse,
+ cast_to=ExplorationRunsResponse,
)
async def get_explorer_chat(
@@ -2618,15 +2691,18 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get = to_raw_response_wrapper(
connectors.get,
)
+ self.get_active_exploration_run = to_raw_response_wrapper(
+ connectors.get_active_exploration_run,
+ )
self.get_clarification_requests = to_raw_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_run_progress = to_raw_response_wrapper(
+ connectors.get_exploration_run_progress,
+ )
self.get_exploration_runs = to_raw_response_wrapper(
connectors.get_exploration_runs,
)
- self.get_exploration_status = to_raw_response_wrapper(
- connectors.get_exploration_status,
- )
self.get_explorer_chat = to_raw_response_wrapper(
connectors.get_explorer_chat,
)
@@ -2707,15 +2783,18 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get = async_to_raw_response_wrapper(
connectors.get,
)
+ self.get_active_exploration_run = async_to_raw_response_wrapper(
+ connectors.get_active_exploration_run,
+ )
self.get_clarification_requests = async_to_raw_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_run_progress = async_to_raw_response_wrapper(
+ connectors.get_exploration_run_progress,
+ )
self.get_exploration_runs = async_to_raw_response_wrapper(
connectors.get_exploration_runs,
)
- self.get_exploration_status = async_to_raw_response_wrapper(
- connectors.get_exploration_status,
- )
self.get_explorer_chat = async_to_raw_response_wrapper(
connectors.get_explorer_chat,
)
@@ -2796,15 +2875,18 @@ def __init__(self, connectors: ConnectorsResource) -> None:
self.get = to_streamed_response_wrapper(
connectors.get,
)
+ self.get_active_exploration_run = to_streamed_response_wrapper(
+ connectors.get_active_exploration_run,
+ )
self.get_clarification_requests = to_streamed_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_run_progress = to_streamed_response_wrapper(
+ connectors.get_exploration_run_progress,
+ )
self.get_exploration_runs = to_streamed_response_wrapper(
connectors.get_exploration_runs,
)
- self.get_exploration_status = to_streamed_response_wrapper(
- connectors.get_exploration_status,
- )
self.get_explorer_chat = to_streamed_response_wrapper(
connectors.get_explorer_chat,
)
@@ -2885,15 +2967,18 @@ def __init__(self, connectors: AsyncConnectorsResource) -> None:
self.get = async_to_streamed_response_wrapper(
connectors.get,
)
+ self.get_active_exploration_run = async_to_streamed_response_wrapper(
+ connectors.get_active_exploration_run,
+ )
self.get_clarification_requests = async_to_streamed_response_wrapper(
connectors.get_clarification_requests,
)
+ self.get_exploration_run_progress = async_to_streamed_response_wrapper(
+ connectors.get_exploration_run_progress,
+ )
self.get_exploration_runs = async_to_streamed_response_wrapper(
connectors.get_exploration_runs,
)
- self.get_exploration_status = async_to_streamed_response_wrapper(
- connectors.get_exploration_status,
- )
self.get_explorer_chat = async_to_streamed_response_wrapper(
connectors.get_explorer_chat,
)
diff --git a/src/structify/resources/user/user.py b/src/structify/resources/user/user.py
index 354969852..9d97998a5 100644
--- a/src/structify/resources/user/user.py
+++ b/src/structify/resources/user/user.py
@@ -20,6 +20,7 @@
user_update_params,
user_refresh_params,
user_survey_submit_params,
+ user_save_onboarding_answers_params,
)
from ..._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
from ..._utils import maybe_transform, async_maybe_transform
@@ -43,9 +44,12 @@
from ...types.user_info import UserInfo
from ...types.admin.user import User
from ...types.user_usage_response import UserUsageResponse
+from ...types.onboarding_answers_param import OnboardingAnswersParam
from ...types.refresh_session_response import RefreshSessionResponse
from ...types.survey_submission_response import SurveySubmissionResponse
from ...types.user_transactions_response import UserTransactionsResponse
+from ...types.get_onboarding_answers_response import GetOnboardingAnswersResponse
+from ...types.save_onboarding_answers_response import SaveOnboardingAnswersResponse
__all__ = ["UserResource", "AsyncUserResource"]
@@ -149,6 +153,24 @@ def enrich(
cast_to=NoneType,
)
+ def get_onboarding_answers(
+ self,
+ *,
+ # 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,
+ ) -> GetOnboardingAnswersResponse:
+ return self._get(
+ "/user/onboarding/answers",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=GetOnboardingAnswersResponse,
+ )
+
def info(
self,
*,
@@ -209,6 +231,38 @@ def refresh(
cast_to=RefreshSessionResponse,
)
+ def save_onboarding_answers(
+ self,
+ *,
+ answers: OnboardingAnswersParam,
+ # 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,
+ ) -> SaveOnboardingAnswersResponse:
+ """
+ Args:
+ 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
+ """
+ return self._put(
+ "/user/onboarding/answers",
+ body=maybe_transform(
+ {"answers": answers}, user_save_onboarding_answers_params.UserSaveOnboardingAnswersParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SaveOnboardingAnswersResponse,
+ )
+
def survey_submit(
self,
*,
@@ -396,6 +450,24 @@ async def enrich(
cast_to=NoneType,
)
+ async def get_onboarding_answers(
+ self,
+ *,
+ # 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,
+ ) -> GetOnboardingAnswersResponse:
+ return await self._get(
+ "/user/onboarding/answers",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=GetOnboardingAnswersResponse,
+ )
+
async def info(
self,
*,
@@ -456,6 +528,38 @@ async def refresh(
cast_to=RefreshSessionResponse,
)
+ async def save_onboarding_answers(
+ self,
+ *,
+ answers: OnboardingAnswersParam,
+ # 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,
+ ) -> SaveOnboardingAnswersResponse:
+ """
+ Args:
+ 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
+ """
+ return await self._put(
+ "/user/onboarding/answers",
+ body=await async_maybe_transform(
+ {"answers": answers}, user_save_onboarding_answers_params.UserSaveOnboardingAnswersParams
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SaveOnboardingAnswersResponse,
+ )
+
async def survey_submit(
self,
*,
@@ -554,12 +658,18 @@ def __init__(self, user: UserResource) -> None:
self.enrich = to_raw_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = to_raw_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = to_raw_response_wrapper(
user.info,
)
self.refresh = to_raw_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = to_raw_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = to_raw_response_wrapper(
user.survey_submit,
)
@@ -590,12 +700,18 @@ def __init__(self, user: AsyncUserResource) -> None:
self.enrich = async_to_raw_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = async_to_raw_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = async_to_raw_response_wrapper(
user.info,
)
self.refresh = async_to_raw_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = async_to_raw_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = async_to_raw_response_wrapper(
user.survey_submit,
)
@@ -626,12 +742,18 @@ def __init__(self, user: UserResource) -> None:
self.enrich = to_streamed_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = to_streamed_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = to_streamed_response_wrapper(
user.info,
)
self.refresh = to_streamed_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = to_streamed_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = to_streamed_response_wrapper(
user.survey_submit,
)
@@ -662,12 +784,18 @@ def __init__(self, user: AsyncUserResource) -> None:
self.enrich = async_to_streamed_response_wrapper(
user.enrich,
)
+ self.get_onboarding_answers = async_to_streamed_response_wrapper(
+ user.get_onboarding_answers,
+ )
self.info = async_to_streamed_response_wrapper(
user.info,
)
self.refresh = async_to_streamed_response_wrapper(
user.refresh,
)
+ self.save_onboarding_answers = async_to_streamed_response_wrapper(
+ user.save_onboarding_answers,
+ )
self.survey_submit = async_to_streamed_response_wrapper(
user.survey_submit,
)
diff --git a/src/structify/types/__init__.py b/src/structify/types/__init__.py
index f870fc69a..636201a5a 100644
--- a/src/structify/types/__init__.py
+++ b/src/structify/types/__init__.py
@@ -38,6 +38,7 @@
from .dashboard_page import DashboardPage as DashboardPage
from .dashboard_spec import DashboardSpec as DashboardSpec
from .job_event_body import JobEventBody as JobEventBody
+from .phase_activity import PhaseActivity as PhaseActivity
from .project_member import ProjectMember as ProjectMember
from .strategy_param import StrategyParam as StrategyParam
from .team_with_role import TeamWithRole as TeamWithRole
@@ -58,6 +59,7 @@
from .viz_param_param import VizParamParam as VizParamParam
from .viz_query_param import VizQueryParam as VizQueryParam
from .chat_copy_params import ChatCopyParams as ChatCopyParams
+from .datahub_progress import DatahubProgress as DatahubProgress
from .job_get_response import JobGetResponse as JobGetResponse
from .save_requirement import SaveRequirement as SaveRequirement
from .viz_date_control import VizDateControl as VizDateControl
@@ -77,11 +79,13 @@
from .user_usage_params import UserUsageParams as UserUsageParams
from .workflow_node_log import WorkflowNodeLog as WorkflowNodeLog
from .connector_category import ConnectorCategory as ConnectorCategory
+from .datahub_secret_map import DatahubSecretMap as DatahubSecretMap
from .dataset_descriptor import DatasetDescriptor as DatasetDescriptor
from .dataset_get_params import DatasetGetParams as DatasetGetParams
from .entity_view_params import EntityViewParams as EntityViewParams
from .exploration_status import ExplorationStatus as ExplorationStatus
from .merge_config_param import MergeConfigParam as MergeConfigParam
+from .onboarding_answers import OnboardingAnswers as OnboardingAnswers
from .parquet_edit_param import ParquetEditParam as ParquetEditParam
from .project_visibility import ProjectVisibility as ProjectVisibility
from .relationship_param import RelationshipParam as RelationshipParam
@@ -127,6 +131,7 @@
from .entity_verify_params import EntityVerifyParams as EntityVerifyParams
from .entity_view_response import EntityViewResponse as EntityViewResponse
from .exploration_phase_id import ExplorationPhaseID as ExplorationPhaseID
+from .exploration_progress import ExplorationProgress as ExplorationProgress
from .list_tables_response import ListTablesResponse as ListTablesResponse
from .project_get_response import ProjectGetResponse as ProjectGetResponse
from .scrape_list_response import ScrapeListResponse as ScrapeListResponse
@@ -185,7 +190,6 @@
from .entity_add_batch_params import EntityAddBatchParams as EntityAddBatchParams
from .entity_list_jobs_params import EntityListJobsParams as EntityListJobsParams
from .entity_summarize_params import EntitySummarizeParams as EntitySummarizeParams
-from .explore_status_response import ExploreStatusResponse as ExploreStatusResponse
from .get_job_events_response import GetJobEventsResponse as GetJobEventsResponse
from .template_question_param import TemplateQuestionParam as TemplateQuestionParam
from .trigger_review_response import TriggerReviewResponse as TriggerReviewResponse
@@ -194,12 +198,14 @@
from .chat_load_files_response import ChatLoadFilesResponse as ChatLoadFilesResponse
from .connector_explore_params import ConnectorExploreParams as ConnectorExploreParams
from .connector_store_response import ConnectorStoreResponse as ConnectorStoreResponse
+from .datahub_secret_map_param import DatahubSecretMapParam as DatahubSecretMapParam
from .dataset_descriptor_param import DatasetDescriptorParam as DatasetDescriptorParam
from .document_download_params import DocumentDownloadParams as DocumentDownloadParams
from .entity_derive_all_params import EntityDeriveAllParams as EntityDeriveAllParams
from .entity_get_merges_params import EntityGetMergesParams as EntityGetMergesParams
from .list_dashboards_response import ListDashboardsResponse as ListDashboardsResponse
from .match_create_jobs_params import MatchCreateJobsParams as MatchCreateJobsParams
+from .onboarding_answers_param import OnboardingAnswersParam as OnboardingAnswersParam
from .refresh_session_response import RefreshSessionResponse as RefreshSessionResponse
from .session_kill_jobs_params import SessionKillJobsParams as SessionKillJobsParams
from .simulate_prompt_response import SimulatePromptResponse as SimulatePromptResponse
@@ -320,6 +326,7 @@
from .chat_upload_input_file_response import ChatUploadInputFileResponse as ChatUploadInputFileResponse
from .connector_catalog_list_response import ConnectorCatalogListResponse as ConnectorCatalogListResponse
from .entity_update_property_response import EntityUpdatePropertyResponse as EntityUpdatePropertyResponse
+from .get_onboarding_answers_response import GetOnboardingAnswersResponse as GetOnboardingAnswersResponse
from .session_edit_node_output_params import SessionEditNodeOutputParams as SessionEditNodeOutputParams
from .workflow_schedule_create_params import WorkflowScheduleCreateParams as WorkflowScheduleCreateParams
from .workflow_schedule_update_params import WorkflowScheduleUpdateParams as WorkflowScheduleUpdateParams
@@ -330,6 +337,7 @@
from .entity_get_local_subgraph_params import EntityGetLocalSubgraphParams as EntityGetLocalSubgraphParams
from .nango_list_integrations_response import NangoListIntegrationsResponse as NangoListIntegrationsResponse
from .project_collaborator_input_param import ProjectCollaboratorInputParam as ProjectCollaboratorInputParam
+from .save_onboarding_answers_response import SaveOnboardingAnswersResponse as SaveOnboardingAnswersResponse
from .connector_auth_method_with_fields import ConnectorAuthMethodWithFields as ConnectorAuthMethodWithFields
from .dataset_reorder_properties_params import DatasetReorderPropertiesParams as DatasetReorderPropertiesParams
from .dataset_set_primary_column_params import DatasetSetPrimaryColumnParams as DatasetSetPrimaryColumnParams
@@ -357,6 +365,7 @@
from .session_request_confirmation_params import SessionRequestConfirmationParams as SessionRequestConfirmationParams
from .session_update_node_progress_params import SessionUpdateNodeProgressParams as SessionUpdateNodeProgressParams
from .structure_enhance_property_response import StructureEnhancePropertyResponse as StructureEnhancePropertyResponse
+from .user_save_onboarding_answers_params import UserSaveOnboardingAnswersParams as UserSaveOnboardingAnswersParams
from .connector_add_schema_object_response import ConnectorAddSchemaObjectResponse as ConnectorAddSchemaObjectResponse
from .dataset_enrichment_progress_response import DatasetEnrichmentProgressResponse as DatasetEnrichmentProgressResponse
from .structure_find_relationship_response import StructureFindRelationshipResponse as StructureFindRelationshipResponse
diff --git a/src/structify/types/admin/__init__.py b/src/structify/types/admin/__init__.py
index 00baacd28..d07081a7d 100644
--- a/src/structify/types/admin/__init__.py
+++ b/src/structify/types/admin/__init__.py
@@ -8,7 +8,6 @@
from .team_list_params import TeamListParams as TeamListParams
from .job_delete_params import JobDeleteParams as JobDeleteParams
from .job_list_response import JobListResponse as JobListResponse
-from .datahub_secret_map import DatahubSecretMap as DatahubSecretMap
from .team_list_response import TeamListResponse as TeamListResponse
from .user_create_params import UserCreateParams as UserCreateParams
from .user_list_response import UserListResponse as UserListResponse
@@ -26,13 +25,12 @@
from .job_kill_by_user_params import JobKillByUserParams as JobKillByUserParams
from .user_get_stats_response import UserGetStatsResponse as UserGetStatsResponse
from .user_impersonate_params import UserImpersonateParams as UserImpersonateParams
-from .datahub_secret_map_param import DatahubSecretMapParam as DatahubSecretMapParam
+from .connector_clone_response import ConnectorCloneResponse as ConnectorCloneResponse
from .dataset_get_by_id_params import DatasetGetByIDParams as DatasetGetByIDParams
from .team_extend_trial_params import TeamExtendTrialParams as TeamExtendTrialParams
from .admin_add_member_response import AdminAddMemberResponse as AdminAddMemberResponse
from .admin_teams_list_response import AdminTeamsListResponse as AdminTeamsListResponse
from .chat_template_list_params import ChatTemplateListParams as ChatTemplateListParams
-from .clone_connectors_response import CloneConnectorsResponse as CloneConnectorsResponse
from .job_kill_by_user_response import JobKillByUserResponse as JobKillByUserResponse
from .team_expire_grants_params import TeamExpireGrantsParams as TeamExpireGrantsParams
from .team_grant_credits_params import TeamGrantCreditsParams as TeamGrantCreditsParams
diff --git a/src/structify/types/admin/clone_connectors_response.py b/src/structify/types/admin/connector_clone_response.py
similarity index 72%
rename from src/structify/types/admin/clone_connectors_response.py
rename to src/structify/types/admin/connector_clone_response.py
index 3f9e92177..3b3f86184 100644
--- a/src/structify/types/admin/clone_connectors_response.py
+++ b/src/structify/types/admin/connector_clone_response.py
@@ -5,8 +5,8 @@
from ..._models import BaseModel
from ..connector import Connector
-__all__ = ["CloneConnectorsResponse"]
+__all__ = ["ConnectorCloneResponse"]
-class CloneConnectorsResponse(BaseModel):
+class ConnectorCloneResponse(BaseModel):
connectors: List[Connector]
diff --git a/src/structify/types/admin/connector_set_datahub_config_params.py b/src/structify/types/admin/connector_set_datahub_config_params.py
index c346ae395..19b947e9c 100644
--- a/src/structify/types/admin/connector_set_datahub_config_params.py
+++ b/src/structify/types/admin/connector_set_datahub_config_params.py
@@ -6,7 +6,7 @@
from typing_extensions import Required, TypedDict
from .datahub_ingestion_type import DatahubIngestionType
-from .datahub_secret_map_param import DatahubSecretMapParam
+from ..datahub_secret_map_param import DatahubSecretMapParam
__all__ = ["ConnectorSetDatahubConfigParams"]
diff --git a/src/structify/types/connector.py b/src/structify/types/connector.py
index 63f742487..fb8393c35 100644
--- a/src/structify/types/connector.py
+++ b/src/structify/types/connector.py
@@ -6,7 +6,7 @@
from .._models import BaseModel
from .connector_category import ConnectorCategory
-from .admin.datahub_secret_map import DatahubSecretMap
+from .datahub_secret_map import DatahubSecretMap
__all__ = ["Connector"]
diff --git a/src/structify/types/connector_update_params.py b/src/structify/types/connector_update_params.py
index af460319e..9b1a14456 100644
--- a/src/structify/types/connector_update_params.py
+++ b/src/structify/types/connector_update_params.py
@@ -7,7 +7,7 @@
from .._types import SequenceNotStr
from .connector_category import ConnectorCategory
-from .admin.datahub_secret_map_param import DatahubSecretMapParam
+from .datahub_secret_map_param import DatahubSecretMapParam
__all__ = ["ConnectorUpdateParams"]
diff --git a/src/structify/types/datahub_progress.py b/src/structify/types/datahub_progress.py
new file mode 100644
index 000000000..7b4561117
--- /dev/null
+++ b/src/structify/types/datahub_progress.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal
+
+from .._models import BaseModel
+
+__all__ = ["DatahubProgress"]
+
+
+class DatahubProgress(BaseModel):
+ databases_created: int
+
+ job_id: str
+
+ job_status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ pages_fetched: int
+
+ schemas_created: int
+
+ tables_processed: int
+
+ total_datasets: int
diff --git a/src/structify/types/admin/datahub_secret_map.py b/src/structify/types/datahub_secret_map.py
similarity index 100%
rename from src/structify/types/admin/datahub_secret_map.py
rename to src/structify/types/datahub_secret_map.py
diff --git a/src/structify/types/admin/datahub_secret_map_param.py b/src/structify/types/datahub_secret_map_param.py
similarity index 100%
rename from src/structify/types/admin/datahub_secret_map_param.py
rename to src/structify/types/datahub_secret_map_param.py
diff --git a/src/structify/types/exploration_progress.py b/src/structify/types/exploration_progress.py
new file mode 100644
index 000000000..2b3d4f515
--- /dev/null
+++ b/src/structify/types/exploration_progress.py
@@ -0,0 +1,15 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+from .phase_activity import PhaseActivity
+from .datahub_progress import DatahubProgress
+
+__all__ = ["ExplorationProgress"]
+
+
+class ExplorationProgress(BaseModel):
+ phases: List[PhaseActivity]
+
+ datahub: Optional[DatahubProgress] = None
diff --git a/src/structify/types/explore_status_response.py b/src/structify/types/explore_status_response.py
deleted file mode 100644
index 4275c265a..000000000
--- a/src/structify/types/explore_status_response.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-
-from typing import Optional
-from datetime import datetime
-
-from .._models import BaseModel
-from .exploration_status import ExplorationStatus
-
-__all__ = ["ExploreStatusResponse"]
-
-
-class ExploreStatusResponse(BaseModel):
- status: ExplorationStatus
-
- started_at: Optional[datetime] = None
diff --git a/src/structify/types/get_onboarding_answers_response.py b/src/structify/types/get_onboarding_answers_response.py
new file mode 100644
index 000000000..cada36acc
--- /dev/null
+++ b/src/structify/types/get_onboarding_answers_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .onboarding_answers import OnboardingAnswers
+
+__all__ = ["GetOnboardingAnswersResponse"]
+
+
+class GetOnboardingAnswersResponse(BaseModel):
+ answers: OnboardingAnswers
diff --git a/src/structify/types/onboarding_answers.py b/src/structify/types/onboarding_answers.py
new file mode 100644
index 000000000..d3d0be2a2
--- /dev/null
+++ b/src/structify/types/onboarding_answers.py
@@ -0,0 +1,23 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from .._models import BaseModel
+
+__all__ = ["OnboardingAnswers"]
+
+
+class OnboardingAnswers(BaseModel):
+ company_name: Optional[str] = None
+
+ connected_connector_ids: Optional[List[str]] = None
+
+ full_name: Optional[str] = None
+
+ primary_goal: Optional[str] = None
+
+ recommended_template_id: Optional[str] = None
+
+ role: Optional[str] = None
+
+ systems_to_connect: Optional[List[str]] = None
diff --git a/src/structify/types/onboarding_answers_param.py b/src/structify/types/onboarding_answers_param.py
new file mode 100644
index 000000000..b3e43f9f8
--- /dev/null
+++ b/src/structify/types/onboarding_answers_param.py
@@ -0,0 +1,26 @@
+# 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
+
+from .._types import SequenceNotStr
+
+__all__ = ["OnboardingAnswersParam"]
+
+
+class OnboardingAnswersParam(TypedDict, total=False):
+ company_name: Optional[str]
+
+ connected_connector_ids: Optional[SequenceNotStr[str]]
+
+ full_name: Optional[str]
+
+ primary_goal: Optional[str]
+
+ recommended_template_id: Optional[str]
+
+ role: Optional[str]
+
+ systems_to_connect: Optional[SequenceNotStr[str]]
diff --git a/src/structify/types/phase_activity.py b/src/structify/types/phase_activity.py
new file mode 100644
index 000000000..63e43ac12
--- /dev/null
+++ b/src/structify/types/phase_activity.py
@@ -0,0 +1,24 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from typing_extensions import Literal
+
+from .._models import BaseModel
+from .exploration_phase_id import ExplorationPhaseID
+
+__all__ = ["PhaseActivity"]
+
+
+class PhaseActivity(BaseModel):
+ job_id: str
+
+ phase_id: ExplorationPhaseID
+ """Identifies the phase of connector exploration
+
+ This enum is used to track which phase of exploration a chat session belongs to.
+ It's stored as JSONB in the database to allow for flexible phase identification.
+ """
+
+ status: Literal["Queued", "Running", "Completed", "Failed"]
+
+ chat_id: Optional[str] = None
diff --git a/src/structify/types/save_onboarding_answers_response.py b/src/structify/types/save_onboarding_answers_response.py
new file mode 100644
index 000000000..03ee078f3
--- /dev/null
+++ b/src/structify/types/save_onboarding_answers_response.py
@@ -0,0 +1,10 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .onboarding_answers import OnboardingAnswers
+
+__all__ = ["SaveOnboardingAnswersResponse"]
+
+
+class SaveOnboardingAnswersResponse(BaseModel):
+ answers: OnboardingAnswers
diff --git a/src/structify/types/user_save_onboarding_answers_params.py b/src/structify/types/user_save_onboarding_answers_params.py
new file mode 100644
index 000000000..4689e70ae
--- /dev/null
+++ b/src/structify/types/user_save_onboarding_answers_params.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Required, TypedDict
+
+from .onboarding_answers_param import OnboardingAnswersParam
+
+__all__ = ["UserSaveOnboardingAnswersParams"]
+
+
+class UserSaveOnboardingAnswersParams(TypedDict, total=False):
+ answers: Required[OnboardingAnswersParam]
diff --git a/tests/api_resources/admin/test_connector.py b/tests/api_resources/admin/test_connector.py
index da0a98af9..7d2a3c984 100644
--- a/tests/api_resources/admin/test_connector.py
+++ b/tests/api_resources/admin/test_connector.py
@@ -11,7 +11,7 @@
from tests.utils import assert_matches_type
from structify.types import Connector
from structify.types.admin import (
- CloneConnectorsResponse,
+ ConnectorCloneResponse,
AdminListConnectorsResponse,
)
@@ -35,7 +35,7 @@ def test_method_clone(self, client: Structify) -> None:
source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
+ assert_matches_type(ConnectorCloneResponse, connector, path=["response"])
@parametrize
def test_raw_response_clone(self, client: Structify) -> None:
@@ -55,7 +55,7 @@ def test_raw_response_clone(self, client: Structify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
+ assert_matches_type(ConnectorCloneResponse, connector, path=["response"])
@parametrize
def test_streaming_response_clone(self, client: Structify) -> None:
@@ -75,7 +75,7 @@ def test_streaming_response_clone(self, client: Structify) -> None:
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
+ assert_matches_type(ConnectorCloneResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@@ -177,7 +177,7 @@ async def test_method_clone(self, async_client: AsyncStructify) -> None:
source_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
target_team_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
+ assert_matches_type(ConnectorCloneResponse, connector, path=["response"])
@parametrize
async def test_raw_response_clone(self, async_client: AsyncStructify) -> None:
@@ -197,7 +197,7 @@ async def test_raw_response_clone(self, async_client: AsyncStructify) -> None:
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
+ assert_matches_type(ConnectorCloneResponse, connector, path=["response"])
@parametrize
async def test_streaming_response_clone(self, async_client: AsyncStructify) -> None:
@@ -217,7 +217,7 @@ async def test_streaming_response_clone(self, async_client: AsyncStructify) -> N
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(CloneConnectorsResponse, connector, path=["response"])
+ assert_matches_type(ConnectorCloneResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
diff --git a/tests/api_resources/test_connectors.py b/tests/api_resources/test_connectors.py
index 134428572..138becde0 100644
--- a/tests/api_resources/test_connectors.py
+++ b/tests/api_resources/test_connectors.py
@@ -3,7 +3,7 @@
from __future__ import annotations
import os
-from typing import Any, cast
+from typing import Any, Optional, cast
import httpx
import pytest
@@ -13,12 +13,13 @@
from tests.utils import assert_matches_type
from structify.types import (
Connector,
+ ExplorationRun,
ListTablesResponse,
+ ExplorationProgress,
UpdateTableResponse,
ConnectorGetResponse,
ConnectorWithSecrets,
ExplorerChatResponse,
- ExploreStatusResponse,
ConnectorStoreResponse,
ExplorationRunsResponse,
ConnectorExploreResponse,
@@ -915,6 +916,44 @@ def test_path_params_get(self, client: Structify) -> None:
"",
)
+ @parametrize
+ def test_method_get_active_exploration_run(self, client: Structify) -> None:
+ connector = client.connectors.get_active_exploration_run(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_active_exploration_run(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.get_active_exploration_run(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = response.parse()
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_active_exploration_run(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.get_active_exploration_run(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = response.parse()
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_path_params_get_active_exploration_run(self, client: Structify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ client.connectors.with_raw_response.get_active_exploration_run(
+ "",
+ )
+
@parametrize
def test_method_get_clarification_requests(self, client: Structify) -> None:
connector = client.connectors.get_clarification_requests(
@@ -954,78 +993,88 @@ def test_path_params_get_clarification_requests(self, client: Structify) -> None
)
@parametrize
- def test_method_get_exploration_runs(self, client: Structify) -> None:
- connector = client.connectors.get_exploration_runs(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ def test_method_get_exploration_run_progress(self, client: Structify) -> None:
+ connector = client.connectors.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
@parametrize
- def test_raw_response_get_exploration_runs(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.get_exploration_runs(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ def test_raw_response_get_exploration_run_progress(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
@parametrize
- def test_streaming_response_get_exploration_runs(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.get_exploration_runs(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ def test_streaming_response_get_exploration_run_progress(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_get_exploration_runs(self, client: Structify) -> None:
+ def test_path_params_get_exploration_run_progress(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.get_exploration_runs(
- "",
+ client.connectors.with_raw_response.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ client.connectors.with_raw_response.get_exploration_run_progress(
+ run_id="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@parametrize
- def test_method_get_exploration_status(self, client: Structify) -> None:
- connector = client.connectors.get_exploration_status(
+ def test_method_get_exploration_runs(self, client: Structify) -> None:
+ connector = client.connectors.get_exploration_runs(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
@parametrize
- def test_raw_response_get_exploration_status(self, client: Structify) -> None:
- response = client.connectors.with_raw_response.get_exploration_status(
+ def test_raw_response_get_exploration_runs(self, client: Structify) -> None:
+ response = client.connectors.with_raw_response.get_exploration_runs(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
@parametrize
- def test_streaming_response_get_exploration_status(self, client: Structify) -> None:
- with client.connectors.with_streaming_response.get_exploration_status(
+ def test_streaming_response_get_exploration_runs(self, client: Structify) -> None:
+ with client.connectors.with_streaming_response.get_exploration_runs(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- def test_path_params_get_exploration_status(self, client: Structify) -> None:
+ def test_path_params_get_exploration_runs(self, client: Structify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- client.connectors.with_raw_response.get_exploration_status(
+ client.connectors.with_raw_response.get_exploration_runs(
"",
)
@@ -2378,6 +2427,44 @@ async def test_path_params_get(self, async_client: AsyncStructify) -> None:
"",
)
+ @parametrize
+ async def test_method_get_active_exploration_run(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.get_active_exploration_run(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_active_exploration_run(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.get_active_exploration_run(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ connector = await response.parse()
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_active_exploration_run(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.get_active_exploration_run(
+ "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ connector = await response.parse()
+ assert_matches_type(Optional[ExplorationRun], connector, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_path_params_get_active_exploration_run(self, async_client: AsyncStructify) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
+ await async_client.connectors.with_raw_response.get_active_exploration_run(
+ "",
+ )
+
@parametrize
async def test_method_get_clarification_requests(self, async_client: AsyncStructify) -> None:
connector = await async_client.connectors.get_clarification_requests(
@@ -2417,78 +2504,88 @@ async def test_path_params_get_clarification_requests(self, async_client: AsyncS
)
@parametrize
- async def test_method_get_exploration_runs(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.get_exploration_runs(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ async def test_method_get_exploration_run_progress(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
@parametrize
- async def test_raw_response_get_exploration_runs(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.get_exploration_runs(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ async def test_raw_response_get_exploration_run_progress(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
@parametrize
- async def test_streaming_response_get_exploration_runs(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.get_exploration_runs(
- "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ async def test_streaming_response_get_exploration_run_progress(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
+ assert_matches_type(ExplorationProgress, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_get_exploration_runs(self, async_client: AsyncStructify) -> None:
+ async def test_path_params_get_exploration_run_progress(self, async_client: AsyncStructify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.get_exploration_runs(
- "",
+ await async_client.connectors.with_raw_response.get_exploration_run_progress(
+ run_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
+ connector_id="",
+ )
+
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `run_id` but received ''"):
+ await async_client.connectors.with_raw_response.get_exploration_run_progress(
+ run_id="",
+ connector_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
@parametrize
- async def test_method_get_exploration_status(self, async_client: AsyncStructify) -> None:
- connector = await async_client.connectors.get_exploration_status(
+ async def test_method_get_exploration_runs(self, async_client: AsyncStructify) -> None:
+ connector = await async_client.connectors.get_exploration_runs(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
@parametrize
- async def test_raw_response_get_exploration_status(self, async_client: AsyncStructify) -> None:
- response = await async_client.connectors.with_raw_response.get_exploration_status(
+ async def test_raw_response_get_exploration_runs(self, async_client: AsyncStructify) -> None:
+ response = await async_client.connectors.with_raw_response.get_exploration_runs(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
)
assert response.is_closed is True
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
@parametrize
- async def test_streaming_response_get_exploration_status(self, async_client: AsyncStructify) -> None:
- async with async_client.connectors.with_streaming_response.get_exploration_status(
+ async def test_streaming_response_get_exploration_runs(self, async_client: AsyncStructify) -> None:
+ async with async_client.connectors.with_streaming_response.get_exploration_runs(
"182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e",
) as response:
assert not response.is_closed
assert response.http_request.headers.get("X-Stainless-Lang") == "python"
connector = await response.parse()
- assert_matches_type(ExploreStatusResponse, connector, path=["response"])
+ assert_matches_type(ExplorationRunsResponse, connector, path=["response"])
assert cast(Any, response.is_closed) is True
@parametrize
- async def test_path_params_get_exploration_status(self, async_client: AsyncStructify) -> None:
+ async def test_path_params_get_exploration_runs(self, async_client: AsyncStructify) -> None:
with pytest.raises(ValueError, match=r"Expected a non-empty value for `connector_id` but received ''"):
- await async_client.connectors.with_raw_response.get_exploration_status(
+ await async_client.connectors.with_raw_response.get_exploration_runs(
"",
)
diff --git a/tests/api_resources/test_user.py b/tests/api_resources/test_user.py
index 57a4dcc64..063cd0063 100644
--- a/tests/api_resources/test_user.py
+++ b/tests/api_resources/test_user.py
@@ -15,6 +15,8 @@
RefreshSessionResponse,
SurveySubmissionResponse,
UserTransactionsResponse,
+ GetOnboardingAnswersResponse,
+ SaveOnboardingAnswersResponse,
)
from structify.types.admin import User
@@ -117,6 +119,31 @@ def test_streaming_response_enrich(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_get_onboarding_answers(self, client: Structify) -> None:
+ user = client.user.get_onboarding_answers()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_raw_response_get_onboarding_answers(self, client: Structify) -> None:
+ response = client.user.with_raw_response.get_onboarding_answers()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_streaming_response_get_onboarding_answers(self, client: Structify) -> None:
+ with client.user.with_streaming_response.get_onboarding_answers() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_info(self, client: Structify) -> None:
user = client.user.info()
@@ -176,6 +203,52 @@ def test_streaming_response_refresh(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_save_onboarding_answers(self, client: Structify) -> None:
+ user = client.user.save_onboarding_answers(
+ answers={},
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_method_save_onboarding_answers_with_all_params(self, client: Structify) -> None:
+ user = client.user.save_onboarding_answers(
+ answers={
+ "company_name": "company_name",
+ "connected_connector_ids": ["string"],
+ "full_name": "full_name",
+ "primary_goal": "primary_goal",
+ "recommended_template_id": "recommended_template_id",
+ "role": "role",
+ "systems_to_connect": ["string"],
+ },
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_raw_response_save_onboarding_answers(self, client: Structify) -> None:
+ response = client.user.with_raw_response.save_onboarding_answers(
+ answers={},
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ def test_streaming_response_save_onboarding_answers(self, client: Structify) -> None:
+ with client.user.with_streaming_response.save_onboarding_answers(
+ answers={},
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_survey_submit(self, client: Structify) -> None:
user = client.user.survey_submit(
@@ -363,6 +436,31 @@ async def test_streaming_response_enrich(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ user = await async_client.user.get_onboarding_answers()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_raw_response_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ response = await async_client.user.with_raw_response.get_onboarding_answers()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_get_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ async with async_client.user.with_streaming_response.get_onboarding_answers() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(GetOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_info(self, async_client: AsyncStructify) -> None:
user = await async_client.user.info()
@@ -422,6 +520,52 @@ async def test_streaming_response_refresh(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ user = await async_client.user.save_onboarding_answers(
+ answers={},
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_method_save_onboarding_answers_with_all_params(self, async_client: AsyncStructify) -> None:
+ user = await async_client.user.save_onboarding_answers(
+ answers={
+ "company_name": "company_name",
+ "connected_connector_ids": ["string"],
+ "full_name": "full_name",
+ "primary_goal": "primary_goal",
+ "recommended_template_id": "recommended_template_id",
+ "role": "role",
+ "systems_to_connect": ["string"],
+ },
+ )
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_raw_response_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ response = await async_client.user.with_raw_response.save_onboarding_answers(
+ answers={},
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ user = await response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_save_onboarding_answers(self, async_client: AsyncStructify) -> None:
+ async with async_client.user.with_streaming_response.save_onboarding_answers(
+ answers={},
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ user = await response.parse()
+ assert_matches_type(SaveOnboardingAnswersResponse, user, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_survey_submit(self, async_client: AsyncStructify) -> None:
user = await async_client.user.survey_submit(
From 9c8578843117aabfed6c177eef54dd55b32153d4 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Mon, 23 Mar 2026 23:30:18 +0000
Subject: [PATCH 094/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/tool_invocation.py | 2 --
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index c6069314d..b093939dd 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-c7eee6a00ed99a6b5fcbd38a11eef4eb3f1889d40e801d47abddf53e0c59e94a.yml
-openapi_spec_hash: e6a3b10a0046edf68b1db030a8db0ad6
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-a00065ef65b2723e33063322249f20582458deddf6356a25a038bbd41f1d4505.yml
+openapi_spec_hash: 7d71210389994fdad09aaebde37a7858
config_hash: de97841de67eb76e2acd3a5a6b67a26d
diff --git a/src/structify/types/tool_invocation.py b/src/structify/types/tool_invocation.py
index 53388f030..6956a3018 100644
--- a/src/structify/types/tool_invocation.py
+++ b/src/structify/types/tool_invocation.py
@@ -330,8 +330,6 @@ class SaveTableInput(BaseModel):
notes: Optional[str] = None
- tag: Optional[str] = None
-
class SaveTable(BaseModel):
input: SaveTableInput
From 60f8dcd5ac4811c83554ec663bd4d457f33539a5 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Mar 2026 02:00:27 +0000
Subject: [PATCH 095/105] chore(internal): update gitignore
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index 95ceb189a..3824f4c48 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.prism.log
+.stdy.log
_dev
__pycache__
From 4dd53245dca023dac6911d512963d2a14b0155b7 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Mar 2026 02:07:07 +0000
Subject: [PATCH 096/105] chore(tests): bump steady to v0.19.6
---
scripts/mock | 6 +++---
scripts/test | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/mock b/scripts/mock
index ab814d383..b319bdfbb 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}"
# Run steady mock on the given spec
if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
- npm exec --package=@stdy/cli@0.19.5 -- steady --version
+ npm exec --package=@stdy/cli@0.19.6 -- steady --version
- npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
+ npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
@@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then
echo
else
- npm exec --package=@stdy/cli@0.19.5 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
+ npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
fi
diff --git a/scripts/test b/scripts/test
index d1c8e1a9d..ab01948b6 100755
--- a/scripts/test
+++ b/scripts/test
@@ -43,7 +43,7 @@ elif ! steady_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the steady command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.5 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.6 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
echo
exit 1
From 3177c9b031335b7dad8b974cbc8e7e5af47f69dd Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Tue, 24 Mar 2026 19:18:46 +0000
Subject: [PATCH 097/105] codegen metadata
---
.stats.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index b093939dd..91315f725 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-a00065ef65b2723e33063322249f20582458deddf6356a25a038bbd41f1d4505.yml
-openapi_spec_hash: 7d71210389994fdad09aaebde37a7858
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-4383fb675c7ff5aeeb21ed0d8ed26e1e7e7f583c526647d8a2785fae6a8db6fc.yml
+openapi_spec_hash: 078416ef61d6f905349f26fd54320dca
config_hash: de97841de67eb76e2acd3a5a6b67a26d
From 2957a7945ff54a0e447255d37665aae07750f368 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Mar 2026 01:54:07 +0000
Subject: [PATCH 098/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/types/datahub_progress.py | 2 ++
src/structify/types/job_event_body.py | 8 ++++++++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 91315f725..d04850f29 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-4383fb675c7ff5aeeb21ed0d8ed26e1e7e7f583c526647d8a2785fae6a8db6fc.yml
-openapi_spec_hash: 078416ef61d6f905349f26fd54320dca
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-8758205f56ee4601473c83784b3a14ff4ae046c9597719b00fd583273ac16abc.yml
+openapi_spec_hash: a19bf35af3ead4f69a310dfea8663855
config_hash: de97841de67eb76e2acd3a5a6b67a26d
diff --git a/src/structify/types/datahub_progress.py b/src/structify/types/datahub_progress.py
index 7b4561117..5fd316fa6 100644
--- a/src/structify/types/datahub_progress.py
+++ b/src/structify/types/datahub_progress.py
@@ -16,6 +16,8 @@ class DatahubProgress(BaseModel):
pages_fetched: int
+ records_written: int
+
schemas_created: int
tables_processed: int
diff --git a/src/structify/types/job_event_body.py b/src/structify/types/job_event_body.py
index 8820bff9d..d35bb49af 100644
--- a/src/structify/types/job_event_body.py
+++ b/src/structify/types/job_event_body.py
@@ -25,6 +25,7 @@
"DatahubSchemasCreated",
"DatahubTablesProcessed",
"DatahubAnnotationsQueued",
+ "DatahubIngestionProgress",
"DatahubEmbeddingBatch",
"ViewedPdfPage",
]
@@ -181,6 +182,12 @@ class DatahubAnnotationsQueued(BaseModel):
full_annotations_queued: int
+class DatahubIngestionProgress(BaseModel):
+ event_type: Literal["datahub_ingestion_progress"]
+
+ records_written: int
+
+
class DatahubEmbeddingBatch(BaseModel):
batch_num: int
@@ -215,6 +222,7 @@ class ViewedPdfPage(BaseModel):
DatahubSchemasCreated,
DatahubTablesProcessed,
DatahubAnnotationsQueued,
+ DatahubIngestionProgress,
DatahubEmbeddingBatch,
ViewedPdfPage,
],
From a9b43a66365028af38669fe38d6a6275e70980c0 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Mar 2026 02:01:32 +0000
Subject: [PATCH 099/105] chore(ci): skip lint on metadata-only changes
Note that we still want to run tests, as these depend on the metadata.
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d0fd5d668..b7512d114 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,7 +19,7 @@ jobs:
timeout-minutes: 10
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/structify-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
- if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+ 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@v6
@@ -38,7 +38,7 @@ jobs:
run: ./scripts/lint
build:
- if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+ if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata')
timeout-minutes: 10
name: build
permissions:
From dc20757e4e4ae8250f8468084bc71e638238519c Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Mar 2026 02:02:47 +0000
Subject: [PATCH 100/105] chore(tests): bump steady to v0.19.7
---
scripts/mock | 6 +++---
scripts/test | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/mock b/scripts/mock
index b319bdfbb..09eb49f65 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -22,9 +22,9 @@ echo "==> Starting mock server with URL ${URL}"
# Run steady mock on the given spec
if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
- npm exec --package=@stdy/cli@0.19.6 -- steady --version
+ npm exec --package=@stdy/cli@0.19.7 -- steady --version
- npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
+ npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
@@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then
echo
else
- npm exec --package=@stdy/cli@0.19.6 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
+ npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
fi
diff --git a/scripts/test b/scripts/test
index ab01948b6..e46b9b58d 100755
--- a/scripts/test
+++ b/scripts/test
@@ -43,7 +43,7 @@ elif ! steady_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the steady command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.6 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
echo
exit 1
From 5e74183af52a15223e47a86c12e278fa9baae23e Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Mar 2026 06:10:02 +0000
Subject: [PATCH 101/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
.../resources/connector_catalog/connector_catalog.py | 12 +++++++++++-
src/structify/types/connector_catalog_list_params.py | 8 ++++++++
tests/api_resources/test_connector_catalog.py | 2 ++
4 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index d04850f29..99c9a9b90 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-8758205f56ee4601473c83784b3a14ff4ae046c9597719b00fd583273ac16abc.yml
-openapi_spec_hash: a19bf35af3ead4f69a310dfea8663855
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-98b70908fefea6e8700e8b59027706c7243ed385df23a6d9677229bde75d0f66.yml
+openapi_spec_hash: c0683fd6f52b8e1ee90ac4c17a908d88
config_hash: de97841de67eb76e2acd3a5a6b67a26d
diff --git a/src/structify/resources/connector_catalog/connector_catalog.py b/src/structify/resources/connector_catalog/connector_catalog.py
index 1dcfb0683..a549b5b1f 100644
--- a/src/structify/resources/connector_catalog/connector_catalog.py
+++ b/src/structify/resources/connector_catalog/connector_catalog.py
@@ -15,7 +15,7 @@
AsyncAdminResourceWithStreamingResponse,
)
from ...types import connector_catalog_list_params
-from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given
+from ..._types import Body, Omit, Query, Headers, NotGiven, SequenceNotStr, omit, not_given
from ..._utils import path_template, maybe_transform, async_maybe_transform
from ..._compat import cached_property
from ..._resource import SyncAPIResource, AsyncAPIResource
@@ -68,6 +68,7 @@ def with_streaming_response(self) -> ConnectorCatalogResourceWithStreamingRespon
def list(
self,
*,
+ categories: SequenceNotStr[str] | Omit = omit,
include_inactive: bool | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
@@ -83,6 +84,9 @@ def list(
List all connector catalog entries with their auth methods and logos
Args:
+ categories: Optional category filter (exact match against any element in the categories
+ array)
+
include_inactive: Include inactive auth methods (admin only)
search: Optional search query to filter by name, slug, or category (case-insensitive
@@ -105,6 +109,7 @@ def list(
timeout=timeout,
query=maybe_transform(
{
+ "categories": categories,
"include_inactive": include_inactive,
"limit": limit,
"offset": offset,
@@ -210,6 +215,7 @@ def with_streaming_response(self) -> AsyncConnectorCatalogResourceWithStreamingR
async def list(
self,
*,
+ categories: SequenceNotStr[str] | Omit = omit,
include_inactive: bool | Omit = omit,
limit: int | Omit = omit,
offset: int | Omit = omit,
@@ -225,6 +231,9 @@ async def list(
List all connector catalog entries with their auth methods and logos
Args:
+ categories: Optional category filter (exact match against any element in the categories
+ array)
+
include_inactive: Include inactive auth methods (admin only)
search: Optional search query to filter by name, slug, or category (case-insensitive
@@ -247,6 +256,7 @@ async def list(
timeout=timeout,
query=await async_maybe_transform(
{
+ "categories": categories,
"include_inactive": include_inactive,
"limit": limit,
"offset": offset,
diff --git a/src/structify/types/connector_catalog_list_params.py b/src/structify/types/connector_catalog_list_params.py
index 7189a9672..3ccf7f44e 100644
--- a/src/structify/types/connector_catalog_list_params.py
+++ b/src/structify/types/connector_catalog_list_params.py
@@ -5,10 +5,18 @@
from typing import Optional
from typing_extensions import TypedDict
+from .._types import SequenceNotStr
+
__all__ = ["ConnectorCatalogListParams"]
class ConnectorCatalogListParams(TypedDict, total=False):
+ categories: SequenceNotStr[str]
+ """
+ Optional category filter (exact match against any element in the categories
+ array)
+ """
+
include_inactive: bool
"""Include inactive auth methods (admin only)"""
diff --git a/tests/api_resources/test_connector_catalog.py b/tests/api_resources/test_connector_catalog.py
index 632fe5174..bae5c1420 100644
--- a/tests/api_resources/test_connector_catalog.py
+++ b/tests/api_resources/test_connector_catalog.py
@@ -33,6 +33,7 @@ def test_method_list(self, client: Structify) -> None:
@parametrize
def test_method_list_with_all_params(self, client: Structify) -> None:
connector_catalog = client.connector_catalog.list(
+ categories=["string"],
include_inactive=True,
limit=0,
offset=0,
@@ -162,6 +163,7 @@ async def test_method_list(self, async_client: AsyncStructify) -> None:
@parametrize
async def test_method_list_with_all_params(self, async_client: AsyncStructify) -> None:
connector_catalog = await async_client.connector_catalog.list(
+ categories=["string"],
include_inactive=True,
limit=0,
offset=0,
From 22b7aeb09997b0d7b8e4320bb5e37860f78874ae Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Wed, 25 Mar 2026 23:38:09 +0000
Subject: [PATCH 102/105] feat: Update from Structify backend changes
---
.stats.yml | 4 ++--
src/structify/_client.py | 12 ++++++------
tests/test_client.py | 16 ++++++++--------
3 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/.stats.yml b/.stats.yml
index 99c9a9b90..d134f8ac2 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-98b70908fefea6e8700e8b59027706c7243ed385df23a6d9677229bde75d0f66.yml
-openapi_spec_hash: c0683fd6f52b8e1ee90ac4c17a908d88
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-2586602c5112a24f3dcee99dd368b1144ca0241867e53cf67ea0a37ffa362b2a.yml
+openapi_spec_hash: 7e401ba01d129571850882a15e2eb04f
config_hash: de97841de67eb76e2acd3a5a6b67a26d
diff --git a/src/structify/_client.py b/src/structify/_client.py
index 213456c0c..66683468f 100644
--- a/src/structify/_client.py
+++ b/src/structify/_client.py
@@ -382,7 +382,7 @@ def _api_key(self) -> dict[str, str]:
api_key = self.api_key
if api_key is None:
return {}
- return {"api_key": api_key}
+ return {"api-key": api_key}
@property
def _session_token(self) -> dict[str, str]:
@@ -402,14 +402,14 @@ def default_headers(self) -> dict[str, str | Omit]:
@override
def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
- if headers.get("api_key") or isinstance(custom_headers.get("api_key"), Omit):
+ if headers.get("api-key") or isinstance(custom_headers.get("api-key"), Omit):
return
if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
return
raise TypeError(
- '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted"'
+ '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted"'
)
def copy(
@@ -770,7 +770,7 @@ def _api_key(self) -> dict[str, str]:
api_key = self.api_key
if api_key is None:
return {}
- return {"api_key": api_key}
+ return {"api-key": api_key}
@property
def _session_token(self) -> dict[str, str]:
@@ -790,14 +790,14 @@ def default_headers(self) -> dict[str, str | Omit]:
@override
def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
- if headers.get("api_key") or isinstance(custom_headers.get("api_key"), Omit):
+ if headers.get("api-key") or isinstance(custom_headers.get("api-key"), Omit):
return
if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
return
raise TypeError(
- '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted"'
+ '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted"'
)
def copy(
diff --git a/tests/test_client.py b/tests/test_client.py
index 378c73e3e..c5f22bc89 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -402,19 +402,19 @@ def test_default_headers_option(self) -> None:
def test_validate_headers(self) -> None:
client = Structify(base_url=base_url, api_key=api_key, _strict_response_validation=True)
request = client._build_request(FinalRequestOptions(method="get", url="/foo"))
- assert request.headers.get("api_key") == api_key
+ assert request.headers.get("api-key") == api_key
with update_env(**{"STRUCTIFY_API_TOKEN": Omit()}):
client2 = Structify(base_url=base_url, api_key=None, _strict_response_validation=True)
with pytest.raises(
TypeError,
- match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted",
+ match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted",
):
client2._build_request(FinalRequestOptions(method="get", url="/foo"))
- request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api_key": Omit()}))
- assert request2.headers.get("api_key") is None
+ request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api-key": Omit()}))
+ assert request2.headers.get("api-key") is None
def test_default_query_option(self) -> None:
client = Structify(
@@ -1312,19 +1312,19 @@ async def test_default_headers_option(self) -> None:
def test_validate_headers(self) -> None:
client = AsyncStructify(base_url=base_url, api_key=api_key, _strict_response_validation=True)
request = client._build_request(FinalRequestOptions(method="get", url="/foo"))
- assert request.headers.get("api_key") == api_key
+ assert request.headers.get("api-key") == api_key
with update_env(**{"STRUCTIFY_API_TOKEN": Omit()}):
client2 = AsyncStructify(base_url=base_url, api_key=None, _strict_response_validation=True)
with pytest.raises(
TypeError,
- match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted",
+ match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted",
):
client2._build_request(FinalRequestOptions(method="get", url="/foo"))
- request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api_key": Omit()}))
- assert request2.headers.get("api_key") is None
+ request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api-key": Omit()}))
+ assert request2.headers.get("api-key") is None
async def test_default_query_option(self) -> None:
client = AsyncStructify(
From 38c67302a084c70b535aa9bbb6594d881e462281 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Thu, 26 Mar 2026 21:20:11 +0000
Subject: [PATCH 103/105] feat: Update from Structify backend changes
---
.stats.yml | 8 +-
api.md | 6 +
src/structify/_client.py | 12 +-
src/structify/resources/admin/jobs.py | 207 +++++++++++++++++-
src/structify/types/admin/__init__.py | 4 +
.../types/admin/job_concurrency_response.py | 28 +++
.../types/admin/job_running_stats_response.py | 37 ++++
.../admin/job_update_concurrency_params.py | 24 ++
.../admin/job_update_concurrency_response.py | 28 +++
tests/api_resources/admin/test_jobs.py | 179 +++++++++++++++
tests/test_client.py | 16 +-
11 files changed, 530 insertions(+), 19 deletions(-)
create mode 100644 src/structify/types/admin/job_concurrency_response.py
create mode 100644 src/structify/types/admin/job_running_stats_response.py
create mode 100644 src/structify/types/admin/job_update_concurrency_params.py
create mode 100644 src/structify/types/admin/job_update_concurrency_response.py
diff --git a/.stats.yml b/.stats.yml
index d134f8ac2..45591bca0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 254
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-2586602c5112a24f3dcee99dd368b1144ca0241867e53cf67ea0a37ffa362b2a.yml
-openapi_spec_hash: 7e401ba01d129571850882a15e2eb04f
-config_hash: de97841de67eb76e2acd3a5a6b67a26d
+configured_endpoints: 257
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/structify%2Fstructify-98b70908fefea6e8700e8b59027706c7243ed385df23a6d9677229bde75d0f66.yml
+openapi_spec_hash: c0683fd6f52b8e1ee90ac4c17a908d88
+config_hash: 5a7e7204a5ad7239167be965bb256616
diff --git a/api.md b/api.md
index c1d1335c2..7bf8b004d 100644
--- a/api.md
+++ b/api.md
@@ -353,7 +353,10 @@ from structify.types.admin import (
AdminDeleteJobsResponse,
AdminListJobsRequestParams,
JobListResponse,
+ JobConcurrencyResponse,
JobKillByUserResponse,
+ JobRunningStatsResponse,
+ JobUpdateConcurrencyResponse,
)
```
@@ -361,7 +364,10 @@ Methods:
- client.admin.jobs.list(\*\*params) -> SyncJobsList[JobListResponse]
- client.admin.jobs.delete(\*\*params) -> AdminDeleteJobsResponse
+- client.admin.jobs.concurrency() -> JobConcurrencyResponse
- client.admin.jobs.kill_by_user(\*\*params) -> JobKillByUserResponse
+- client.admin.jobs.running_stats() -> JobRunningStatsResponse
+- client.admin.jobs.update_concurrency(\*\*params) -> JobUpdateConcurrencyResponse
## Sandbox
diff --git a/src/structify/_client.py b/src/structify/_client.py
index 66683468f..213456c0c 100644
--- a/src/structify/_client.py
+++ b/src/structify/_client.py
@@ -382,7 +382,7 @@ def _api_key(self) -> dict[str, str]:
api_key = self.api_key
if api_key is None:
return {}
- return {"api-key": api_key}
+ return {"api_key": api_key}
@property
def _session_token(self) -> dict[str, str]:
@@ -402,14 +402,14 @@ def default_headers(self) -> dict[str, str | Omit]:
@override
def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
- if headers.get("api-key") or isinstance(custom_headers.get("api-key"), Omit):
+ if headers.get("api_key") or isinstance(custom_headers.get("api_key"), Omit):
return
if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
return
raise TypeError(
- '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted"'
+ '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted"'
)
def copy(
@@ -770,7 +770,7 @@ def _api_key(self) -> dict[str, str]:
api_key = self.api_key
if api_key is None:
return {}
- return {"api-key": api_key}
+ return {"api_key": api_key}
@property
def _session_token(self) -> dict[str, str]:
@@ -790,14 +790,14 @@ def default_headers(self) -> dict[str, str | Omit]:
@override
def _validate_headers(self, headers: Headers, custom_headers: Headers) -> None:
- if headers.get("api-key") or isinstance(custom_headers.get("api-key"), Omit):
+ if headers.get("api_key") or isinstance(custom_headers.get("api_key"), Omit):
return
if headers.get("Authorization") or isinstance(custom_headers.get("Authorization"), Omit):
return
raise TypeError(
- '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted"'
+ '"Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted"'
)
def copy(
diff --git a/src/structify/resources/admin/jobs.py b/src/structify/resources/admin/jobs.py
index c95c5fb48..424b118db 100644
--- a/src/structify/resources/admin/jobs.py
+++ b/src/structify/resources/admin/jobs.py
@@ -18,11 +18,14 @@
async_to_streamed_response_wrapper,
)
from ...pagination import SyncJobsList, AsyncJobsList
-from ...types.admin import job_list_params, job_delete_params, job_kill_by_user_params
+from ...types.admin import job_list_params, job_delete_params, job_kill_by_user_params, job_update_concurrency_params
from ..._base_client import AsyncPaginator, make_request_options
from ...types.admin.job_list_response import JobListResponse
+from ...types.admin.job_concurrency_response import JobConcurrencyResponse
from ...types.admin.job_kill_by_user_response import JobKillByUserResponse
from ...types.admin.admin_delete_jobs_response import AdminDeleteJobsResponse
+from ...types.admin.job_running_stats_response import JobRunningStatsResponse
+from ...types.admin.job_update_concurrency_response import JobUpdateConcurrencyResponse
__all__ = ["JobsResource", "AsyncJobsResource"]
@@ -127,6 +130,24 @@ def delete(
cast_to=AdminDeleteJobsResponse,
)
+ def concurrency(
+ self,
+ *,
+ # 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,
+ ) -> JobConcurrencyResponse:
+ return self._get(
+ "/admin/jobs/concurrency_limits",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobConcurrencyResponse,
+ )
+
def kill_by_user(
self,
*,
@@ -157,6 +178,71 @@ def kill_by_user(
cast_to=JobKillByUserResponse,
)
+ def running_stats(
+ self,
+ *,
+ # 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,
+ ) -> JobRunningStatsResponse:
+ return self._get(
+ "/admin/jobs/running_stats",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobRunningStatsResponse,
+ )
+
+ def update_concurrency(
+ self,
+ *,
+ max_connector_explore_jobs: Optional[int] | Omit = omit,
+ max_derive_jobs: Optional[int] | Omit = omit,
+ max_match_jobs: Optional[int] | Omit = omit,
+ max_pdf_jobs: Optional[int] | Omit = omit,
+ max_scrape_jobs: Optional[int] | Omit = omit,
+ max_total_jobs: Optional[int] | Omit = omit,
+ max_web_jobs: Optional[int] | 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,
+ ) -> JobUpdateConcurrencyResponse:
+ """
+ Args:
+ 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
+ """
+ return self._put(
+ "/admin/jobs/concurrency_limits",
+ body=maybe_transform(
+ {
+ "max_connector_explore_jobs": max_connector_explore_jobs,
+ "max_derive_jobs": max_derive_jobs,
+ "max_match_jobs": max_match_jobs,
+ "max_pdf_jobs": max_pdf_jobs,
+ "max_scrape_jobs": max_scrape_jobs,
+ "max_total_jobs": max_total_jobs,
+ "max_web_jobs": max_web_jobs,
+ },
+ job_update_concurrency_params.JobUpdateConcurrencyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobUpdateConcurrencyResponse,
+ )
+
class AsyncJobsResource(AsyncAPIResource):
"""Admin endpoints"""
@@ -258,6 +344,24 @@ async def delete(
cast_to=AdminDeleteJobsResponse,
)
+ async def concurrency(
+ self,
+ *,
+ # 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,
+ ) -> JobConcurrencyResponse:
+ return await self._get(
+ "/admin/jobs/concurrency_limits",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobConcurrencyResponse,
+ )
+
async def kill_by_user(
self,
*,
@@ -288,6 +392,71 @@ async def kill_by_user(
cast_to=JobKillByUserResponse,
)
+ async def running_stats(
+ self,
+ *,
+ # 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,
+ ) -> JobRunningStatsResponse:
+ return await self._get(
+ "/admin/jobs/running_stats",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobRunningStatsResponse,
+ )
+
+ async def update_concurrency(
+ self,
+ *,
+ max_connector_explore_jobs: Optional[int] | Omit = omit,
+ max_derive_jobs: Optional[int] | Omit = omit,
+ max_match_jobs: Optional[int] | Omit = omit,
+ max_pdf_jobs: Optional[int] | Omit = omit,
+ max_scrape_jobs: Optional[int] | Omit = omit,
+ max_total_jobs: Optional[int] | Omit = omit,
+ max_web_jobs: Optional[int] | 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,
+ ) -> JobUpdateConcurrencyResponse:
+ """
+ Args:
+ 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
+ """
+ return await self._put(
+ "/admin/jobs/concurrency_limits",
+ body=await async_maybe_transform(
+ {
+ "max_connector_explore_jobs": max_connector_explore_jobs,
+ "max_derive_jobs": max_derive_jobs,
+ "max_match_jobs": max_match_jobs,
+ "max_pdf_jobs": max_pdf_jobs,
+ "max_scrape_jobs": max_scrape_jobs,
+ "max_total_jobs": max_total_jobs,
+ "max_web_jobs": max_web_jobs,
+ },
+ job_update_concurrency_params.JobUpdateConcurrencyParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=JobUpdateConcurrencyResponse,
+ )
+
class JobsResourceWithRawResponse:
def __init__(self, jobs: JobsResource) -> None:
@@ -299,9 +468,18 @@ def __init__(self, jobs: JobsResource) -> None:
self.delete = to_raw_response_wrapper(
jobs.delete,
)
+ self.concurrency = to_raw_response_wrapper(
+ jobs.concurrency,
+ )
self.kill_by_user = to_raw_response_wrapper(
jobs.kill_by_user,
)
+ self.running_stats = to_raw_response_wrapper(
+ jobs.running_stats,
+ )
+ self.update_concurrency = to_raw_response_wrapper(
+ jobs.update_concurrency,
+ )
class AsyncJobsResourceWithRawResponse:
@@ -314,9 +492,18 @@ def __init__(self, jobs: AsyncJobsResource) -> None:
self.delete = async_to_raw_response_wrapper(
jobs.delete,
)
+ self.concurrency = async_to_raw_response_wrapper(
+ jobs.concurrency,
+ )
self.kill_by_user = async_to_raw_response_wrapper(
jobs.kill_by_user,
)
+ self.running_stats = async_to_raw_response_wrapper(
+ jobs.running_stats,
+ )
+ self.update_concurrency = async_to_raw_response_wrapper(
+ jobs.update_concurrency,
+ )
class JobsResourceWithStreamingResponse:
@@ -329,9 +516,18 @@ def __init__(self, jobs: JobsResource) -> None:
self.delete = to_streamed_response_wrapper(
jobs.delete,
)
+ self.concurrency = to_streamed_response_wrapper(
+ jobs.concurrency,
+ )
self.kill_by_user = to_streamed_response_wrapper(
jobs.kill_by_user,
)
+ self.running_stats = to_streamed_response_wrapper(
+ jobs.running_stats,
+ )
+ self.update_concurrency = to_streamed_response_wrapper(
+ jobs.update_concurrency,
+ )
class AsyncJobsResourceWithStreamingResponse:
@@ -344,6 +540,15 @@ def __init__(self, jobs: AsyncJobsResource) -> None:
self.delete = async_to_streamed_response_wrapper(
jobs.delete,
)
+ self.concurrency = async_to_streamed_response_wrapper(
+ jobs.concurrency,
+ )
self.kill_by_user = async_to_streamed_response_wrapper(
jobs.kill_by_user,
)
+ self.running_stats = async_to_streamed_response_wrapper(
+ jobs.running_stats,
+ )
+ self.update_concurrency = async_to_streamed_response_wrapper(
+ jobs.update_concurrency,
+ )
diff --git a/src/structify/types/admin/__init__.py b/src/structify/types/admin/__init__.py
index d07081a7d..8422f8b82 100644
--- a/src/structify/types/admin/__init__.py
+++ b/src/structify/types/admin/__init__.py
@@ -27,6 +27,7 @@
from .user_impersonate_params import UserImpersonateParams as UserImpersonateParams
from .connector_clone_response import ConnectorCloneResponse as ConnectorCloneResponse
from .dataset_get_by_id_params import DatasetGetByIDParams as DatasetGetByIDParams
+from .job_concurrency_response import JobConcurrencyResponse as JobConcurrencyResponse
from .team_extend_trial_params import TeamExtendTrialParams as TeamExtendTrialParams
from .admin_add_member_response import AdminAddMemberResponse as AdminAddMemberResponse
from .admin_teams_list_response import AdminTeamsListResponse as AdminTeamsListResponse
@@ -37,6 +38,7 @@
from .team_remove_member_params import TeamRemoveMemberParams as TeamRemoveMemberParams
from .admin_delete_jobs_response import AdminDeleteJobsResponse as AdminDeleteJobsResponse
from .clone_connector_item_param import CloneConnectorItemParam as CloneConnectorItemParam
+from .job_running_stats_response import JobRunningStatsResponse as JobRunningStatsResponse
from .admin_list_members_response import AdminListMembersResponse as AdminListMembersResponse
from .chat_template_create_params import ChatTemplateCreateParams as ChatTemplateCreateParams
from .chat_template_list_response import ChatTemplateListResponse as ChatTemplateListResponse
@@ -46,8 +48,10 @@
from .create_subscription_response import CreateSubscriptionResponse as CreateSubscriptionResponse
from .functional_test_create_params import FunctionalTestCreateParams as FunctionalTestCreateParams
from .functional_test_list_response import FunctionalTestListResponse as FunctionalTestListResponse
+from .job_update_concurrency_params import JobUpdateConcurrencyParams as JobUpdateConcurrencyParams
from .admin_list_connectors_response import AdminListConnectorsResponse as AdminListConnectorsResponse
from .update_seats_override_response import UpdateSeatsOverrideResponse as UpdateSeatsOverrideResponse
+from .job_update_concurrency_response import JobUpdateConcurrencyResponse as JobUpdateConcurrencyResponse
from .team_cancel_subscription_params import TeamCancelSubscriptionParams as TeamCancelSubscriptionParams
from .team_create_subscription_params import TeamCreateSubscriptionParams as TeamCreateSubscriptionParams
from .functional_test_link_chat_params import FunctionalTestLinkChatParams as FunctionalTestLinkChatParams
diff --git a/src/structify/types/admin/job_concurrency_response.py b/src/structify/types/admin/job_concurrency_response.py
new file mode 100644
index 000000000..8932c09d4
--- /dev/null
+++ b/src/structify/types/admin/job_concurrency_response.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from ..._models import BaseModel
+
+__all__ = ["JobConcurrencyResponse"]
+
+
+class JobConcurrencyResponse(BaseModel):
+ id: int
+
+ updated_at: datetime
+
+ max_connector_explore_jobs: Optional[int] = None
+
+ max_derive_jobs: Optional[int] = None
+
+ max_match_jobs: Optional[int] = None
+
+ max_pdf_jobs: Optional[int] = None
+
+ max_scrape_jobs: Optional[int] = None
+
+ max_total_jobs: Optional[int] = None
+
+ max_web_jobs: Optional[int] = None
diff --git a/src/structify/types/admin/job_running_stats_response.py b/src/structify/types/admin/job_running_stats_response.py
new file mode 100644
index 000000000..8f0d2f748
--- /dev/null
+++ b/src/structify/types/admin/job_running_stats_response.py
@@ -0,0 +1,37 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List
+
+from ..._models import BaseModel
+
+__all__ = ["JobRunningStatsResponse", "ByType", "ByUser"]
+
+
+class ByType(BaseModel):
+ count: int
+
+ job_type: str
+
+
+class ByUser(BaseModel):
+ email: str
+
+ queued: int
+
+ running: int
+
+ user_id: str
+
+
+class JobRunningStatsResponse(BaseModel):
+ by_type: List[ByType]
+
+ by_user: List[ByUser]
+
+ completed_last_hour: int
+
+ failed_last_hour: int
+
+ total_queued: int
+
+ total_running: int
diff --git a/src/structify/types/admin/job_update_concurrency_params.py b/src/structify/types/admin/job_update_concurrency_params.py
new file mode 100644
index 000000000..5cbbdc869
--- /dev/null
+++ b/src/structify/types/admin/job_update_concurrency_params.py
@@ -0,0 +1,24 @@
+# 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__ = ["JobUpdateConcurrencyParams"]
+
+
+class JobUpdateConcurrencyParams(TypedDict, total=False):
+ max_connector_explore_jobs: Optional[int]
+
+ max_derive_jobs: Optional[int]
+
+ max_match_jobs: Optional[int]
+
+ max_pdf_jobs: Optional[int]
+
+ max_scrape_jobs: Optional[int]
+
+ max_total_jobs: Optional[int]
+
+ max_web_jobs: Optional[int]
diff --git a/src/structify/types/admin/job_update_concurrency_response.py b/src/structify/types/admin/job_update_concurrency_response.py
new file mode 100644
index 000000000..82b1ce3f3
--- /dev/null
+++ b/src/structify/types/admin/job_update_concurrency_response.py
@@ -0,0 +1,28 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import Optional
+from datetime import datetime
+
+from ..._models import BaseModel
+
+__all__ = ["JobUpdateConcurrencyResponse"]
+
+
+class JobUpdateConcurrencyResponse(BaseModel):
+ id: int
+
+ updated_at: datetime
+
+ max_connector_explore_jobs: Optional[int] = None
+
+ max_derive_jobs: Optional[int] = None
+
+ max_match_jobs: Optional[int] = None
+
+ max_pdf_jobs: Optional[int] = None
+
+ max_scrape_jobs: Optional[int] = None
+
+ max_total_jobs: Optional[int] = None
+
+ max_web_jobs: Optional[int] = None
diff --git a/tests/api_resources/admin/test_jobs.py b/tests/api_resources/admin/test_jobs.py
index ac3210575..2ae99cb3f 100644
--- a/tests/api_resources/admin/test_jobs.py
+++ b/tests/api_resources/admin/test_jobs.py
@@ -13,7 +13,10 @@
from structify.types.admin import (
JobListResponse,
JobKillByUserResponse,
+ JobConcurrencyResponse,
AdminDeleteJobsResponse,
+ JobRunningStatsResponse,
+ JobUpdateConcurrencyResponse,
)
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -89,6 +92,31 @@ def test_streaming_response_delete(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_concurrency(self, client: Structify) -> None:
+ job = client.admin.jobs.concurrency()
+ assert_matches_type(JobConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ def test_raw_response_concurrency(self, client: Structify) -> None:
+ response = client.admin.jobs.with_raw_response.concurrency()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = response.parse()
+ assert_matches_type(JobConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ def test_streaming_response_concurrency(self, client: Structify) -> None:
+ with client.admin.jobs.with_streaming_response.concurrency() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = response.parse()
+ assert_matches_type(JobConcurrencyResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
def test_method_kill_by_user(self, client: Structify) -> None:
job = client.admin.jobs.kill_by_user(
@@ -120,6 +148,69 @@ def test_streaming_response_kill_by_user(self, client: Structify) -> None:
assert cast(Any, response.is_closed) is True
+ @parametrize
+ def test_method_running_stats(self, client: Structify) -> None:
+ job = client.admin.jobs.running_stats()
+ assert_matches_type(JobRunningStatsResponse, job, path=["response"])
+
+ @parametrize
+ def test_raw_response_running_stats(self, client: Structify) -> None:
+ response = client.admin.jobs.with_raw_response.running_stats()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = response.parse()
+ assert_matches_type(JobRunningStatsResponse, job, path=["response"])
+
+ @parametrize
+ def test_streaming_response_running_stats(self, client: Structify) -> None:
+ with client.admin.jobs.with_streaming_response.running_stats() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = response.parse()
+ assert_matches_type(JobRunningStatsResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ def test_method_update_concurrency(self, client: Structify) -> None:
+ job = client.admin.jobs.update_concurrency()
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ def test_method_update_concurrency_with_all_params(self, client: Structify) -> None:
+ job = client.admin.jobs.update_concurrency(
+ max_connector_explore_jobs=0,
+ max_derive_jobs=0,
+ max_match_jobs=0,
+ max_pdf_jobs=0,
+ max_scrape_jobs=0,
+ max_total_jobs=0,
+ max_web_jobs=0,
+ )
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ def test_raw_response_update_concurrency(self, client: Structify) -> None:
+ response = client.admin.jobs.with_raw_response.update_concurrency()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = response.parse()
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ def test_streaming_response_update_concurrency(self, client: Structify) -> None:
+ with client.admin.jobs.with_streaming_response.update_concurrency() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = response.parse()
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
class TestAsyncJobs:
parametrize = pytest.mark.parametrize(
@@ -193,6 +284,31 @@ async def test_streaming_response_delete(self, async_client: AsyncStructify) ->
assert cast(Any, response.is_closed) is True
+ @parametrize
+ async def test_method_concurrency(self, async_client: AsyncStructify) -> None:
+ job = await async_client.admin.jobs.concurrency()
+ assert_matches_type(JobConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ async def test_raw_response_concurrency(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.jobs.with_raw_response.concurrency()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = await response.parse()
+ assert_matches_type(JobConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_concurrency(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.jobs.with_streaming_response.concurrency() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = await response.parse()
+ assert_matches_type(JobConcurrencyResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
@parametrize
async def test_method_kill_by_user(self, async_client: AsyncStructify) -> None:
job = await async_client.admin.jobs.kill_by_user(
@@ -223,3 +339,66 @@ async def test_streaming_response_kill_by_user(self, async_client: AsyncStructif
assert_matches_type(JobKillByUserResponse, job, path=["response"])
assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_running_stats(self, async_client: AsyncStructify) -> None:
+ job = await async_client.admin.jobs.running_stats()
+ assert_matches_type(JobRunningStatsResponse, job, path=["response"])
+
+ @parametrize
+ async def test_raw_response_running_stats(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.jobs.with_raw_response.running_stats()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = await response.parse()
+ assert_matches_type(JobRunningStatsResponse, job, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_running_stats(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.jobs.with_streaming_response.running_stats() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = await response.parse()
+ assert_matches_type(JobRunningStatsResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @parametrize
+ async def test_method_update_concurrency(self, async_client: AsyncStructify) -> None:
+ job = await async_client.admin.jobs.update_concurrency()
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ async def test_method_update_concurrency_with_all_params(self, async_client: AsyncStructify) -> None:
+ job = await async_client.admin.jobs.update_concurrency(
+ max_connector_explore_jobs=0,
+ max_derive_jobs=0,
+ max_match_jobs=0,
+ max_pdf_jobs=0,
+ max_scrape_jobs=0,
+ max_total_jobs=0,
+ max_web_jobs=0,
+ )
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ async def test_raw_response_update_concurrency(self, async_client: AsyncStructify) -> None:
+ response = await async_client.admin.jobs.with_raw_response.update_concurrency()
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ job = await response.parse()
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ @parametrize
+ async def test_streaming_response_update_concurrency(self, async_client: AsyncStructify) -> None:
+ async with async_client.admin.jobs.with_streaming_response.update_concurrency() as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ job = await response.parse()
+ assert_matches_type(JobUpdateConcurrencyResponse, job, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
diff --git a/tests/test_client.py b/tests/test_client.py
index c5f22bc89..378c73e3e 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -402,19 +402,19 @@ def test_default_headers_option(self) -> None:
def test_validate_headers(self) -> None:
client = Structify(base_url=base_url, api_key=api_key, _strict_response_validation=True)
request = client._build_request(FinalRequestOptions(method="get", url="/foo"))
- assert request.headers.get("api-key") == api_key
+ assert request.headers.get("api_key") == api_key
with update_env(**{"STRUCTIFY_API_TOKEN": Omit()}):
client2 = Structify(base_url=base_url, api_key=None, _strict_response_validation=True)
with pytest.raises(
TypeError,
- match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted",
+ match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted",
):
client2._build_request(FinalRequestOptions(method="get", url="/foo"))
- request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api-key": Omit()}))
- assert request2.headers.get("api-key") is None
+ request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api_key": Omit()}))
+ assert request2.headers.get("api_key") is None
def test_default_query_option(self) -> None:
client = Structify(
@@ -1312,19 +1312,19 @@ async def test_default_headers_option(self) -> None:
def test_validate_headers(self) -> None:
client = AsyncStructify(base_url=base_url, api_key=api_key, _strict_response_validation=True)
request = client._build_request(FinalRequestOptions(method="get", url="/foo"))
- assert request.headers.get("api-key") == api_key
+ assert request.headers.get("api_key") == api_key
with update_env(**{"STRUCTIFY_API_TOKEN": Omit()}):
client2 = AsyncStructify(base_url=base_url, api_key=None, _strict_response_validation=True)
with pytest.raises(
TypeError,
- match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api-key` or `Authorization` headers to be explicitly omitted",
+ match="Could not resolve authentication method. Expected either api_key or session_token to be set. Or for one of the `api_key` or `Authorization` headers to be explicitly omitted",
):
client2._build_request(FinalRequestOptions(method="get", url="/foo"))
- request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api-key": Omit()}))
- assert request2.headers.get("api-key") is None
+ request2 = client2._build_request(FinalRequestOptions(method="get", url="/foo", headers={"api_key": Omit()}))
+ assert request2.headers.get("api_key") is None
async def test_default_query_option(self) -> None:
client = AsyncStructify(
From 6d5a683526efc84586e87f86bf187aed79d2be5b Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Mar 2026 02:25:43 +0000
Subject: [PATCH 104/105] feat(internal): implement indices array format for
query and form serialization
---
scripts/mock | 4 ++--
scripts/test | 2 +-
src/structify/_qs.py | 5 ++++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/scripts/mock b/scripts/mock
index 09eb49f65..290e21b9a 100755
--- a/scripts/mock
+++ b/scripts/mock
@@ -24,7 +24,7 @@ if [ "$1" == "--daemon" ]; then
# Pre-install the package so the download doesn't eat into the startup timeout
npm exec --package=@stdy/cli@0.19.7 -- steady --version
- npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL" &> .stdy.log &
+ npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log &
# Wait for server to come online via health endpoint (max 30s)
echo -n "Waiting for server"
@@ -48,5 +48,5 @@ if [ "$1" == "--daemon" ]; then
echo
else
- npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets "$URL"
+ npm exec --package=@stdy/cli@0.19.7 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL"
fi
diff --git a/scripts/test b/scripts/test
index e46b9b58d..661f9bf48 100755
--- a/scripts/test
+++ b/scripts/test
@@ -43,7 +43,7 @@ elif ! steady_is_running ; then
echo -e "To run the server, pass in the path or url of your OpenAPI"
echo -e "spec to the steady command:"
echo
- echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-form-array-format=comma --validator-query-array-format=comma --validator-form-object-format=brackets --validator-query-object-format=brackets${NC}"
+ echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.19.7 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=comma --validator-form-array-format=comma --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}"
echo
exit 1
diff --git a/src/structify/_qs.py b/src/structify/_qs.py
index ada6fd3f7..de8c99bc6 100644
--- a/src/structify/_qs.py
+++ b/src/structify/_qs.py
@@ -101,7 +101,10 @@ def _stringify_item(
items.extend(self._stringify_item(key, item, opts))
return items
elif array_format == "indices":
- raise NotImplementedError("The array indices format is not supported yet")
+ items = []
+ for i, item in enumerate(value):
+ items.extend(self._stringify_item(f"{key}[{i}]", item, opts))
+ return items
elif array_format == "brackets":
items = []
key = key + "[]"
From 90b9c6b6bad6b62d682f6f11cd4bf4b2eee5086d Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 27 Mar 2026 02:26:42 +0000
Subject: [PATCH 105/105] release: 1.184.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 118 ++++++++++++++++++++++++++++++++++
pyproject.toml | 2 +-
src/structify/_version.py | 2 +-
4 files changed, 121 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 4d3d04fcb..592985c16 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.183.0"
+ ".": "1.184.0"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f1d6ced3..2385ff3f6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,123 @@
# Changelog
+## 1.184.0 (2026-03-27)
+
+Full Changelog: [v1.183.0...v1.184.0](https://github.com/StructifyAI/structify-python/compare/v1.183.0...v1.184.0)
+
+### Features
+
+* **api:** api update ([60cf087](https://github.com/StructifyAI/structify-python/commit/60cf0874a5e1299c02ca7dea7118ae831c51e6ef))
+* **internal:** implement indices array format for query and form serialization ([6d5a683](https://github.com/StructifyAI/structify-python/commit/6d5a683526efc84586e87f86bf187aed79d2be5b))
+* Update from Structify backend changes ([38c6730](https://github.com/StructifyAI/structify-python/commit/38c67302a084c70b535aa9bbb6594d881e462281))
+* Update from Structify backend changes ([22b7aeb](https://github.com/StructifyAI/structify-python/commit/22b7aeb09997b0d7b8e4320bb5e37860f78874ae))
+* Update from Structify backend changes ([5e74183](https://github.com/StructifyAI/structify-python/commit/5e74183af52a15223e47a86c12e278fa9baae23e))
+* Update from Structify backend changes ([2957a79](https://github.com/StructifyAI/structify-python/commit/2957a7945ff54a0e447255d37665aae07750f368))
+* Update from Structify backend changes ([9c85788](https://github.com/StructifyAI/structify-python/commit/9c8578843117aabfed6c177eef54dd55b32153d4))
+* Update from Structify backend changes ([7300ef1](https://github.com/StructifyAI/structify-python/commit/7300ef146472dae2bc013c407e3dc21806adb8ba))
+* Update from Structify backend changes ([9ccbf40](https://github.com/StructifyAI/structify-python/commit/9ccbf40f09c05630249647b7f4a24ee75de96159))
+* Update from Structify backend changes ([856162a](https://github.com/StructifyAI/structify-python/commit/856162a9e8724dda056be17cf39157a3a2d2b733))
+* Update from Structify backend changes ([0135605](https://github.com/StructifyAI/structify-python/commit/01356050e6b8ca81b73063513a3620830ce2d84f))
+* Update from Structify backend changes ([cb2bde3](https://github.com/StructifyAI/structify-python/commit/cb2bde357153c0bc2d0b145868e0d62915f4f952))
+* Update from Structify backend changes ([a1eb77b](https://github.com/StructifyAI/structify-python/commit/a1eb77bd78add7544ae5bc0d72535d317ee23098))
+* Update from Structify backend changes ([bde5a39](https://github.com/StructifyAI/structify-python/commit/bde5a390b285b282578bb6b4857285b2abd23491))
+* Update from Structify backend changes ([ca4fa72](https://github.com/StructifyAI/structify-python/commit/ca4fa72263d7eb09ba0aa91e2d0e32b1d724bbc1))
+* Update from Structify backend changes ([37cd67f](https://github.com/StructifyAI/structify-python/commit/37cd67f7a018a7d6b37aea2646ca1f9d5559977d))
+* Update from Structify backend changes ([387dd18](https://github.com/StructifyAI/structify-python/commit/387dd1845dfe380e4f36dfa592b57e3131f76fed))
+* Update from Structify backend changes ([d31cd4b](https://github.com/StructifyAI/structify-python/commit/d31cd4b98af129060626b47828b9d99dfae6dbce))
+* Update from Structify backend changes ([da0f0de](https://github.com/StructifyAI/structify-python/commit/da0f0de6d612197df5fd6c85d493e25474f71f1b))
+* Update from Structify backend changes ([2db1ef6](https://github.com/StructifyAI/structify-python/commit/2db1ef601ecc67ffb5696f4cf8cdd6e92e8915bf))
+* Update from Structify backend changes ([ac9f0d5](https://github.com/StructifyAI/structify-python/commit/ac9f0d53b217e035ccbb75d026593634e054f117))
+* Update from Structify backend changes ([5a23230](https://github.com/StructifyAI/structify-python/commit/5a232300a64a4d64671f8167da883d3b80389b9b))
+* Update from Structify backend changes ([234176c](https://github.com/StructifyAI/structify-python/commit/234176cb1e424b08de929ee3445ab3ccf6c85105))
+* Update from Structify backend changes ([9586986](https://github.com/StructifyAI/structify-python/commit/9586986c012ee305ab90de33c7d74ea715becee2))
+* Update from Structify backend changes ([4ec4f4f](https://github.com/StructifyAI/structify-python/commit/4ec4f4f2c97687d23575d9b235ee1a3aefef648d))
+* Update from Structify backend changes ([9c9b785](https://github.com/StructifyAI/structify-python/commit/9c9b785cb118b656322d0614e6602b1f64f25c9b))
+* Update from Structify backend changes ([0175b62](https://github.com/StructifyAI/structify-python/commit/0175b62731b9c9e7cc3a2069b32ed44fae801df2))
+* Update from Structify backend changes ([e8fa6c0](https://github.com/StructifyAI/structify-python/commit/e8fa6c0eee8eef620bd297933c4bbff1da13b798))
+* Update from Structify backend changes ([2d67a15](https://github.com/StructifyAI/structify-python/commit/2d67a154e0b37a1a29e35e21678b059a8cfe1e85))
+* Update from Structify backend changes ([aa26452](https://github.com/StructifyAI/structify-python/commit/aa264524de4459f4977103f5884778d5b3e5200f))
+* Update from Structify backend changes ([6cdb36b](https://github.com/StructifyAI/structify-python/commit/6cdb36ba947a077d7a4ea24ec416da65d2cf4c3f))
+* Update from Structify backend changes ([20ef4cf](https://github.com/StructifyAI/structify-python/commit/20ef4cf65fbf656dec67a065725fc4931a224912))
+* Update from Structify backend changes ([38e454b](https://github.com/StructifyAI/structify-python/commit/38e454b00abe1dbd46adcbcf73e01f0babae4faa))
+* Update from Structify backend changes ([74d1ead](https://github.com/StructifyAI/structify-python/commit/74d1eadcaade7a9bf4f43a968b34a69441647b47))
+* Update from Structify backend changes ([9f87667](https://github.com/StructifyAI/structify-python/commit/9f876676e531c57f0133d2a413bf739d3f7f93cc))
+* Update from Structify backend changes ([e348c2a](https://github.com/StructifyAI/structify-python/commit/e348c2a7b58b48e7c5655757a098bea70033b2b9))
+* Update from Structify backend changes ([c4ccd37](https://github.com/StructifyAI/structify-python/commit/c4ccd37bdf1803dfceb77762fb2c50a960ec4e27))
+* Update from Structify backend changes ([4148cb4](https://github.com/StructifyAI/structify-python/commit/4148cb4b20cbe6cf0ca8371d0d4c602a80f5a764))
+* Update from Structify backend changes ([3536c2c](https://github.com/StructifyAI/structify-python/commit/3536c2cb1daa0eadb86d4966210d1a4bbe45c2c9))
+* Update from Structify backend changes ([95228ad](https://github.com/StructifyAI/structify-python/commit/95228adc1fd74e0ebec420fabceed3d133c2f7be))
+* Update from Structify backend changes ([1df1a86](https://github.com/StructifyAI/structify-python/commit/1df1a867e1490126f24a42ad3c2e16cdc485e92d))
+* Update from Structify backend changes ([59a5760](https://github.com/StructifyAI/structify-python/commit/59a57607f5c573af3639642bfaa20b8bd59f2f8d))
+* Update from Structify backend changes ([761ede8](https://github.com/StructifyAI/structify-python/commit/761ede84e233b966e824ac0aba9bc27b73567f48))
+* Update from Structify backend changes ([bb8b31f](https://github.com/StructifyAI/structify-python/commit/bb8b31f20614a17e816c2ba850429eb0ed71650e))
+* Update from Structify backend changes ([e6f9de0](https://github.com/StructifyAI/structify-python/commit/e6f9de054fb1e15331baa2949f171b9284e83690))
+* Update from Structify backend changes ([74b1b21](https://github.com/StructifyAI/structify-python/commit/74b1b217602570cb51c926fb93057318b4e63a81))
+* Update from Structify backend changes ([27ab73d](https://github.com/StructifyAI/structify-python/commit/27ab73d19b4c16c19c1b95015d3a10cd4d9bd58f))
+* Update from Structify backend changes ([003a774](https://github.com/StructifyAI/structify-python/commit/003a774cb8dd043eda2b550b00acdb9e9e3b5a64))
+* Update from Structify backend changes ([37cc1d9](https://github.com/StructifyAI/structify-python/commit/37cc1d9c7a286de5680f51b9f97125d824022cf1))
+* Update from Structify backend changes ([1e163ca](https://github.com/StructifyAI/structify-python/commit/1e163ca21cb69ea540293df7fa86a2edd74b9c6a))
+* Update from Structify backend changes ([f0e673a](https://github.com/StructifyAI/structify-python/commit/f0e673a1faeef8766e2a3d315c13efea2e1e27fd))
+* Update from Structify backend changes ([06905d3](https://github.com/StructifyAI/structify-python/commit/06905d33be13a97cb80f22d04354695456429e7f))
+* Update from Structify backend changes ([7b2a30a](https://github.com/StructifyAI/structify-python/commit/7b2a30a861fb15068c26b16f4dc6f8fc9de7a59c))
+* Update from Structify backend changes ([11b106e](https://github.com/StructifyAI/structify-python/commit/11b106e4ed0d8d8990206878d403f3462f244b67))
+* Update from Structify backend changes ([657d6aa](https://github.com/StructifyAI/structify-python/commit/657d6aae3f7758ec809f7e41a7805405dfe617b7))
+* Update from Structify backend changes ([e3ad58e](https://github.com/StructifyAI/structify-python/commit/e3ad58e6c063c306aa5e481ec97c74cf4e3ba313))
+* Update from Structify backend changes ([8be62b6](https://github.com/StructifyAI/structify-python/commit/8be62b67db9556a1a8dbd7f7cc5080ae2e164cde))
+* Update from Structify backend changes ([46fc19d](https://github.com/StructifyAI/structify-python/commit/46fc19ded10bfac99a76d2c3a4a3f08d271c25e5))
+* Update from Structify backend changes ([06d6f58](https://github.com/StructifyAI/structify-python/commit/06d6f5872b86da5de923d0657b0c340f312d42ec))
+* Update from Structify backend changes ([d28fc51](https://github.com/StructifyAI/structify-python/commit/d28fc512323f5c7eecd56e086a6894c4e2ea2794))
+* Update from Structify backend changes ([3e01edf](https://github.com/StructifyAI/structify-python/commit/3e01edfbfeb5703f1e52a8d5fd7d7825a49adec3))
+* Update from Structify backend changes ([ffda5ed](https://github.com/StructifyAI/structify-python/commit/ffda5ed618ac602e2e9287512f4b0876c421d741))
+* Update from Structify backend changes ([ef67e88](https://github.com/StructifyAI/structify-python/commit/ef67e8857e56940b6d8f7b7d351ce8bf6d2d6d29))
+* Update from Structify backend changes ([6f8c059](https://github.com/StructifyAI/structify-python/commit/6f8c059edc0ed2a5fb61c805f3a28ece6397f207))
+* Update from Structify backend changes ([ab6c580](https://github.com/StructifyAI/structify-python/commit/ab6c580596d6cb790650173533f43d647651e25a))
+* Update from Structify backend changes ([9091cce](https://github.com/StructifyAI/structify-python/commit/9091cce1f24daa6ec1079c5b313a8c212173f835))
+* Update from Structify backend changes ([fdc379a](https://github.com/StructifyAI/structify-python/commit/fdc379a0fbc2ecc263f473553bded63e671a5640))
+* Update from Structify backend changes ([68e0e5a](https://github.com/StructifyAI/structify-python/commit/68e0e5a43037252590cf8a697d4b78760c4a7260))
+* Update from Structify backend changes ([7822818](https://github.com/StructifyAI/structify-python/commit/782281890bbcb0117c542df7072e167a4b978a1d))
+* Update from Structify backend changes ([5c40f7b](https://github.com/StructifyAI/structify-python/commit/5c40f7b6977787dee2e1d96b1b13a4379229f38a))
+* Update from Structify backend changes ([6cbcd7d](https://github.com/StructifyAI/structify-python/commit/6cbcd7d9e1c0374a9d6780e44f107ba37bea8d4f))
+* Update from Structify backend changes ([f733d2a](https://github.com/StructifyAI/structify-python/commit/f733d2aad89b62c283d279a02d341d2b05a6357e))
+* Update from Structify backend changes ([6c64d5c](https://github.com/StructifyAI/structify-python/commit/6c64d5c8b902b82ef046fafbef03dfbe27fbd05c))
+* Update from Structify backend changes ([454d1dd](https://github.com/StructifyAI/structify-python/commit/454d1ddd7f12b025bb552850da43d381f702fb55))
+* Update from Structify backend changes ([04eadec](https://github.com/StructifyAI/structify-python/commit/04eadec50e082e5ce788917a4d7a7e916c4a6765))
+* Update from Structify backend changes ([248cbcb](https://github.com/StructifyAI/structify-python/commit/248cbcb0cb64809d62173317c07498ad37cd83d2))
+* Update from Structify backend changes ([dade595](https://github.com/StructifyAI/structify-python/commit/dade59552964ae2200022f60dc64f17543d225d3))
+* Update from Structify backend changes ([4c65bf1](https://github.com/StructifyAI/structify-python/commit/4c65bf113a5aeada0e0fa77d46c5cacf50632e7a))
+
+
+### Bug Fixes
+
+* **deps:** bump minimum typing-extensions version ([e948f17](https://github.com/StructifyAI/structify-python/commit/e948f171a34d73a5b6e5f6b334a86b6b98180d4d))
+* **pydantic:** do not pass `by_alias` unless set ([ea00e09](https://github.com/StructifyAI/structify-python/commit/ea00e09a4b072323f1f13c2825773257f638c462))
+* sanitize endpoint path params ([dd440d0](https://github.com/StructifyAI/structify-python/commit/dd440d04c277fee4e8373c09bc51b43a951369a1))
+
+
+### Chores
+
+* **ci:** skip lint on metadata-only changes ([a9b43a6](https://github.com/StructifyAI/structify-python/commit/a9b43a66365028af38669fe38d6a6275e70980c0))
+* **ci:** skip uploading artifacts on stainless-internal branches ([e426d6b](https://github.com/StructifyAI/structify-python/commit/e426d6bf94f57c72581cd3289faf17a8dcd4538e))
+* format all `api.md` files ([fc8a112](https://github.com/StructifyAI/structify-python/commit/fc8a112722cb379d824920e3fde59345fdb4df85))
+* **internal:** add request options to SSE classes ([aa6dc7f](https://github.com/StructifyAI/structify-python/commit/aa6dc7fc0ef92720834578efa70fc6661b4b69a8))
+* **internal:** codegen related update ([206ea94](https://github.com/StructifyAI/structify-python/commit/206ea94f15ea80ed61eca73e32ef753a57b2ede7))
+* **internal:** fix lint error on Python 3.14 ([3a7173f](https://github.com/StructifyAI/structify-python/commit/3a7173f56434bada6297dc0b2b25cd77fa0053cb))
+* **internal:** make `test_proxy_environment_variables` more resilient ([3543b8f](https://github.com/StructifyAI/structify-python/commit/3543b8f5f16df6c661e561ecb5d01d5959fc0f72))
+* **internal:** make `test_proxy_environment_variables` more resilient to env ([42b68e8](https://github.com/StructifyAI/structify-python/commit/42b68e89e75ab91d86ee3b492c2a648acd338ad6))
+* **internal:** tweak CI branches ([92ed8ac](https://github.com/StructifyAI/structify-python/commit/92ed8ac799e16266310bc9e66cb8bbcff3e681aa))
+* **internal:** update gitignore ([60f8dcd](https://github.com/StructifyAI/structify-python/commit/60f8dcd5ac4811c83554ec663bd4d457f33539a5))
+* **test:** do not count install time for mock server timeout ([1563f48](https://github.com/StructifyAI/structify-python/commit/1563f48901ebd6545e8eb594370b12019fb47a30))
+* **tests:** bump steady to v0.19.4 ([15d506e](https://github.com/StructifyAI/structify-python/commit/15d506ee5ea1a4a7bf1a0091237718e1f94edad9))
+* **tests:** bump steady to v0.19.5 ([afa480c](https://github.com/StructifyAI/structify-python/commit/afa480c9b5df39ee202220baf8a7dbf7a367eb39))
+* **tests:** bump steady to v0.19.6 ([4dd5324](https://github.com/StructifyAI/structify-python/commit/4dd53245dca023dac6911d512963d2a14b0155b7))
+* **tests:** bump steady to v0.19.7 ([dc20757](https://github.com/StructifyAI/structify-python/commit/dc20757e4e4ae8250f8468084bc71e638238519c))
+* update mock server docs ([c7ba1b2](https://github.com/StructifyAI/structify-python/commit/c7ba1b2e113db5b1df0282216045997064362d93))
+* update placeholder string ([cfb1da4](https://github.com/StructifyAI/structify-python/commit/cfb1da44851a3714a7096d23413a09abae1ecfc5))
+
+
+### Refactors
+
+* **tests:** switch from prism to steady ([cc504ac](https://github.com/StructifyAI/structify-python/commit/cc504acffcde1581af4c46f697b06ff34dfb4643))
+
## 1.183.0 (2026-02-11)
Full Changelog: [v1.182.0...v1.183.0](https://github.com/StructifyAI/structify-python/compare/v1.182.0...v1.183.0)
diff --git a/pyproject.toml b/pyproject.toml
index b7b294339..ba360bd07 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "structifyai"
-version = "1.183.0"
+version = "1.184.0"
description = "The official Python library for the structify API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/structify/_version.py b/src/structify/_version.py
index 8f1fc8183..cd8644a6c 100644
--- a/src/structify/_version.py
+++ b/src/structify/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "structify"
-__version__ = "1.183.0" # x-release-please-version
+__version__ = "1.184.0" # x-release-please-version