tinyfish 0.2.5__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {tinyfish-0.2.5 → tinyfish-0.2.6}/PKG-INFO +33 -1
  2. {tinyfish-0.2.5 → tinyfish-0.2.6}/README.md +32 -0
  3. {tinyfish-0.2.5 → tinyfish-0.2.6}/pyproject.toml +8 -3
  4. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/__init__.py +27 -0
  5. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/client/async_.py +10 -0
  6. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/client/sync.py +10 -0
  7. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/resource.py +2 -0
  8. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/agent/__init__.py +146 -6
  9. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/client.py +5 -0
  10. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/fetch/__init__.py +59 -4
  11. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/runs/types.py +4 -0
  12. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/search/__init__.py +36 -0
  13. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/search/types.py +1 -0
  14. tinyfish-0.2.6/src/tinyfish/vault/__init__.py +208 -0
  15. tinyfish-0.2.6/src/tinyfish/vault/types.py +106 -0
  16. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_agent.py +249 -0
  17. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_fetch.py +62 -1
  18. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_runs.py +159 -0
  19. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_search.py +26 -3
  20. tinyfish-0.2.6/tests/test_vault.py +438 -0
  21. {tinyfish-0.2.5 → tinyfish-0.2.6}/uv.lock +15 -12
  22. {tinyfish-0.2.5 → tinyfish-0.2.6}/.gitignore +0 -0
  23. {tinyfish-0.2.5 → tinyfish-0.2.6}/.pre-commit-config.yaml +0 -0
  24. {tinyfish-0.2.5 → tinyfish-0.2.6}/AGENTS.md +0 -0
  25. {tinyfish-0.2.5 → tinyfish-0.2.6}/CLAUDE.md +0 -0
  26. {tinyfish-0.2.5 → tinyfish-0.2.6}/RELEASE.md +0 -0
  27. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/exceptions-and-errors-guide.md +0 -0
  28. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/internal/api-integration-header.md +0 -0
  29. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/internal/exceptions-and-errors-guide.md +0 -0
  30. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/internal/publishing-private-guide.md +0 -0
  31. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/pagination-guide.md +0 -0
  32. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/proxy-and-browser-profiles.md +0 -0
  33. {tinyfish-0.2.5 → tinyfish-0.2.6}/docs/streaming-guide.md +0 -0
  34. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/__init__.py +0 -0
  35. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/client/__init__.py +0 -0
  36. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/client/_base.py +0 -0
  37. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/exceptions.py +0 -0
  38. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/_utils/sse_parser.py +0 -0
  39. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/agent/types.py +0 -0
  40. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/browser/__init__.py +0 -0
  41. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/browser/types.py +0 -0
  42. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/fetch/types.py +0 -0
  43. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/py.typed +0 -0
  44. {tinyfish-0.2.5 → tinyfish-0.2.6}/src/tinyfish/runs/__init__.py +0 -0
  45. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/__init__.py +0 -0
  46. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/conftest.py +0 -0
  47. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_browser.py +0 -0
  48. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_client.py +0 -0
  49. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/test_errors.py +0 -0
  50. {tinyfish-0.2.5 → tinyfish-0.2.6}/tests/testing_guide.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tinyfish
3
- Version: 0.2.5
3
+ Version: 0.2.6
4
4
  Summary: Official Python SDK for the TinyFish API
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: httpx>=0.27.0
@@ -75,6 +75,14 @@ response = client.agent.run(
75
75
  enabled=True,
76
76
  country_code=ProxyCountryCode.US, # optional — US, GB, CA, DE, FR, JP, AU
77
77
  ),
78
+ output_schema={ # require structured output
79
+ "type": "object",
80
+ "properties": {
81
+ "headline_count": {"type": "integer"},
82
+ "top_headline": {"type": "string"},
83
+ },
84
+ "required": ["headline_count", "top_headline"],
85
+ },
78
86
  )
79
87
 
80
88
  if response.status == RunStatus.COMPLETED:
@@ -83,6 +91,12 @@ else:
83
91
  print(f"Failed: {response.error.message}")
84
92
  ```
85
93
 
94
+ `output_schema` must be a top-level object. The SDK sends the schema to the API as-is; invalid schemas are rejected by
95
+ the API before execution.
96
+
97
+ The same `output_schema=` keyword is available on `client.agent.queue()` and `client.agent.stream()`.
98
+ Persisted runs return the requested contract back as `run.output_schema`.
99
+
86
100
  **Returns `AgentRunResponse`:**
87
101
 
88
102
  | Field | Type | Description |
@@ -101,6 +115,8 @@ else:
101
115
 
102
116
  Starts the automation in the background and returns a `run_id` immediately. Poll with `runs.get()` when you're ready for the result.
103
117
 
118
+ `queue()` accepts the same structured-output parameters as `run()`, including `output_schema=...`.
119
+
104
120
  ```python
105
121
  import time
106
122
  from tinyfish import TinyFish, RunStatus
@@ -179,6 +195,7 @@ run = client.runs.get(
179
195
  print(run.status) # PENDING, RUNNING, COMPLETED, FAILED, CANCELLED
180
196
  print(run.result)
181
197
  print(run.goal)
198
+ print(run.output_schema) # requested structured-output contract, if one was provided
182
199
  print(run.streaming_url) # live browser URL (while RUNNING)
183
200
  print(run.browser_config) # proxy/browser settings that were used
184
201
  ```
@@ -191,6 +208,7 @@ print(run.browser_config) # proxy/browser settings that were used
191
208
  | `status` | `RunStatus` | `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED` |
192
209
  | `goal` | `str` | The goal that was given |
193
210
  | `result` | `dict \| None` | Extracted data (`None` if not completed) |
211
+ | `output_schema` | `dict \| None` | JSON Schema contract originally requested for the run |
194
212
  | `error` | `RunError \| None` | Error details (`None` if succeeded) |
195
213
  | `streaming_url` | `str \| None` | Live browser URL (available while running) |
196
214
  | `browser_config` | `BrowserConfig \| None` | Proxy/browser settings used |
@@ -296,6 +314,20 @@ response = client.agent.run(
296
314
  )
297
315
  ```
298
316
 
317
+ ### Browser Context Profiles
318
+
319
+ Use Browser Context Profiles when a run should start from saved logged-in state. Pass `use_profile=True` for your default profile, or add `profile_id` for a specific profile. Pair with `use_vault=True` when TinyFish should repair stale sessions with saved credentials.
320
+
321
+ ```python
322
+ response = client.agent.run(
323
+ goal="Summarize the dashboard",
324
+ url="https://app.example.com/dashboard",
325
+ use_profile=True,
326
+ profile_id="prof_abc123def4567890",
327
+ use_vault=True,
328
+ )
329
+ ```
330
+
299
331
  ### Proxy configuration
300
332
 
301
333
  Route requests through a proxy, optionally pinned to a country:
@@ -65,6 +65,14 @@ response = client.agent.run(
65
65
  enabled=True,
66
66
  country_code=ProxyCountryCode.US, # optional — US, GB, CA, DE, FR, JP, AU
67
67
  ),
68
+ output_schema={ # require structured output
69
+ "type": "object",
70
+ "properties": {
71
+ "headline_count": {"type": "integer"},
72
+ "top_headline": {"type": "string"},
73
+ },
74
+ "required": ["headline_count", "top_headline"],
75
+ },
68
76
  )
69
77
 
70
78
  if response.status == RunStatus.COMPLETED:
@@ -73,6 +81,12 @@ else:
73
81
  print(f"Failed: {response.error.message}")
74
82
  ```
75
83
 
84
+ `output_schema` must be a top-level object. The SDK sends the schema to the API as-is; invalid schemas are rejected by
85
+ the API before execution.
86
+
87
+ The same `output_schema=` keyword is available on `client.agent.queue()` and `client.agent.stream()`.
88
+ Persisted runs return the requested contract back as `run.output_schema`.
89
+
76
90
  **Returns `AgentRunResponse`:**
77
91
 
78
92
  | Field | Type | Description |
@@ -91,6 +105,8 @@ else:
91
105
 
92
106
  Starts the automation in the background and returns a `run_id` immediately. Poll with `runs.get()` when you're ready for the result.
93
107
 
108
+ `queue()` accepts the same structured-output parameters as `run()`, including `output_schema=...`.
109
+
94
110
  ```python
95
111
  import time
96
112
  from tinyfish import TinyFish, RunStatus
@@ -169,6 +185,7 @@ run = client.runs.get(
169
185
  print(run.status) # PENDING, RUNNING, COMPLETED, FAILED, CANCELLED
170
186
  print(run.result)
171
187
  print(run.goal)
188
+ print(run.output_schema) # requested structured-output contract, if one was provided
172
189
  print(run.streaming_url) # live browser URL (while RUNNING)
173
190
  print(run.browser_config) # proxy/browser settings that were used
174
191
  ```
@@ -181,6 +198,7 @@ print(run.browser_config) # proxy/browser settings that were used
181
198
  | `status` | `RunStatus` | `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED` |
182
199
  | `goal` | `str` | The goal that was given |
183
200
  | `result` | `dict \| None` | Extracted data (`None` if not completed) |
201
+ | `output_schema` | `dict \| None` | JSON Schema contract originally requested for the run |
184
202
  | `error` | `RunError \| None` | Error details (`None` if succeeded) |
185
203
  | `streaming_url` | `str \| None` | Live browser URL (available while running) |
186
204
  | `browser_config` | `BrowserConfig \| None` | Proxy/browser settings used |
@@ -286,6 +304,20 @@ response = client.agent.run(
286
304
  )
287
305
  ```
288
306
 
307
+ ### Browser Context Profiles
308
+
309
+ Use Browser Context Profiles when a run should start from saved logged-in state. Pass `use_profile=True` for your default profile, or add `profile_id` for a specific profile. Pair with `use_vault=True` when TinyFish should repair stale sessions with saved credentials.
310
+
311
+ ```python
312
+ response = client.agent.run(
313
+ goal="Summarize the dashboard",
314
+ url="https://app.example.com/dashboard",
315
+ use_profile=True,
316
+ profile_id="prof_abc123def4567890",
317
+ use_vault=True,
318
+ )
319
+ ```
320
+
289
321
  ### Proxy configuration
290
322
 
291
323
  Route requests through a proxy, optionally pinned to a country:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tinyfish"
3
- version = "0.2.5"
3
+ version = "0.2.6"
4
4
  description = "Official Python SDK for the TinyFish API"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -10,6 +10,11 @@ dependencies = [
10
10
  "tenacity>=8.0.0",
11
11
  ]
12
12
 
13
+ [tool.uv]
14
+ constraint-dependencies = [
15
+ "pygments>=2.20.0",
16
+ ]
17
+
13
18
  [build-system]
14
19
  requires = ["hatchling"]
15
20
  build-backend = "hatchling.build"
@@ -20,8 +25,8 @@ packages = ["src/tinyfish"]
20
25
  [dependency-groups]
21
26
  dev = [
22
27
  "ruff>=0.15.2",
23
- "pytest>=8.0.0",
24
- "pytest-asyncio>=0.25.0",
28
+ "pytest>=9.0.3",
29
+ "pytest-asyncio>=1.3.0",
25
30
  "respx>=0.22.0",
26
31
  "python-dotenv>=1.2.2",
27
32
  ]
@@ -65,6 +65,21 @@ from .runs.types import (
65
65
  # Search types
66
66
  from .search.types import SearchQueryResponse, SearchResult
67
67
 
68
+ # Vault types
69
+ from .vault.types import (
70
+ FieldMetadata,
71
+ SyncSummary,
72
+ VaultConnection,
73
+ VaultConnectResponse,
74
+ VaultDisconnectResponse,
75
+ VaultFieldType,
76
+ VaultItem,
77
+ VaultListConnectionsResponse,
78
+ VaultListItemsResponse,
79
+ VaultProvider,
80
+ VaultSyncItemsResponse,
81
+ )
82
+
68
83
  __version__ = version("tinyfish")
69
84
 
70
85
  __all__ = [
@@ -122,4 +137,16 @@ __all__ = [
122
137
  "RunStatus",
123
138
  "RunListResponse",
124
139
  "PaginationInfo",
140
+ # Vault types
141
+ "VaultProvider",
142
+ "VaultFieldType",
143
+ "FieldMetadata",
144
+ "VaultItem",
145
+ "VaultConnection",
146
+ "SyncSummary",
147
+ "VaultConnectResponse",
148
+ "VaultListConnectionsResponse",
149
+ "VaultDisconnectResponse",
150
+ "VaultListItemsResponse",
151
+ "VaultSyncItemsResponse",
125
152
  ]
@@ -131,6 +131,16 @@ class BaseAsyncAPIClient(_BaseClient):
131
131
  response = await self._request("POST", path, json=json)
132
132
  return self._parse_response(response, cast_to)
133
133
 
134
+ async def _delete(
135
+ self,
136
+ path: str,
137
+ *,
138
+ cast_to: type[ResponseT],
139
+ ) -> ResponseT:
140
+ """Make DELETE request and parse the response into cast_to."""
141
+ response = await self._request("DELETE", path)
142
+ return self._parse_response(response, cast_to)
143
+
134
144
  async def _post_stream(
135
145
  self,
136
146
  path: str,
@@ -131,6 +131,16 @@ class BaseSyncAPIClient(_BaseClient):
131
131
  response = self._request("POST", path, json=json)
132
132
  return self._parse_response(response, cast_to)
133
133
 
134
+ def _delete(
135
+ self,
136
+ path: str,
137
+ *,
138
+ cast_to: type[ResponseT],
139
+ ) -> ResponseT:
140
+ """Make DELETE request and parse the response into cast_to."""
141
+ response = self._request("DELETE", path)
142
+ return self._parse_response(response, cast_to)
143
+
134
144
  def _post_stream(
135
145
  self,
136
146
  path: str,
@@ -10,6 +10,7 @@ class BaseSyncAPIResource:
10
10
  self._client = client
11
11
  self._get = client._get
12
12
  self._post = client._post
13
+ self._delete = client._delete
13
14
  self._post_stream = client._post_stream
14
15
 
15
16
 
@@ -20,4 +21,5 @@ class BaseAsyncAPIResource:
20
21
  self._client = client
21
22
  self._get = client._get
22
23
  self._post = client._post
24
+ self._delete = client._delete
23
25
  self._post_stream = client._post_stream
@@ -27,12 +27,32 @@ def _build_run_body(
27
27
  url: str,
28
28
  browser_profile: BrowserProfile | None,
29
29
  proxy_config: ProxyConfig | None,
30
+ output_schema: dict[str, Any] | None,
31
+ use_profile: bool | None = None,
32
+ profile_id: str | None = None,
33
+ use_vault: bool | None = None,
34
+ credential_item_ids: list[str] | None = None,
30
35
  ) -> dict[str, Any]:
31
36
  body: dict[str, Any] = {"goal": goal, "url": url}
32
37
  if browser_profile is not None:
33
38
  body["browser_profile"] = browser_profile
34
39
  if proxy_config is not None:
35
40
  body["proxy_config"] = proxy_config.model_dump(exclude_none=True)
41
+ if output_schema is not None:
42
+ body["output_schema"] = output_schema
43
+ if use_profile is not None:
44
+ body["use_profile"] = use_profile
45
+ if profile_id is not None:
46
+ profile_id = profile_id.strip()
47
+ if not profile_id:
48
+ raise ValueError("profile_id must be a non-empty string")
49
+ if use_profile is not True:
50
+ raise ValueError("profile_id requires use_profile=True")
51
+ body["profile_id"] = profile_id
52
+ if use_vault is not None:
53
+ body["use_vault"] = use_vault
54
+ if credential_item_ids is not None:
55
+ body["credential_item_ids"] = credential_item_ids
36
56
  return body
37
57
 
38
58
 
@@ -106,6 +126,11 @@ class AgentResource(BaseSyncAPIResource):
106
126
  url: str,
107
127
  browser_profile: BrowserProfile | None = None,
108
128
  proxy_config: ProxyConfig | None = None,
129
+ output_schema: dict[str, Any] | None = None,
130
+ use_profile: bool | None = None,
131
+ profile_id: str | None = None,
132
+ use_vault: bool | None = None,
133
+ credential_item_ids: list[str] | None = None,
109
134
  ) -> AgentRunResponse:
110
135
  """Run a browser automation and wait for it to finish.
111
136
 
@@ -117,6 +142,11 @@ class AgentResource(BaseSyncAPIResource):
117
142
  url: The URL to open the browser on.
118
143
  browser_profile: "lite" (default) or "stealth" (anti-detection).
119
144
  proxy_config: Optional proxy settings (enabled, country_code).
145
+ output_schema: Optional JSON Schema object describing the expected final result.
146
+ use_profile: Whether to start from a saved Browser Context Profile.
147
+ profile_id: Specific Browser Context Profile ID. Requires use_profile=True.
148
+ use_vault: Whether to use stored vault credentials for authentication.
149
+ credential_item_ids: Specific vault item IDs to use. When omitted, all matching credentials are available.
120
150
 
121
151
  Returns:
122
152
  AgentRunResponse with status, result, and timing info.
@@ -126,7 +156,17 @@ class AgentResource(BaseSyncAPIResource):
126
156
  RateLimitError: Too many requests.
127
157
  InternalServerError: Something went wrong on the server.
128
158
  """
129
- body = _build_run_body(goal, url, browser_profile, proxy_config)
159
+ body = _build_run_body(
160
+ goal,
161
+ url,
162
+ browser_profile,
163
+ proxy_config,
164
+ output_schema,
165
+ use_profile,
166
+ profile_id,
167
+ use_vault,
168
+ credential_item_ids,
169
+ )
130
170
  return self._post("/v1/automation/run", json=body, cast_to=AgentRunResponse)
131
171
 
132
172
  def queue(
@@ -136,6 +176,11 @@ class AgentResource(BaseSyncAPIResource):
136
176
  url: str,
137
177
  browser_profile: BrowserProfile | None = None,
138
178
  proxy_config: ProxyConfig | None = None,
179
+ output_schema: dict[str, Any] | None = None,
180
+ use_profile: bool | None = None,
181
+ profile_id: str | None = None,
182
+ use_vault: bool | None = None,
183
+ credential_item_ids: list[str] | None = None,
139
184
  ) -> AgentRunAsyncResponse:
140
185
  """Queue a browser automation and return immediately.
141
186
 
@@ -147,6 +192,11 @@ class AgentResource(BaseSyncAPIResource):
147
192
  url: The URL to open the browser on.
148
193
  browser_profile: "lite" (default) or "stealth" (anti-detection).
149
194
  proxy_config: Optional proxy settings (enabled, country_code).
195
+ output_schema: Optional JSON Schema object describing the expected final result.
196
+ use_profile: Whether to start from a saved Browser Context Profile.
197
+ profile_id: Specific Browser Context Profile ID. Requires use_profile=True.
198
+ use_vault: Whether to use stored vault credentials for authentication.
199
+ credential_item_ids: Specific vault item IDs to use. When omitted, all matching credentials are available.
150
200
 
151
201
  Returns:
152
202
  AgentRunAsyncResponse with the run_id to poll later.
@@ -156,7 +206,17 @@ class AgentResource(BaseSyncAPIResource):
156
206
  RateLimitError: Too many requests.
157
207
  InternalServerError: Something went wrong on the server.
158
208
  """
159
- body = _build_run_body(goal, url, browser_profile, proxy_config)
209
+ body = _build_run_body(
210
+ goal,
211
+ url,
212
+ browser_profile,
213
+ proxy_config,
214
+ output_schema,
215
+ use_profile,
216
+ profile_id,
217
+ use_vault,
218
+ credential_item_ids,
219
+ )
160
220
  return self._post("/v1/automation/run-async", json=body, cast_to=AgentRunAsyncResponse)
161
221
 
162
222
  def stream(
@@ -166,6 +226,11 @@ class AgentResource(BaseSyncAPIResource):
166
226
  url: str,
167
227
  browser_profile: BrowserProfile | None = None,
168
228
  proxy_config: ProxyConfig | None = None,
229
+ output_schema: dict[str, Any] | None = None,
230
+ use_profile: bool | None = None,
231
+ profile_id: str | None = None,
232
+ use_vault: bool | None = None,
233
+ credential_item_ids: list[str] | None = None,
169
234
  on_started: Callable[[StartedEvent], None] | None = None,
170
235
  on_streaming_url: Callable[[StreamingUrlEvent], None] | None = None,
171
236
  on_progress: Callable[[ProgressEvent], None] | None = None,
@@ -202,6 +267,11 @@ class AgentResource(BaseSyncAPIResource):
202
267
  url: The URL to open the browser on.
203
268
  browser_profile: "lite" (default) or "stealth" (anti-detection).
204
269
  proxy_config: Optional proxy settings (enabled, country_code).
270
+ output_schema: Optional JSON Schema object describing the expected final result.
271
+ use_profile: Whether to start from a saved Browser Context Profile.
272
+ profile_id: Specific Browser Context Profile ID. Requires use_profile=True.
273
+ use_vault: Whether to use stored vault credentials for authentication.
274
+ credential_item_ids: Specific vault item IDs to use. When omitted, all matching credentials are available.
205
275
  on_started: Called when the run starts (receives StartedEvent).
206
276
  on_streaming_url: Called with the live browser stream URL (receives StreamingUrlEvent).
207
277
  on_progress: Called on each automation step (receives ProgressEvent).
@@ -216,7 +286,17 @@ class AgentResource(BaseSyncAPIResource):
216
286
  RateLimitError: Too many requests.
217
287
  InternalServerError: Something went wrong on the server.
218
288
  """
219
- body = _build_run_body(goal, url, browser_profile, proxy_config)
289
+ body = _build_run_body(
290
+ goal,
291
+ url,
292
+ browser_profile,
293
+ proxy_config,
294
+ output_schema,
295
+ use_profile,
296
+ profile_id,
297
+ use_vault,
298
+ credential_item_ids,
299
+ )
220
300
 
221
301
  def _generate() -> Iterator[AgentRunWithStreamingResponse]:
222
302
  lines = self._post_stream("/v1/automation/run-sse", json=body)
@@ -261,6 +341,11 @@ class AsyncAgentResource(BaseAsyncAPIResource):
261
341
  url: str,
262
342
  browser_profile: BrowserProfile | None = None,
263
343
  proxy_config: ProxyConfig | None = None,
344
+ output_schema: dict[str, Any] | None = None,
345
+ use_profile: bool | None = None,
346
+ profile_id: str | None = None,
347
+ use_vault: bool | None = None,
348
+ credential_item_ids: list[str] | None = None,
264
349
  ) -> AgentRunResponse:
265
350
  """Run a browser automation and wait for it to finish.
266
351
 
@@ -272,6 +357,11 @@ class AsyncAgentResource(BaseAsyncAPIResource):
272
357
  url: The URL to open the browser on.
273
358
  browser_profile: "lite" (default) or "stealth" (anti-detection).
274
359
  proxy_config: Optional proxy settings (enabled, country_code).
360
+ output_schema: Optional JSON Schema object describing the expected final result.
361
+ use_profile: Whether to start from a saved Browser Context Profile.
362
+ profile_id: Specific Browser Context Profile ID. Requires use_profile=True.
363
+ use_vault: Whether to use stored vault credentials for authentication.
364
+ credential_item_ids: Specific vault item IDs to use. When omitted, all matching credentials are available.
275
365
 
276
366
  Returns:
277
367
  AgentRunResponse with status, result, and timing info.
@@ -281,7 +371,17 @@ class AsyncAgentResource(BaseAsyncAPIResource):
281
371
  RateLimitError: Too many requests.
282
372
  InternalServerError: Something went wrong on the server.
283
373
  """
284
- body = _build_run_body(goal, url, browser_profile, proxy_config)
374
+ body = _build_run_body(
375
+ goal,
376
+ url,
377
+ browser_profile,
378
+ proxy_config,
379
+ output_schema,
380
+ use_profile,
381
+ profile_id,
382
+ use_vault,
383
+ credential_item_ids,
384
+ )
285
385
  return await self._post("/v1/automation/run", json=body, cast_to=AgentRunResponse)
286
386
 
287
387
  async def queue(
@@ -291,6 +391,11 @@ class AsyncAgentResource(BaseAsyncAPIResource):
291
391
  url: str,
292
392
  browser_profile: BrowserProfile | None = None,
293
393
  proxy_config: ProxyConfig | None = None,
394
+ output_schema: dict[str, Any] | None = None,
395
+ use_profile: bool | None = None,
396
+ profile_id: str | None = None,
397
+ use_vault: bool | None = None,
398
+ credential_item_ids: list[str] | None = None,
294
399
  ) -> AgentRunAsyncResponse:
295
400
  """Queue a browser automation and return immediately.
296
401
 
@@ -302,6 +407,11 @@ class AsyncAgentResource(BaseAsyncAPIResource):
302
407
  url: The URL to open the browser on.
303
408
  browser_profile: "lite" (default) or "stealth" (anti-detection).
304
409
  proxy_config: Optional proxy settings (enabled, country_code).
410
+ output_schema: Optional JSON Schema object describing the expected final result.
411
+ use_profile: Whether to start from a saved Browser Context Profile.
412
+ profile_id: Specific Browser Context Profile ID. Requires use_profile=True.
413
+ use_vault: Whether to use stored vault credentials for authentication.
414
+ credential_item_ids: Specific vault item IDs to use. When omitted, all matching credentials are available.
305
415
 
306
416
  Returns:
307
417
  AgentRunAsyncResponse with the run_id to poll later.
@@ -311,7 +421,17 @@ class AsyncAgentResource(BaseAsyncAPIResource):
311
421
  RateLimitError: Too many requests.
312
422
  InternalServerError: Something went wrong on the server.
313
423
  """
314
- body = _build_run_body(goal, url, browser_profile, proxy_config)
424
+ body = _build_run_body(
425
+ goal,
426
+ url,
427
+ browser_profile,
428
+ proxy_config,
429
+ output_schema,
430
+ use_profile,
431
+ profile_id,
432
+ use_vault,
433
+ credential_item_ids,
434
+ )
315
435
  return await self._post("/v1/automation/run-async", json=body, cast_to=AgentRunAsyncResponse)
316
436
 
317
437
  def stream(
@@ -321,6 +441,11 @@ class AsyncAgentResource(BaseAsyncAPIResource):
321
441
  url: str,
322
442
  browser_profile: BrowserProfile | None = None,
323
443
  proxy_config: ProxyConfig | None = None,
444
+ output_schema: dict[str, Any] | None = None,
445
+ use_profile: bool | None = None,
446
+ profile_id: str | None = None,
447
+ use_vault: bool | None = None,
448
+ credential_item_ids: list[str] | None = None,
324
449
  on_started: Callable[[StartedEvent], None] | None = None,
325
450
  on_streaming_url: Callable[[StreamingUrlEvent], None] | None = None,
326
451
  on_progress: Callable[[ProgressEvent], None] | None = None,
@@ -357,6 +482,11 @@ class AsyncAgentResource(BaseAsyncAPIResource):
357
482
  url: The URL to open the browser on.
358
483
  browser_profile: "lite" (default) or "stealth" (anti-detection).
359
484
  proxy_config: Optional proxy settings (enabled, country_code).
485
+ output_schema: Optional JSON Schema object describing the expected final result.
486
+ use_profile: Whether to start from a saved Browser Context Profile.
487
+ profile_id: Specific Browser Context Profile ID. Requires use_profile=True.
488
+ use_vault: Whether to use stored vault credentials for authentication.
489
+ credential_item_ids: Specific vault item IDs to use. When omitted, all matching credentials are available.
360
490
  on_started: Called when the run starts (receives StartedEvent).
361
491
  on_streaming_url: Called with the live browser stream URL (receives StreamingUrlEvent).
362
492
  on_progress: Called on each automation step (receives ProgressEvent).
@@ -371,7 +501,17 @@ class AsyncAgentResource(BaseAsyncAPIResource):
371
501
  RateLimitError: Too many requests.
372
502
  InternalServerError: Something went wrong on the server.
373
503
  """
374
- body = _build_run_body(goal, url, browser_profile, proxy_config)
504
+ body = _build_run_body(
505
+ goal,
506
+ url,
507
+ browser_profile,
508
+ proxy_config,
509
+ output_schema,
510
+ use_profile,
511
+ profile_id,
512
+ use_vault,
513
+ credential_item_ids,
514
+ )
375
515
 
376
516
  async def _generate() -> AsyncIterator[AgentRunWithStreamingResponse]:
377
517
  lines = self._post_stream("/v1/automation/run-sse", json=body)
@@ -8,6 +8,7 @@ from .browser import AsyncBrowserResource, BrowserResource
8
8
  from .fetch import AsyncFetchResource, FetchResource
9
9
  from .runs import AsyncRunsResource, RunsResource
10
10
  from .search import AsyncSearchResource, SearchResource
11
+ from .vault import AsyncVaultResource, VaultResource
11
12
 
12
13
  __all__ = ["TinyFish", "AsyncTinyFish"]
13
14
 
@@ -28,6 +29,7 @@ class TinyFish(BaseSyncAPIClient):
28
29
  fetch: FetchResource
29
30
  runs: RunsResource
30
31
  search: SearchResource
32
+ vault: VaultResource
31
33
 
32
34
  def __init__(
33
35
  self,
@@ -52,6 +54,7 @@ class TinyFish(BaseSyncAPIClient):
52
54
  self.fetch = FetchResource(self)
53
55
  self.runs = RunsResource(self)
54
56
  self.search = SearchResource(self)
57
+ self.vault = VaultResource(self)
55
58
 
56
59
 
57
60
  class AsyncTinyFish(BaseAsyncAPIClient):
@@ -65,6 +68,7 @@ class AsyncTinyFish(BaseAsyncAPIClient):
65
68
  fetch: AsyncFetchResource
66
69
  runs: AsyncRunsResource
67
70
  search: AsyncSearchResource
71
+ vault: AsyncVaultResource
68
72
 
69
73
  def __init__(
70
74
  self,
@@ -89,3 +93,4 @@ class AsyncTinyFish(BaseAsyncAPIClient):
89
93
  self.fetch = AsyncFetchResource(self)
90
94
  self.runs = AsyncRunsResource(self)
91
95
  self.search = AsyncSearchResource(self)
96
+ self.vault = AsyncVaultResource(self)