Skip to content

Commit 1320841

Browse files
committed
stash
1 parent f730bbb commit 1320841

File tree

4 files changed

+125
-34
lines changed

4 files changed

+125
-34
lines changed

examples/stream-zod.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env -S npm run tsn -T
2+
3+
import { BrowserUse } from 'browser-use-sdk';
4+
import { TaskViewWithSchema } from 'browser-use-sdk/lib/parse';
5+
import z from 'zod';
6+
7+
const HackerNewsResponse = z.object({
8+
title: z.string(),
9+
url: z.string(),
10+
score: z.number(),
11+
});
12+
13+
const TaskOutput = z.object({
14+
posts: z.array(HackerNewsResponse),
15+
});
16+
17+
async function main() {
18+
// gets API Key from environment variable BROWSER_USE_API_KEY
19+
const browseruse = new BrowserUse();
20+
21+
console.log('Creating task and starting stream...\n');
22+
23+
// Create a task and get the stream
24+
const stream = browseruse.tasks.stream({
25+
task: 'Extract top 10 Hacker News posts and return the title, url, and score',
26+
structuredOutputJson: TaskOutput,
27+
});
28+
29+
// Get a reader from the stream
30+
const reader = stream.getReader();
31+
const decoder = new TextDecoder();
32+
33+
try {
34+
// Read the stream chunk by chunk
35+
loop: while (true) {
36+
const { done, value } = await reader.read();
37+
38+
if (done) {
39+
console.log('\nStream completed');
40+
break loop;
41+
}
42+
43+
// Decode the chunk and parse the Server-Sent Events format
44+
const chunk = decoder.decode(value, { stream: true });
45+
const lines = chunk.split('\n');
46+
47+
for (const line of lines) {
48+
if (line.startsWith('event: ')) {
49+
const event = line.slice(7);
50+
process.stdout.write(`\n[${event}] `);
51+
} else if (line.startsWith('data: ')) {
52+
const data = line.slice(6);
53+
if (data.trim() && data !== '{}') {
54+
try {
55+
const parsed = JSON.parse(data) as TaskViewWithSchema<typeof TaskOutput>;
56+
57+
process.stdout.write(`${parsed.status}`);
58+
if (parsed.sessionLiveUrl) {
59+
process.stdout.write(` | Live URL: ${parsed.sessionLiveUrl}`);
60+
}
61+
62+
if (parsed.steps.length > 0) {
63+
const latestStep = parsed.steps[parsed.steps.length - 1];
64+
process.stdout.write(` | ${latestStep!.nextGoal}`);
65+
}
66+
67+
if (parsed.status === 'finished') {
68+
process.stdout.write(`\n\nOUTPUT:`);
69+
70+
for (const post of parsed.doneOutput!.posts) {
71+
process.stdout.write(`\n - ${post.title} (${post.score}) ${post.url}`);
72+
}
73+
74+
break loop;
75+
}
76+
} catch (e) {
77+
process.stdout.write(`Raw data: ${data}`);
78+
}
79+
}
80+
}
81+
}
82+
}
83+
} catch (error) {
84+
console.error('Error reading stream:', error);
85+
} finally {
86+
reader.releaseLock();
87+
}
88+
}
89+
90+
main().catch(console.error);

examples/stream.ts

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -32,36 +32,7 @@ async function main() {
3232
const lines = chunk.split('\n');
3333

3434
for (const line of lines) {
35-
if (line.startsWith('event: ')) {
36-
const event = line.slice(7);
37-
process.stdout.write(`\n[${event}] `);
38-
} else if (line.startsWith('data: ')) {
39-
const data = line.slice(6);
40-
if (data.trim() && data !== '{}') {
41-
try {
42-
const parsed = JSON.parse(data) as BrowserUse.TaskView;
43-
44-
process.stdout.write(`${parsed.status}`);
45-
if (parsed.sessionLiveUrl) {
46-
process.stdout.write(` | Live URL: ${parsed.sessionLiveUrl}`);
47-
}
48-
49-
if (parsed.steps.length > 0) {
50-
const latestStep = parsed.steps[parsed.steps.length - 1];
51-
process.stdout.write(` | ${latestStep!.nextGoal}`);
52-
}
53-
54-
if (parsed.status === 'finished') {
55-
process.stdout.write(`\n\nOUTPUT: ${parsed.doneOutput}`);
56-
// Close the reader and exit the main loop when task is finished
57-
reader.releaseLock();
58-
return;
59-
}
60-
} catch (e) {
61-
process.stdout.write(`Raw data: ${data}`);
62-
}
63-
}
64-
}
35+
console.log(line);
6536
}
6637
}
6738
} catch (error) {
File renamed without changes.

src/resources/tasks.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
22

3-
import type { ZodType } from 'zod';
3+
import { ZodType } from 'zod';
44

55
import { APIPromise } from '../core/api-promise';
66
import { APIResource } from '../core/resource';
@@ -131,7 +131,15 @@ export class Tasks extends APIResource {
131131
} while (true);
132132
}
133133

134-
stream(body: TaskCreateParams, options?: RequestOptions) {
134+
stream<T extends ZodType>(
135+
body: TaskCreateParamsWithSchema<T>,
136+
options?: RequestOptions,
137+
): ReadableStream<Uint8Array<ArrayBufferLike>>;
138+
stream(body: TaskCreateParams, options?: RequestOptions): ReadableStream<Uint8Array<ArrayBufferLike>>;
139+
stream(
140+
body: TaskCreateParams | TaskCreateParamsWithSchema<ZodType>,
141+
options?: RequestOptions,
142+
): ReadableStream<Uint8Array<ArrayBufferLike>> {
135143
const self = this;
136144

137145
const enc = new TextEncoder();
@@ -142,12 +150,34 @@ export class Tasks extends APIResource {
142150
controller.enqueue(enc.encode(': connected\n\n'));
143151

144152
try {
145-
for await (const msg of self.watch(body, { interval: 500 }, options)) {
153+
let req: TaskCreateParams;
154+
155+
if (
156+
'structuredOutputJson' in body &&
157+
body.structuredOutputJson != null &&
158+
typeof body.structuredOutputJson === 'object'
159+
) {
160+
req = {
161+
...body,
162+
structuredOutputJson: stringifyStructuredOutput(body.structuredOutputJson),
163+
};
164+
} else {
165+
req = body as TaskCreateParams;
166+
}
167+
168+
for await (const msg of self.watch(req, { interval: 500 }, options)) {
146169
if (options?.signal?.aborted) {
147170
break;
148171
}
149172

150-
const data = JSON.stringify(msg.data);
173+
let data: string;
174+
175+
if (body.structuredOutputJson != null && typeof body.structuredOutputJson === 'object') {
176+
const parsed = parseStructuredTaskOutput<ZodType>(msg.data, body.structuredOutputJson);
177+
data = JSON.stringify(parsed);
178+
} else {
179+
data = JSON.stringify(msg.data);
180+
}
151181

152182
const payload = `event: ${msg.event}\ndata: ${data}\n\n`;
153183
controller.enqueue(enc.encode(payload));

0 commit comments

Comments
 (0)