@tiny-fish/sdk 0.0.6 → 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.
- package/README.md +175 -305
- package/dist/_utils/client.d.ts +2 -2
- package/dist/_utils/client.d.ts.map +1 -1
- package/dist/_utils/client.js.map +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +34 -63
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/types.d.ts +255 -129
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +133 -41
- package/dist/agent/types.js.map +1 -1
- package/dist/browser/index.d.ts +2 -4
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +10 -2
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/types.d.ts +13 -9
- package/dist/browser/types.d.ts.map +1 -1
- package/dist/browser/types.js +12 -2
- package/dist/browser/types.js.map +1 -1
- package/dist/fetch/index.d.ts +1 -1
- package/dist/fetch/index.d.ts.map +1 -1
- package/dist/fetch/index.js +21 -13
- package/dist/fetch/index.js.map +1 -1
- package/dist/fetch/types.d.ts +167 -49
- package/dist/fetch/types.d.ts.map +1 -1
- package/dist/fetch/types.js +65 -7
- package/dist/fetch/types.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/runs/index.d.ts +1 -1
- package/dist/runs/index.d.ts.map +1 -1
- package/dist/runs/index.js +25 -16
- package/dist/runs/index.js.map +1 -1
- package/dist/runs/types.d.ts +114 -66
- package/dist/runs/types.d.ts.map +1 -1
- package/dist/runs/types.js +48 -6
- package/dist/runs/types.js.map +1 -1
- package/dist/search/index.d.ts +2 -6
- package/dist/search/index.d.ts.map +1 -1
- package/dist/search/index.js +13 -8
- package/dist/search/index.js.map +1 -1
- package/dist/search/types.d.ts +29 -21
- package/dist/search/types.d.ts.map +1 -1
- package/dist/search/types.js +22 -2
- package/dist/search/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# TinyFish TypeScript SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Typed access to TinyFish web agents, fetch extraction, remote browser sessions, run history, and search.
|
|
4
4
|
|
|
5
|
-
|
|
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
|
|
6
13
|
|
|
7
14
|
## Installation
|
|
8
15
|
|
|
@@ -10,81 +17,26 @@ For SDK design conventions and how new API surfaces should be added, see [ARCHIT
|
|
|
10
17
|
npm install @tiny-fish/sdk
|
|
11
18
|
```
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
## Get your API key
|
|
20
|
+
Requirements:
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
- Node.js 18+
|
|
23
|
+
- a TinyFish API key from [agent.tinyfish.ai/api-keys](https://agent.tinyfish.ai/api-keys)
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
Authenticate with either the constructor or `TINYFISH_API_KEY`:
|
|
20
26
|
|
|
21
|
-
```
|
|
27
|
+
```ts
|
|
22
28
|
import { TinyFish } from "@tiny-fish/sdk";
|
|
23
29
|
|
|
24
|
-
const client = new TinyFish({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
goal: "What is the current Bitcoin price?",
|
|
29
|
-
url: "https://www.coinbase.com/price/bitcoin",
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
onProgress: (e) => console.log(` > ${e.purpose}`),
|
|
33
|
-
onComplete: (e) => console.log(e.result),
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
for await (const event of stream) {
|
|
38
|
-
// Callbacks fire automatically during iteration
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
Need per-request cancellation without changing the client-wide timeout? Pass an `AbortSignal` as the optional second argument:
|
|
43
|
-
|
|
44
|
-
```typescript
|
|
45
|
-
const controller = new AbortController();
|
|
46
|
-
|
|
47
|
-
const stream = await client.agent.stream(
|
|
48
|
-
{
|
|
49
|
-
goal: "Extract the top 5 headlines",
|
|
50
|
-
url: "https://news.ycombinator.com",
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
signal: controller.signal,
|
|
54
|
-
},
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
controller.abort();
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
Or set the `TINYFISH_API_KEY` environment variable and omit `apiKey`:
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
const client = new TinyFish();
|
|
30
|
+
const client = new TinyFish({
|
|
31
|
+
apiKey: process.env.TINYFISH_API_KEY,
|
|
32
|
+
});
|
|
64
33
|
```
|
|
65
34
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
## Methods
|
|
69
|
-
|
|
70
|
-
| Method | Description | Returns | Blocks? |
|
|
71
|
-
|--------|-------------|---------|---------|
|
|
72
|
-
| [`agent.stream()`](#agentstream--real-time-events) | Stream live SSE events as the agent works | `AgentStream` | No |
|
|
73
|
-
| [`agent.run()`](#agentrun--block-until-done) | Run an automation, wait for the result | `AgentRunResponse` | Yes |
|
|
74
|
-
| [`agent.queue()`](#agentqueue--fire-and-forget) | Start an automation, return immediately | `AgentRunAsyncResponse` | No |
|
|
75
|
-
| [`browser.sessions.create()`](#browsersessionscreate--create-a-browser-session) | Create a remote browser session | `BrowserSession` | — |
|
|
76
|
-
| [`fetch.getContents()`](#fetchgetcontents--fetch-and-extract-content) | Fetch URLs and return extracted content | `FetchResponse` | — |
|
|
77
|
-
| [`runs.get()`](#runsget--retrieve-a-single-run) | Retrieve a single run by ID | `Run` | — |
|
|
78
|
-
| [`runs.list()`](#runslist--list-and-filter-runs) | List runs with filtering, sorting, pagination | `RunListResponse` | — |
|
|
79
|
-
| [`search.query()`](#searchquery--run-a-web-search) | Run a web search query | `SearchQueryResponse` | — |
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
### `agent.stream()` — real-time events
|
|
35
|
+
## Quickstart
|
|
84
36
|
|
|
85
|
-
|
|
37
|
+
`agent.stream()` is the best default for product integrations because it gives you progress updates while the run is happening.
|
|
86
38
|
|
|
87
|
-
```
|
|
39
|
+
```ts
|
|
88
40
|
import { TinyFish } from "@tiny-fish/sdk";
|
|
89
41
|
|
|
90
42
|
const client = new TinyFish();
|
|
@@ -95,29 +47,23 @@ const stream = await client.agent.stream(
|
|
|
95
47
|
url: "https://news.ycombinator.com",
|
|
96
48
|
},
|
|
97
49
|
{
|
|
98
|
-
onStarted: (
|
|
99
|
-
onStreamingUrl: (
|
|
100
|
-
onProgress: (
|
|
101
|
-
onComplete: (
|
|
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),
|
|
102
54
|
},
|
|
103
55
|
);
|
|
104
56
|
|
|
105
57
|
for await (const event of stream) {
|
|
106
|
-
// Callbacks fire automatically during iteration.
|
|
107
|
-
// You can also inspect events directly:
|
|
108
58
|
if (event.type === "COMPLETE") {
|
|
109
|
-
console.log(event.
|
|
59
|
+
console.log(`Finished with status ${event.status}`);
|
|
110
60
|
}
|
|
111
61
|
}
|
|
112
62
|
```
|
|
113
63
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Call `stream.close()` to abort early and stop yielding events.
|
|
117
|
-
|
|
118
|
-
The second argument also accepts `signal` for request-scoped cancellation:
|
|
64
|
+
Need request-scoped cancellation without changing the client-wide timeout? Pass an `AbortSignal` as the optional second argument:
|
|
119
65
|
|
|
120
|
-
```
|
|
66
|
+
```ts
|
|
121
67
|
const controller = new AbortController();
|
|
122
68
|
|
|
123
69
|
const stream = await client.agent.stream(
|
|
@@ -127,53 +73,67 @@ const stream = await client.agent.stream(
|
|
|
127
73
|
},
|
|
128
74
|
{
|
|
129
75
|
signal: controller.signal,
|
|
130
|
-
onProgress: (e) => console.log(e.purpose),
|
|
131
76
|
},
|
|
132
77
|
);
|
|
133
78
|
|
|
134
79
|
controller.abort();
|
|
135
80
|
```
|
|
136
81
|
|
|
137
|
-
|
|
82
|
+
## Choose an API
|
|
138
83
|
|
|
139
|
-
|
|
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` |
|
|
140
94
|
|
|
141
|
-
|
|
95
|
+
## Core workflows
|
|
142
96
|
|
|
143
|
-
|
|
97
|
+
### Run and wait
|
|
144
98
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
99
|
+
Use `agent.run()` for scripts, cron jobs, and backend tasks that should block until the result is ready.
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
import {
|
|
103
|
+
BrowserProfile,
|
|
104
|
+
ProxyCountryCode,
|
|
105
|
+
RunStatus,
|
|
106
|
+
TinyFish,
|
|
107
|
+
} from "@tiny-fish/sdk";
|
|
148
108
|
|
|
149
109
|
const client = new TinyFish();
|
|
150
110
|
|
|
151
111
|
const response = await client.agent.run({
|
|
152
|
-
goal: "
|
|
153
|
-
url: "https://
|
|
154
|
-
browser_profile: BrowserProfile.STEALTH,
|
|
155
|
-
proxy_config: {
|
|
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: {
|
|
156
116
|
enabled: true,
|
|
157
|
-
country_code: ProxyCountryCode.US,
|
|
117
|
+
country_code: ProxyCountryCode.US,
|
|
158
118
|
},
|
|
159
119
|
});
|
|
160
120
|
|
|
161
121
|
if (response.status === RunStatus.COMPLETED) {
|
|
162
122
|
console.log(response.result);
|
|
163
123
|
} else {
|
|
164
|
-
console.
|
|
124
|
+
console.error(response.error?.message);
|
|
165
125
|
}
|
|
166
126
|
```
|
|
167
127
|
|
|
168
|
-
|
|
128
|
+
`run()` also accepts an optional second argument with `signal`:
|
|
169
129
|
|
|
170
|
-
```
|
|
130
|
+
```ts
|
|
171
131
|
const controller = new AbortController();
|
|
172
132
|
|
|
173
133
|
const response = await client.agent.run(
|
|
174
134
|
{
|
|
175
|
-
goal: "Extract the
|
|
176
|
-
url: "https://
|
|
135
|
+
goal: "Extract the page title",
|
|
136
|
+
url: "https://example.com",
|
|
177
137
|
},
|
|
178
138
|
{
|
|
179
139
|
signal: controller.signal,
|
|
@@ -181,113 +141,51 @@ const response = await client.agent.run(
|
|
|
181
141
|
);
|
|
182
142
|
```
|
|
183
143
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
| Field | Type | Description |
|
|
187
|
-
|-------|------|-------------|
|
|
188
|
-
| `status` | `RunStatus` | `COMPLETED`, `FAILED`, etc. |
|
|
189
|
-
| `run_id` | `string \| null` | Unique run identifier |
|
|
190
|
-
| `result` | `Record<string, unknown> \| null` | Extracted data (`null` if failed) |
|
|
191
|
-
| `error` | `RunError \| null` | Error details (`null` if succeeded) |
|
|
192
|
-
| `num_of_steps` | `number` | Number of steps the agent took |
|
|
193
|
-
| `started_at` | `string \| null` | ISO 8601 timestamp when the run started |
|
|
194
|
-
| `finished_at` | `string \| null` | ISO 8601 timestamp when the run finished |
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
### `agent.queue()` — fire and forget
|
|
144
|
+
### Queue and poll
|
|
199
145
|
|
|
200
|
-
|
|
146
|
+
Use `agent.queue()` when you do not want to keep the request open.
|
|
201
147
|
|
|
202
|
-
```
|
|
203
|
-
import {
|
|
148
|
+
```ts
|
|
149
|
+
import { RunStatus, TinyFish } from "@tiny-fish/sdk";
|
|
204
150
|
|
|
205
151
|
const client = new TinyFish();
|
|
206
152
|
|
|
207
153
|
const queued = await client.agent.queue({
|
|
208
|
-
goal: "Extract the
|
|
209
|
-
url: "https://
|
|
154
|
+
goal: "Extract all job titles from the careers page",
|
|
155
|
+
url: "https://example.com/careers",
|
|
210
156
|
});
|
|
211
157
|
|
|
212
158
|
if (queued.error) {
|
|
213
|
-
|
|
214
|
-
process.exit(1);
|
|
159
|
+
throw new Error(queued.error.message);
|
|
215
160
|
}
|
|
216
161
|
|
|
217
|
-
|
|
162
|
+
let run = await client.runs.get(queued.run_id);
|
|
218
163
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (run.status === RunStatus.COMPLETED || run.status === RunStatus.FAILED) {
|
|
223
|
-
console.log(run.result);
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
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);
|
|
227
167
|
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
`queue()` also accepts an optional `{ signal }` second argument when you want to cancel just that enqueue request.
|
|
231
|
-
|
|
232
|
-
**Returns `AgentRunAsyncResponse`** — a discriminated union. Check `error` to narrow the type:
|
|
233
168
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (response.error) {
|
|
237
|
-
// response.run_id is null here
|
|
238
|
-
console.error(response.error.message);
|
|
169
|
+
if (run.status === RunStatus.COMPLETED) {
|
|
170
|
+
console.log(run.result);
|
|
239
171
|
} else {
|
|
240
|
-
|
|
241
|
-
const run = await client.runs.get(response.run_id);
|
|
172
|
+
console.error(run.error?.message ?? `Run ended with status: ${run.status}`);
|
|
242
173
|
}
|
|
243
174
|
```
|
|
244
175
|
|
|
245
|
-
|
|
246
|
-
|-------|------|-------------|
|
|
247
|
-
| `run_id` | `string \| null` | Run ID to poll with `runs.get()` |
|
|
248
|
-
| `error` | `RunError \| null` | Error if queuing itself failed |
|
|
176
|
+
`queue()` also accepts an optional second argument with `signal` for cancelling just the enqueue request.
|
|
249
177
|
|
|
250
|
-
|
|
178
|
+
### Fetch clean content
|
|
251
179
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
Create a remote browser session and get back the connection details for direct CDP control. Pass a `url` to hint routing and start the session on a target page, or omit it to start at `about:blank`.
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
import { TinyFish } from "@tiny-fish/sdk";
|
|
180
|
+
Use `fetch.getContents()` when you want extracted content from URLs without a browser-agent run.
|
|
258
181
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
const session = await client.browser.sessions.create({
|
|
262
|
-
url: "https://example.com",
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
console.log(session.session_id);
|
|
266
|
-
console.log(session.cdp_url);
|
|
267
|
-
console.log(session.base_url);
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
**Returns `BrowserSession`:**
|
|
271
|
-
|
|
272
|
-
| Field | Type | Description |
|
|
273
|
-
|-------|------|-------------|
|
|
274
|
-
| `session_id` | `string` | Unique browser session identifier |
|
|
275
|
-
| `cdp_url` | `string` | CDP WebSocket URL for connecting to the browser |
|
|
276
|
-
| `base_url` | `string` | HTTPS base URL for the browser session |
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
### `fetch.getContents()` — fetch and extract content
|
|
281
|
-
|
|
282
|
-
Fetch one or more URLs and return clean extracted content in markdown, html, or json form.
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
182
|
+
```ts
|
|
285
183
|
import { FetchFormat, TinyFish } from "@tiny-fish/sdk";
|
|
286
184
|
|
|
287
185
|
const client = new TinyFish();
|
|
288
186
|
|
|
289
187
|
const response = await client.fetch.getContents({
|
|
290
|
-
urls: ["https://example.com"],
|
|
188
|
+
urls: ["https://example.com", "https://example.org"],
|
|
291
189
|
format: FetchFormat.Markdown,
|
|
292
190
|
links: true,
|
|
293
191
|
image_links: false,
|
|
@@ -297,100 +195,71 @@ console.log(response.results);
|
|
|
297
195
|
console.log(response.errors);
|
|
298
196
|
```
|
|
299
197
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
| Field | Type | Description |
|
|
303
|
-
|-------|------|-------------|
|
|
304
|
-
| `results` | `FetchResult[]` | Successfully fetched URLs and extracted content |
|
|
305
|
-
| `errors` | `FetchError[]` | URLs that failed to fetch |
|
|
306
|
-
|
|
307
|
-
`FetchResult.text` is:
|
|
198
|
+
`fetch.getContents()` accepts 1 to 10 URLs. `FetchResult.text` is:
|
|
308
199
|
|
|
309
|
-
- `string` for `
|
|
310
|
-
- `Record<string, unknown>` for `
|
|
200
|
+
- `string` for `FetchFormat.Markdown` and `FetchFormat.Html`
|
|
201
|
+
- `Record<string, unknown>` for `FetchFormat.Json`
|
|
311
202
|
- `null` if extraction failed for that item
|
|
312
203
|
|
|
313
|
-
|
|
204
|
+
### Create a browser session
|
|
314
205
|
|
|
315
|
-
|
|
206
|
+
Use `browser.sessions.create()` when you want connection details for direct browser control.
|
|
316
207
|
|
|
317
|
-
|
|
208
|
+
```ts
|
|
209
|
+
import { TinyFish } from "@tiny-fish/sdk";
|
|
318
210
|
|
|
319
|
-
|
|
320
|
-
const run = await client.runs.get("run_abc123");
|
|
211
|
+
const client = new TinyFish();
|
|
321
212
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
console.log(
|
|
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);
|
|
327
220
|
```
|
|
328
221
|
|
|
329
|
-
|
|
222
|
+
### Inspect and list runs
|
|
330
223
|
|
|
331
|
-
|
|
332
|
-
|-------|------|-------------|
|
|
333
|
-
| `run_id` | `string` | Unique identifier |
|
|
334
|
-
| `status` | `RunStatus` | `PENDING`, `RUNNING`, `COMPLETED`, `FAILED`, `CANCELLED` |
|
|
335
|
-
| `goal` | `string` | The goal that was given |
|
|
336
|
-
| `result` | `Record<string, unknown> \| null` | Extracted data (`null` if not completed) |
|
|
337
|
-
| `error` | `RunError \| null` | Error details (`null` if succeeded) |
|
|
338
|
-
| `streaming_url` | `string \| null` | Live browser URL (available while running) |
|
|
339
|
-
| `browser_config` | `BrowserConfig \| null` | Proxy/browser settings used |
|
|
340
|
-
| `created_at` | `string` | ISO 8601 timestamp when the run was created |
|
|
341
|
-
| `started_at` | `string \| null` | ISO 8601 timestamp when execution started |
|
|
342
|
-
| `finished_at` | `string \| null` | ISO 8601 timestamp when execution finished |
|
|
343
|
-
| `num_of_steps` | `number` | Number of steps the agent took |
|
|
224
|
+
Fetch a single run when you already know its `run_id`:
|
|
344
225
|
|
|
345
|
-
|
|
226
|
+
```ts
|
|
227
|
+
const run = await client.runs.get("run_abc123");
|
|
346
228
|
|
|
347
|
-
|
|
229
|
+
console.log(run.status);
|
|
230
|
+
console.log(run.result);
|
|
231
|
+
console.log(run.streaming_url);
|
|
232
|
+
```
|
|
348
233
|
|
|
349
|
-
|
|
234
|
+
Use `runs.list()` for filtering and pagination:
|
|
350
235
|
|
|
351
|
-
|
|
236
|
+
```ts
|
|
237
|
+
import { RunStatus, SortDirection, TinyFish } from "@tiny-fish/sdk";
|
|
352
238
|
|
|
353
|
-
|
|
354
|
-
import { RunStatus, SortDirection } from "@tiny-fish/sdk";
|
|
239
|
+
const client = new TinyFish();
|
|
355
240
|
|
|
356
241
|
const response = await client.runs.list({
|
|
357
|
-
status: RunStatus.COMPLETED,
|
|
358
|
-
goal: "headlines",
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
sort_direction: SortDirection.DESC, // optional — "asc" or "desc"
|
|
362
|
-
limit: 10, // optional — max runs per page
|
|
363
|
-
cursor: undefined, // optional — pagination cursor from previous response
|
|
242
|
+
status: RunStatus.COMPLETED,
|
|
243
|
+
goal: "headlines",
|
|
244
|
+
sort_direction: SortDirection.DESC,
|
|
245
|
+
limit: 10,
|
|
364
246
|
});
|
|
365
247
|
|
|
366
248
|
for (const run of response.data) {
|
|
367
|
-
console.log(`${run.run_id} | ${run.goal}`);
|
|
249
|
+
console.log(`${run.run_id} | ${run.status} | ${run.goal}`);
|
|
368
250
|
}
|
|
369
251
|
|
|
370
|
-
// Pagination
|
|
371
252
|
if (response.pagination.has_more) {
|
|
372
|
-
const nextPage = await client.runs.list({
|
|
253
|
+
const nextPage = await client.runs.list({
|
|
254
|
+
cursor: response.pagination.next_cursor ?? undefined,
|
|
255
|
+
});
|
|
256
|
+
console.log(`Fetched ${nextPage.data.length} more runs`);
|
|
373
257
|
}
|
|
374
258
|
```
|
|
375
259
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
| Field | Type | Description |
|
|
379
|
-
|-------|------|-------------|
|
|
380
|
-
| `data` | `Run[]` | List of runs |
|
|
381
|
-
| `pagination.total` | `number` | Total runs matching filters |
|
|
382
|
-
| `pagination.has_more` | `boolean` | Whether more pages exist |
|
|
383
|
-
| `pagination.next_cursor` | `string \| null` | Pass to `cursor` for the next page |
|
|
384
|
-
|
|
385
|
-
See the [Pagination Guide](docs/pagination-guide.md) for full pagination loop examples.
|
|
260
|
+
### Query search
|
|
386
261
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
### `search.query()` — run a web search
|
|
390
|
-
|
|
391
|
-
Run a typed search query through the TinyFish Search API.
|
|
392
|
-
|
|
393
|
-
```typescript
|
|
262
|
+
```ts
|
|
394
263
|
import { TinyFish } from "@tiny-fish/sdk";
|
|
395
264
|
|
|
396
265
|
const client = new TinyFish();
|
|
@@ -406,96 +275,97 @@ console.log(response.total_results);
|
|
|
406
275
|
console.log(response.results[0]?.title);
|
|
407
276
|
```
|
|
408
277
|
|
|
409
|
-
|
|
278
|
+
## Streaming events
|
|
279
|
+
|
|
280
|
+
`agent.stream()` guarantees this event order:
|
|
410
281
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
| `total_results` | `number` | Total number of results returned |
|
|
282
|
+
- `STARTED`
|
|
283
|
+
- `STREAMING_URL`
|
|
284
|
+
- `PROGRESS` repeated zero or more times
|
|
285
|
+
- `COMPLETE`
|
|
416
286
|
|
|
417
|
-
|
|
287
|
+
`HEARTBEAT` events may also appear, but they are keepalive events rather than part of the guaranteed ordered sequence.
|
|
418
288
|
|
|
419
|
-
|
|
289
|
+
You can consume the stream in two ways:
|
|
290
|
+
|
|
291
|
+
- callbacks like `onProgress` and `onComplete`
|
|
292
|
+
- direct iteration with `for await...of`
|
|
293
|
+
|
|
294
|
+
To stop a stream early, call `await stream.close()`.
|
|
420
295
|
|
|
421
296
|
## Configuration
|
|
422
297
|
|
|
423
|
-
|
|
298
|
+
```ts
|
|
299
|
+
import { TinyFish } from "@tiny-fish/sdk";
|
|
424
300
|
|
|
425
|
-
```typescript
|
|
426
301
|
const client = new TinyFish({
|
|
427
|
-
apiKey:
|
|
428
|
-
baseURL: "https://agent.tinyfish.ai",
|
|
429
|
-
timeout: 600_000,
|
|
430
|
-
maxRetries: 2,
|
|
302
|
+
apiKey: process.env.TINYFISH_API_KEY,
|
|
303
|
+
baseURL: "https://agent.tinyfish.ai",
|
|
304
|
+
timeout: 600_000,
|
|
305
|
+
maxRetries: 2,
|
|
431
306
|
});
|
|
432
307
|
```
|
|
433
308
|
|
|
434
|
-
|
|
309
|
+
Defaults:
|
|
435
310
|
|
|
436
|
-
|
|
311
|
+
- `baseURL`: `https://agent.tinyfish.ai`
|
|
312
|
+
- `timeout`: `600000` ms
|
|
313
|
+
- `maxRetries`: `2`
|
|
437
314
|
|
|
438
|
-
|
|
315
|
+
The SDK automatically retries `408`, `429`, and `5xx` responses with exponential backoff. Authentication, validation, and not-found errors fail immediately.
|
|
439
316
|
|
|
440
|
-
|
|
441
|
-
- **`stealth`** — anti-detection mode. Use for sites with bot protection.
|
|
317
|
+
## Browser profiles and proxies
|
|
442
318
|
|
|
443
|
-
|
|
444
|
-
import { BrowserProfile } from "@tiny-fish/sdk";
|
|
319
|
+
`agent.run()`, `agent.queue()`, and `agent.stream()` all accept the same execution parameters:
|
|
445
320
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
browser_profile: BrowserProfile.STEALTH,
|
|
450
|
-
});
|
|
451
|
-
```
|
|
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
|
|
452
324
|
|
|
453
|
-
|
|
325
|
+
Supported proxy country codes:
|
|
454
326
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
url: "...",
|
|
463
|
-
proxy_config: { enabled: true, country_code: ProxyCountryCode.US },
|
|
464
|
-
});
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
Available countries: `US`, `GB`, `CA`, `DE`, `FR`, `JP`, `AU`.
|
|
468
|
-
|
|
469
|
-
See the [Proxy & Browser Profiles Guide](docs/proxy-and-browser-profiles.md) for more details.
|
|
327
|
+
- `US`
|
|
328
|
+
- `GB`
|
|
329
|
+
- `CA`
|
|
330
|
+
- `DE`
|
|
331
|
+
- `FR`
|
|
332
|
+
- `JP`
|
|
333
|
+
- `AU`
|
|
470
334
|
|
|
471
335
|
## Error handling
|
|
472
336
|
|
|
473
|
-
```
|
|
474
|
-
import {
|
|
337
|
+
```ts
|
|
338
|
+
import {
|
|
339
|
+
AuthenticationError,
|
|
340
|
+
RateLimitError,
|
|
341
|
+
SDKError,
|
|
342
|
+
TinyFish,
|
|
343
|
+
} from "@tiny-fish/sdk";
|
|
475
344
|
|
|
476
345
|
const client = new TinyFish();
|
|
477
346
|
|
|
478
347
|
try {
|
|
479
|
-
|
|
348
|
+
await client.agent.run({
|
|
349
|
+
goal: "Extract the page title",
|
|
350
|
+
url: "https://example.com",
|
|
351
|
+
});
|
|
480
352
|
} catch (error) {
|
|
481
353
|
if (error instanceof AuthenticationError) {
|
|
482
|
-
console.
|
|
354
|
+
console.error("Invalid API key");
|
|
483
355
|
} else if (error instanceof RateLimitError) {
|
|
484
|
-
console.
|
|
356
|
+
console.error("Rate limited");
|
|
485
357
|
} else if (error instanceof SDKError) {
|
|
486
|
-
console.
|
|
358
|
+
console.error(error.message);
|
|
359
|
+
} else {
|
|
360
|
+
throw error;
|
|
487
361
|
}
|
|
488
362
|
}
|
|
489
363
|
```
|
|
490
364
|
|
|
491
|
-
The SDK automatically retries transient errors (`408`, `429`, `5xx`) up to `maxRetries` times with exponential backoff. Non-retryable errors (`401`, `400`, `404`) throw immediately.
|
|
492
|
-
|
|
493
|
-
For the full exception hierarchy and internal architecture, see [docs/internal/exceptions-and-errors-guide.md](docs/internal/exceptions-and-errors-guide.md).
|
|
494
|
-
|
|
495
365
|
## Guides
|
|
496
366
|
|
|
497
|
-
- [Streaming
|
|
498
|
-
- [
|
|
499
|
-
- [
|
|
500
|
-
- [
|
|
501
|
-
- [
|
|
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)
|
package/dist/_utils/client.d.ts
CHANGED
|
@@ -43,8 +43,8 @@ export declare class BaseClient {
|
|
|
43
43
|
private _parseErrorMessage;
|
|
44
44
|
/** Maps HTTP status codes to typed error classes. Matches Python SDK's _make_status_error. */
|
|
45
45
|
private _makeStatusError;
|
|
46
|
-
get<T>(path: string, options?: GetRequestOptions): Promise<T>;
|
|
47
|
-
post<T>(path: string, options?: PostRequestOptions): Promise<T>;
|
|
46
|
+
get<T = unknown>(path: string, options?: GetRequestOptions): Promise<T>;
|
|
47
|
+
post<T = unknown>(path: string, options?: PostRequestOptions): Promise<T>;
|
|
48
48
|
postStream(path: string, options?: PostRequestOptions): Promise<ReadableStream<string>>;
|
|
49
49
|
}
|
|
50
50
|
export {};
|