@tiny-fish/sdk 0.0.5 → 0.0.7

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 (56) hide show
  1. package/README.md +231 -206
  2. package/dist/_utils/client.d.ts +14 -9
  3. package/dist/_utils/client.d.ts.map +1 -1
  4. package/dist/_utils/client.js +93 -41
  5. package/dist/_utils/client.js.map +1 -1
  6. package/dist/agent/index.d.ts +3 -3
  7. package/dist/agent/index.d.ts.map +1 -1
  8. package/dist/agent/index.js +39 -65
  9. package/dist/agent/index.js.map +1 -1
  10. package/dist/agent/types.d.ts +258 -127
  11. package/dist/agent/types.d.ts.map +1 -1
  12. package/dist/agent/types.js +133 -41
  13. package/dist/agent/types.js.map +1 -1
  14. package/dist/browser/index.d.ts +16 -0
  15. package/dist/browser/index.d.ts.map +1 -0
  16. package/dist/browser/index.js +29 -0
  17. package/dist/browser/index.js.map +1 -0
  18. package/dist/browser/types.d.ts +17 -0
  19. package/dist/browser/types.d.ts.map +1 -0
  20. package/dist/browser/types.js +15 -0
  21. package/dist/browser/types.js.map +1 -0
  22. package/dist/client.d.ts +6 -0
  23. package/dist/client.d.ts.map +1 -1
  24. package/dist/client.js +9 -0
  25. package/dist/client.js.map +1 -1
  26. package/dist/fetch/index.d.ts +10 -0
  27. package/dist/fetch/index.d.ts.map +1 -0
  28. package/dist/fetch/index.js +37 -0
  29. package/dist/fetch/index.js.map +1 -0
  30. package/dist/fetch/types.d.ts +176 -0
  31. package/dist/fetch/types.d.ts.map +1 -0
  32. package/dist/fetch/types.js +69 -0
  33. package/dist/fetch/types.js.map +1 -0
  34. package/dist/index.d.ts +9 -3
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +8 -2
  37. package/dist/index.js.map +1 -1
  38. package/dist/runs/index.d.ts +1 -1
  39. package/dist/runs/index.d.ts.map +1 -1
  40. package/dist/runs/index.js +25 -16
  41. package/dist/runs/index.js.map +1 -1
  42. package/dist/runs/types.d.ts +114 -66
  43. package/dist/runs/types.d.ts.map +1 -1
  44. package/dist/runs/types.js +48 -6
  45. package/dist/runs/types.js.map +1 -1
  46. package/dist/search/index.d.ts +10 -0
  47. package/dist/search/index.d.ts.map +1 -0
  48. package/dist/search/index.js +29 -0
  49. package/dist/search/index.js.map +1 -0
  50. package/dist/search/types.d.ts +34 -0
  51. package/dist/search/types.d.ts.map +1 -0
  52. package/dist/search/types.js +25 -0
  53. package/dist/search/types.js.map +1 -0
  54. package/dist/version.d.ts +1 -1
  55. package/dist/version.js +1 -1
  56. package/package.json +3 -2
package/README.md CHANGED
@@ -1,70 +1,70 @@
1
1
  # TinyFish TypeScript SDK
2
2
 
3
- The official TypeScript SDK for [TinyFish](https://agent.tinyfish.ai)
3
+ Typed access to TinyFish web agents, fetch extraction, remote browser sessions, run history, and search.
4
+
5
+ Use the SDK when you want to:
6
+
7
+ - automate a page with a natural-language goal
8
+ - stream live progress events and a browser preview URL
9
+ - queue jobs and poll them later
10
+ - fetch clean page content from up to 10 URLs at once
11
+ - create a remote browser session for direct CDP control
12
+ - query TinyFish Search from the same client
4
13
 
5
14
  ## Installation
6
15
 
7
16
  ```bash
8
- npm install tinyfish
17
+ npm install @tiny-fish/sdk
9
18
  ```
10
19
 
11
- Requires Node.js 18+. Also works with Bun and Deno.
20
+ Requirements:
21
+
22
+ - Node.js 18+
23
+ - a TinyFish API key from [agent.tinyfish.ai/api-keys](https://agent.tinyfish.ai/api-keys)
12
24
 
13
- ## Get your API key
25
+ Authenticate with either the constructor or `TINYFISH_API_KEY`:
14
26
 
15
- Sign up and grab your key at [agent.tinyfish.ai/api-keys](https://agent.tinyfish.ai/api-keys).
27
+ ```ts
28
+ import { TinyFish } from "@tiny-fish/sdk";
29
+
30
+ const client = new TinyFish({
31
+ apiKey: process.env.TINYFISH_API_KEY,
32
+ });
33
+ ```
16
34
 
17
35
  ## Quickstart
18
36
 
19
- ```typescript
20
- import { TinyFish } from "tinyfish";
37
+ `agent.stream()` is the best default for product integrations because it gives you progress updates while the run is happening.
21
38
 
22
- const client = new TinyFish({ apiKey: "your-api-key" });
39
+ ```ts
40
+ import { TinyFish } from "@tiny-fish/sdk";
41
+
42
+ const client = new TinyFish();
23
43
 
24
44
  const stream = await client.agent.stream(
25
45
  {
26
- goal: "What is the current Bitcoin price?",
27
- url: "https://www.coinbase.com/price/bitcoin",
46
+ goal: "Extract the top 5 headlines",
47
+ url: "https://news.ycombinator.com",
28
48
  },
29
49
  {
30
- onProgress: (e) => console.log(` > ${e.purpose}`),
31
- onComplete: (e) => console.log(e.result),
50
+ onStarted: (event) => console.log(`Run: ${event.run_id}`),
51
+ onStreamingUrl: (event) => console.log(`Watch live: ${event.streaming_url}`),
52
+ onProgress: (event) => console.log(`> ${event.purpose}`),
53
+ onComplete: (event) => console.log(event.result),
32
54
  },
33
55
  );
34
56
 
35
57
  for await (const event of stream) {
36
- // Callbacks fire automatically during iteration
58
+ if (event.type === "COMPLETE") {
59
+ console.log(`Finished with status ${event.status}`);
60
+ }
37
61
  }
38
62
  ```
39
63
 
40
- Or set the `TINYFISH_API_KEY` environment variable and omit `apiKey`:
41
-
42
- ```typescript
43
- const client = new TinyFish();
44
- ```
45
-
46
- > All methods are async and return promises. There is no synchronous client — JavaScript is async-native.
47
-
48
- ## Methods
49
-
50
- | Method | Description | Returns | Blocks? |
51
- |--------|-------------|---------|---------|
52
- | [`agent.stream()`](#agentstream--real-time-events) | Stream live SSE events as the agent works | `AgentStream` | No |
53
- | [`agent.run()`](#agentrun--block-until-done) | Run an automation, wait for the result | `AgentRunResponse` | Yes |
54
- | [`agent.queue()`](#agentqueue--fire-and-forget) | Start an automation, return immediately | `AgentRunAsyncResponse` | No |
55
- | [`runs.get()`](#runsget--retrieve-a-single-run) | Retrieve a single run by ID | `Run` | — |
56
- | [`runs.list()`](#runslist--list-and-filter-runs) | List runs with filtering, sorting, pagination | `RunListResponse` | — |
57
-
58
- ---
64
+ Need request-scoped cancellation without changing the client-wide timeout? Pass an `AbortSignal` as the optional second argument:
59
65
 
60
- ### `agent.stream()` — real-time events
61
-
62
- Opens a Server-Sent Events stream. You get live progress updates as the agent works, plus a URL for a live browser preview. This is the recommended integration method.
63
-
64
- ```typescript
65
- import { TinyFish } from "tinyfish";
66
-
67
- const client = new TinyFish();
66
+ ```ts
67
+ const controller = new AbortController();
68
68
 
69
69
  const stream = await client.agent.stream(
70
70
  {
@@ -72,275 +72,300 @@ const stream = await client.agent.stream(
72
72
  url: "https://news.ycombinator.com",
73
73
  },
74
74
  {
75
- onStarted: (e) => console.log(`Started: ${e.run_id}`),
76
- onStreamingUrl: (e) => console.log(`Watch: ${e.streaming_url}`),
77
- onProgress: (e) => console.log(` > ${e.purpose}`),
78
- onComplete: (e) => console.log(`Done: ${e.status}`),
75
+ signal: controller.signal,
79
76
  },
80
77
  );
81
78
 
82
- for await (const event of stream) {
83
- // Callbacks fire automatically during iteration.
84
- // You can also inspect events directly:
85
- if (event.type === "COMPLETE") {
86
- console.log(event.result);
87
- }
88
- }
79
+ controller.abort();
89
80
  ```
90
81
 
91
- **Returns `AgentStream`** an async iterable you iterate with `for await`. Events arrive in order: `STARTED` → `STREAMING_URL` → `PROGRESS` (repeated) → `COMPLETE`.
82
+ ## Choose an API
92
83
 
93
- Call `stream.close()` to abort early and stop yielding events.
84
+ | Method | Use it when | Returns |
85
+ | --- | --- | --- |
86
+ | `client.agent.stream()` | You want live events and a browser preview URL | `AgentStream` |
87
+ | `client.agent.run()` | You want one blocking request that waits for the final result | `AgentRunResponse` |
88
+ | `client.agent.queue()` | You want to enqueue work and check back later | `AgentRunAsyncResponse` |
89
+ | `client.fetch.getContents()` | You want extracted page content without running a browser agent | `FetchResponse` |
90
+ | `client.browser.sessions.create()` | You want a remote browser session and CDP connection info | `BrowserSession` |
91
+ | `client.runs.get()` | You already have a `run_id` and need the latest state | `Run` |
92
+ | `client.runs.list()` | You want to list or filter historical runs | `RunListResponse` |
93
+ | `client.search.query()` | You want TinyFish Search results | `SearchQueryResponse` |
94
94
 
95
- See the [Streaming Guide](docs/streaming-guide.md) for the full event lifecycle, event types, and advanced patterns.
95
+ ## Core workflows
96
96
 
97
- ---
97
+ ### Run and wait
98
98
 
99
- ### `agent.run()` block until done
99
+ Use `agent.run()` for scripts, cron jobs, and backend tasks that should block until the result is ready.
100
100
 
101
- Sends the automation and waits for it to finish. Returns the full result in one shot.
102
-
103
- ```typescript
104
- import { TinyFish, RunStatus, BrowserProfile, ProxyCountryCode } from "tinyfish";
105
- import type { ProxyConfig } from "tinyfish";
101
+ ```ts
102
+ import {
103
+ BrowserProfile,
104
+ ProxyCountryCode,
105
+ RunStatus,
106
+ TinyFish,
107
+ } from "@tiny-fish/sdk";
106
108
 
107
109
  const client = new TinyFish();
108
110
 
109
111
  const response = await client.agent.run({
110
- goal: "Extract the top 5 headlines", // required what to do on the page
111
- url: "https://news.ycombinator.com", // required — URL to open
112
- browser_profile: BrowserProfile.STEALTH, // optional — "lite" (default) or "stealth"
113
- proxy_config: { // optional — proxy settings
112
+ goal: "Find the price of the latest MacBook Pro",
113
+ url: "https://www.apple.com/shop/buy-mac/macbook-pro",
114
+ browser_profile: BrowserProfile.STEALTH,
115
+ proxy_config: {
114
116
  enabled: true,
115
- country_code: ProxyCountryCode.US, // optional — US, GB, CA, DE, FR, JP, AU
117
+ country_code: ProxyCountryCode.US,
116
118
  },
117
119
  });
118
120
 
119
121
  if (response.status === RunStatus.COMPLETED) {
120
122
  console.log(response.result);
121
123
  } else {
122
- console.log(`Failed: ${response.error?.message}`);
124
+ console.error(response.error?.message);
123
125
  }
124
126
  ```
125
127
 
126
- **Returns `AgentRunResponse`:**
128
+ `run()` also accepts an optional second argument with `signal`:
127
129
 
128
- | Field | Type | Description |
129
- |-------|------|-------------|
130
- | `status` | `RunStatus` | `COMPLETED`, `FAILED`, etc. |
131
- | `run_id` | `string \| null` | Unique run identifier |
132
- | `result` | `Record<string, unknown> \| null` | Extracted data (`null` if failed) |
133
- | `error` | `RunError \| null` | Error details (`null` if succeeded) |
134
- | `num_of_steps` | `number` | Number of steps the agent took |
135
- | `started_at` | `string \| null` | ISO 8601 timestamp when the run started |
136
- | `finished_at` | `string \| null` | ISO 8601 timestamp when the run finished |
130
+ ```ts
131
+ const controller = new AbortController();
137
132
 
138
- ---
133
+ const response = await client.agent.run(
134
+ {
135
+ goal: "Extract the page title",
136
+ url: "https://example.com",
137
+ },
138
+ {
139
+ signal: controller.signal,
140
+ },
141
+ );
142
+ ```
139
143
 
140
- ### `agent.queue()` — fire and forget
144
+ ### Queue and poll
141
145
 
142
- Starts the automation in the background and returns a `run_id` immediately. Poll with `runs.get()` when you're ready for the result.
146
+ Use `agent.queue()` when you do not want to keep the request open.
143
147
 
144
- ```typescript
145
- import { TinyFish, RunStatus } from "tinyfish";
148
+ ```ts
149
+ import { RunStatus, TinyFish } from "@tiny-fish/sdk";
146
150
 
147
151
  const client = new TinyFish();
148
152
 
149
153
  const queued = await client.agent.queue({
150
- goal: "Extract the top 5 headlines",
151
- url: "https://news.ycombinator.com",
154
+ goal: "Extract all job titles from the careers page",
155
+ url: "https://example.com/careers",
152
156
  });
153
157
 
154
158
  if (queued.error) {
155
- console.error(`Failed to queue: ${queued.error.message}`);
156
- process.exit(1);
159
+ throw new Error(queued.error.message);
157
160
  }
158
161
 
159
- console.log(`Run started: ${queued.run_id}`);
162
+ let run = await client.runs.get(queued.run_id);
160
163
 
161
- // Poll for completion
162
- while (true) {
163
- const run = await client.runs.get(queued.run_id);
164
- if (run.status === RunStatus.COMPLETED || run.status === RunStatus.FAILED) {
165
- console.log(run.result);
166
- break;
167
- }
168
- await new Promise((r) => setTimeout(r, 5000));
164
+ while (run.status === RunStatus.PENDING || run.status === RunStatus.RUNNING) {
165
+ await new Promise((resolve) => setTimeout(resolve, 5000));
166
+ run = await client.runs.get(run.run_id);
169
167
  }
170
- ```
171
168
 
172
- **Returns `AgentRunAsyncResponse`** a discriminated union. Check `error` to narrow the type:
173
-
174
- ```typescript
175
- const response = await client.agent.queue({ goal, url });
176
- if (response.error) {
177
- // response.run_id is null here
178
- console.error(response.error.message);
169
+ if (run.status === RunStatus.COMPLETED) {
170
+ console.log(run.result);
179
171
  } else {
180
- // response.run_id is string here
181
- const run = await client.runs.get(response.run_id);
172
+ console.error(run.error?.message ?? `Run ended with status: ${run.status}`);
182
173
  }
183
174
  ```
184
175
 
185
- | Field | Type | Description |
186
- |-------|------|-------------|
187
- | `run_id` | `string \| null` | Run ID to poll with `runs.get()` |
188
- | `error` | `RunError \| null` | Error if queuing itself failed |
176
+ `queue()` also accepts an optional second argument with `signal` for cancelling just the enqueue request.
189
177
 
190
- ---
178
+ ### Fetch clean content
191
179
 
192
- ### `runs.get()` retrieve a single run
180
+ Use `fetch.getContents()` when you want extracted content from URLs without a browser-agent run.
193
181
 
194
- Fetch the full details of a run by its ID.
182
+ ```ts
183
+ import { FetchFormat, TinyFish } from "@tiny-fish/sdk";
195
184
 
196
- ```typescript
197
- const run = await client.runs.get("run_abc123");
185
+ const client = new TinyFish();
198
186
 
199
- console.log(run.status); // PENDING, RUNNING, COMPLETED, FAILED, CANCELLED
200
- console.log(run.result);
201
- console.log(run.goal);
202
- console.log(run.streaming_url); // live browser URL (while RUNNING)
203
- console.log(run.browser_config); // proxy/browser settings that were used
187
+ const response = await client.fetch.getContents({
188
+ urls: ["https://example.com", "https://example.org"],
189
+ format: FetchFormat.Markdown,
190
+ links: true,
191
+ image_links: false,
192
+ });
193
+
194
+ console.log(response.results);
195
+ console.log(response.errors);
196
+ ```
197
+
198
+ `fetch.getContents()` accepts 1 to 10 URLs. `FetchResult.text` is:
199
+
200
+ - `string` for `FetchFormat.Markdown` and `FetchFormat.Html`
201
+ - `Record<string, unknown>` for `FetchFormat.Json`
202
+ - `null` if extraction failed for that item
203
+
204
+ ### Create a browser session
205
+
206
+ Use `browser.sessions.create()` when you want connection details for direct browser control.
207
+
208
+ ```ts
209
+ import { TinyFish } from "@tiny-fish/sdk";
210
+
211
+ const client = new TinyFish();
212
+
213
+ const session = await client.browser.sessions.create({
214
+ url: "https://example.com",
215
+ });
216
+
217
+ console.log(session.session_id);
218
+ console.log(session.cdp_url);
219
+ console.log(session.base_url);
204
220
  ```
205
221
 
206
- **Returns `Run`:**
222
+ ### Inspect and list runs
207
223
 
208
- | Field | Type | Description |
209
- |-------|------|-------------|
210
- | `run_id` | `string` | Unique identifier |
211
- | `status` | `RunStatus` | `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED` |
212
- | `goal` | `string` | The goal that was given |
213
- | `result` | `Record<string, unknown> \| null` | Extracted data (`null` if not completed) |
214
- | `error` | `RunError \| null` | Error details (`null` if succeeded) |
215
- | `streaming_url` | `string \| null` | Live browser URL (available while running) |
216
- | `browser_config` | `BrowserConfig \| null` | Proxy/browser settings used |
217
- | `created_at` | `string` | ISO 8601 timestamp when the run was created |
218
- | `started_at` | `string \| null` | ISO 8601 timestamp when execution started |
219
- | `finished_at` | `string \| null` | ISO 8601 timestamp when execution finished |
220
- | `num_of_steps` | `number` | Number of steps the agent took |
224
+ Fetch a single run when you already know its `run_id`:
221
225
 
222
- **Throws:** `SDKError` if `run_id` is empty. `NotFoundError` if no run exists with that ID.
226
+ ```ts
227
+ const run = await client.runs.get("run_abc123");
223
228
 
224
- ---
229
+ console.log(run.status);
230
+ console.log(run.result);
231
+ console.log(run.streaming_url);
232
+ ```
225
233
 
226
- ### `runs.list()` list and filter runs
234
+ Use `runs.list()` for filtering and pagination:
227
235
 
228
- List runs with optional filtering, sorting, and cursor-based pagination. All parameters are optional.
236
+ ```ts
237
+ import { RunStatus, SortDirection, TinyFish } from "@tiny-fish/sdk";
229
238
 
230
- ```typescript
231
- import { RunStatus, SortDirection } from "tinyfish";
239
+ const client = new TinyFish();
232
240
 
233
241
  const response = await client.runs.list({
234
- status: RunStatus.COMPLETED, // optional — filter by status
235
- goal: "headlines", // optional — filter by goal text
236
- created_after: "2025-01-01T00:00:00Z", // optional — ISO 8601 lower bound
237
- created_before: "2025-12-31T23:59:59Z", // optional — ISO 8601 upper bound
238
- sort_direction: SortDirection.DESC, // optional — "asc" or "desc"
239
- limit: 10, // optional — max runs per page
240
- cursor: undefined, // optional — pagination cursor from previous response
242
+ status: RunStatus.COMPLETED,
243
+ goal: "headlines",
244
+ sort_direction: SortDirection.DESC,
245
+ limit: 10,
241
246
  });
242
247
 
243
248
  for (const run of response.data) {
244
- console.log(`${run.run_id} | ${run.goal}`);
249
+ console.log(`${run.run_id} | ${run.status} | ${run.goal}`);
245
250
  }
246
251
 
247
- // Pagination
248
252
  if (response.pagination.has_more) {
249
- const nextPage = await client.runs.list({ cursor: response.pagination.next_cursor! });
253
+ const nextPage = await client.runs.list({
254
+ cursor: response.pagination.next_cursor ?? undefined,
255
+ });
256
+ console.log(`Fetched ${nextPage.data.length} more runs`);
250
257
  }
251
258
  ```
252
259
 
253
- **Returns `RunListResponse`:**
260
+ ### Query search
254
261
 
255
- | Field | Type | Description |
256
- |-------|------|-------------|
257
- | `data` | `Run[]` | List of runs |
258
- | `pagination.total` | `number` | Total runs matching filters |
259
- | `pagination.has_more` | `boolean` | Whether more pages exist |
260
- | `pagination.next_cursor` | `string \| null` | Pass to `cursor` for the next page |
262
+ ```ts
263
+ import { TinyFish } from "@tiny-fish/sdk";
261
264
 
262
- See the [Pagination Guide](docs/pagination-guide.md) for full pagination loop examples.
265
+ const client = new TinyFish();
263
266
 
264
- ---
267
+ const response = await client.search.query({
268
+ query: "tinyfish sdk",
269
+ location: "US",
270
+ language: "en",
271
+ });
265
272
 
266
- ## Configuration
273
+ console.log(response.query);
274
+ console.log(response.total_results);
275
+ console.log(response.results[0]?.title);
276
+ ```
267
277
 
268
- ### Client options
278
+ ## Streaming events
269
279
 
270
- ```typescript
271
- const client = new TinyFish({
272
- apiKey: "your-api-key", // optional — or set TINYFISH_API_KEY env var
273
- baseURL: "https://agent.tinyfish.ai", // optional — default shown
274
- timeout: 600_000, // optional — milliseconds (default: 600,000 = 10 min)
275
- maxRetries: 2, // optional — retry attempts (default: 2)
276
- });
277
- ```
280
+ `agent.stream()` guarantees this event order:
278
281
 
279
- The SDK retries `408`, `429`, and `5xx` errors automatically with exponential backoff (0.5s base, max 8s wait).
282
+ - `STARTED`
283
+ - `STREAMING_URL`
284
+ - `PROGRESS` repeated zero or more times
285
+ - `COMPLETE`
280
286
 
281
- ### Browser profiles
287
+ `HEARTBEAT` events may also appear, but they are keepalive events rather than part of the guaranteed ordered sequence.
282
288
 
283
- Control the browser environment with `browser_profile`:
289
+ You can consume the stream in two ways:
284
290
 
285
- - **`lite`** (default) fast, lightweight. Good for most sites.
286
- - **`stealth`** anti-detection mode. Use for sites with bot protection.
291
+ - callbacks like `onProgress` and `onComplete`
292
+ - direct iteration with `for await...of`
287
293
 
288
- ```typescript
289
- import { BrowserProfile } from "tinyfish";
294
+ To stop a stream early, call `await stream.close()`.
290
295
 
291
- const response = await client.agent.run({
292
- goal: "...",
293
- url: "...",
294
- browser_profile: BrowserProfile.STEALTH,
296
+ ## Configuration
297
+
298
+ ```ts
299
+ import { TinyFish } from "@tiny-fish/sdk";
300
+
301
+ const client = new TinyFish({
302
+ apiKey: process.env.TINYFISH_API_KEY,
303
+ baseURL: "https://agent.tinyfish.ai",
304
+ timeout: 600_000,
305
+ maxRetries: 2,
295
306
  });
296
307
  ```
297
308
 
298
- ### Proxy configuration
309
+ Defaults:
299
310
 
300
- Route requests through a proxy, optionally pinned to a country:
311
+ - `baseURL`: `https://agent.tinyfish.ai`
312
+ - `timeout`: `600000` ms
313
+ - `maxRetries`: `2`
301
314
 
302
- ```typescript
303
- import { ProxyCountryCode } from "tinyfish";
315
+ The SDK automatically retries `408`, `429`, and `5xx` responses with exponential backoff. Authentication, validation, and not-found errors fail immediately.
304
316
 
305
- const response = await client.agent.run({
306
- goal: "...",
307
- url: "...",
308
- proxy_config: { enabled: true, country_code: ProxyCountryCode.US },
309
- });
310
- ```
317
+ ## Browser profiles and proxies
311
318
 
312
- Available countries: `US`, `GB`, `CA`, `DE`, `FR`, `JP`, `AU`.
319
+ `agent.run()`, `agent.queue()`, and `agent.stream()` all accept the same execution parameters:
313
320
 
314
- See the [Proxy & Browser Profiles Guide](docs/proxy-and-browser-profiles.md) for more details.
321
+ - `goal` and `url` are required
322
+ - `browser_profile` can be `BrowserProfile.LITE` or `BrowserProfile.STEALTH`
323
+ - `proxy_config` can enable a proxy and optionally pin a country
324
+
325
+ Supported proxy country codes:
326
+
327
+ - `US`
328
+ - `GB`
329
+ - `CA`
330
+ - `DE`
331
+ - `FR`
332
+ - `JP`
333
+ - `AU`
315
334
 
316
335
  ## Error handling
317
336
 
318
- ```typescript
319
- import { TinyFish, AuthenticationError, RateLimitError, SDKError } from "tinyfish";
337
+ ```ts
338
+ import {
339
+ AuthenticationError,
340
+ RateLimitError,
341
+ SDKError,
342
+ TinyFish,
343
+ } from "@tiny-fish/sdk";
320
344
 
321
345
  const client = new TinyFish();
322
346
 
323
347
  try {
324
- const response = await client.agent.run({ goal: "...", url: "..." });
348
+ await client.agent.run({
349
+ goal: "Extract the page title",
350
+ url: "https://example.com",
351
+ });
325
352
  } catch (error) {
326
353
  if (error instanceof AuthenticationError) {
327
- console.log("Invalid API key");
354
+ console.error("Invalid API key");
328
355
  } else if (error instanceof RateLimitError) {
329
- console.log("Rate limited (retries exhausted)");
356
+ console.error("Rate limited");
330
357
  } else if (error instanceof SDKError) {
331
- console.log("Something else went wrong");
358
+ console.error(error.message);
359
+ } else {
360
+ throw error;
332
361
  }
333
362
  }
334
363
  ```
335
364
 
336
- The SDK automatically retries transient errors (`408`, `429`, `5xx`) up to `maxRetries` times with exponential backoff. Non-retryable errors (`401`, `400`, `404`) throw immediately.
337
-
338
- For the full exception hierarchy and internal architecture, see [docs/internal/exceptions-and-errors-guide.md](docs/internal/exceptions-and-errors-guide.md).
339
-
340
365
  ## Guides
341
366
 
342
- - [Streaming Guide](docs/streaming-guide.md) — event lifecycle, callbacks vs iteration, event type reference
343
- - [Proxy & Browser Profiles](docs/proxy-and-browser-profiles.md) — stealth mode, proxy countries
344
- - [Pagination Guide](docs/pagination-guide.md) — filtering, sorting, cursor-based pagination
345
- - [Exceptions & Error Handling (internal)](docs/internal/exceptions-and-errors-guide.md) — layer-by-layer architecture
346
- - [Testing Guide](tests/testing-guide.md) — running and writing tests
367
+ - [Streaming guide](https://github.com/tinyfish-io/ux-labs/blob/main/sdk/sdk-typescript/docs/streaming-guide.md)
368
+ - [Pagination guide](https://github.com/tinyfish-io/ux-labs/blob/main/sdk/sdk-typescript/docs/pagination-guide.md)
369
+ - [Proxy and browser profiles](https://github.com/tinyfish-io/ux-labs/blob/main/sdk/sdk-typescript/docs/proxy-and-browser-profiles.md)
370
+ - [Error hierarchy and internals](https://github.com/tinyfish-io/ux-labs/blob/main/sdk/sdk-typescript/docs/internal/exceptions-and-errors-guide.md)
371
+ - [Architecture notes for SDK contributors](https://github.com/tinyfish-io/ux-labs/blob/main/sdk/sdk-typescript/ARCHITECTURE.md)
@@ -7,6 +7,15 @@ export interface ClientOptions {
7
7
  timeout?: number;
8
8
  maxRetries?: number;
9
9
  }
10
+ interface RequestOptions {
11
+ signal?: AbortSignal | undefined;
12
+ }
13
+ interface GetRequestOptions extends RequestOptions {
14
+ params?: Record<string, string | number | boolean | undefined>;
15
+ }
16
+ interface PostRequestOptions extends RequestOptions {
17
+ json?: unknown;
18
+ }
10
19
  export declare class BaseClient {
11
20
  private readonly _apiKey;
12
21
  readonly baseURL: string;
@@ -20,6 +29,7 @@ export declare class BaseClient {
20
29
  protected _buildHeaders(): Record<string, string>;
21
30
  /** Inject api_integration from TF_API_INTEGRATION env var into JSON body. */
22
31
  private static _injectIntegration;
32
+ private _buildRequestSignal;
23
33
  /**
24
34
  * Core request method with retry and error mapping.
25
35
  * All public methods (get, post, postStream) delegate here.
@@ -33,14 +43,9 @@ export declare class BaseClient {
33
43
  private _parseErrorMessage;
34
44
  /** Maps HTTP status codes to typed error classes. Matches Python SDK's _make_status_error. */
35
45
  private _makeStatusError;
36
- get<T>(path: string, options?: {
37
- params?: Record<string, string | number | boolean | undefined>;
38
- }): Promise<T>;
39
- post<T>(path: string, options?: {
40
- json?: unknown;
41
- }): Promise<T>;
42
- postStream(path: string, options?: {
43
- json?: unknown;
44
- }): Promise<ReadableStream<string>>;
46
+ get<T = unknown>(path: string, options?: GetRequestOptions): Promise<T>;
47
+ post<T = unknown>(path: string, options?: PostRequestOptions): Promise<T>;
48
+ postStream(path: string, options?: PostRequestOptions): Promise<ReadableStream<string>>;
45
49
  }
50
+ export {};
46
51
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/_utils/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqBH,MAAM,WAAW,aAAa;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,OAAO,GAAE,aAAkB;IAcvC;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAejC,SAAS,CAAC,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUjD,6EAA6E;IAC7E,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAYjC;;;OAGG;YACW,QAAQ;IAwDtB;;;;OAIG;YACW,kBAAkB;IAuBhC,8FAA8F;YAChF,gBAAgB;IAmCxB,GAAG,CAAC,CAAC,EACV,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAA;KAAE,GAC1E,OAAO,CAAC,CAAC,CAAC;IAgBP,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAK/D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;CAS7F"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/_utils/client.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqBH,MAAM,WAAW,aAAa;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACvB,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CACjC;AAED,UAAU,iBAAkB,SAAQ,cAAc;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;CAC/D;AAED,UAAU,kBAAmB,SAAQ,cAAc;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAYD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;gBAEhB,OAAO,GAAE,aAAkB;IAcvC;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAejC,SAAS,CAAC,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUjD,6EAA6E;IAC7E,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAYjC,OAAO,CAAC,mBAAmB;IAyC3B;;;OAGG;YACW,QAAQ;IAmFtB;;;;OAIG;YACW,kBAAkB;IAuBhC,8FAA8F;YAChF,gBAAgB;IAmCxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC;IAgBvE,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC;IAKzE,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;CAS7F"}