diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a915e8c..2be9c43 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.1" + ".": "0.2.0" } diff --git a/.stats.yml b/.stats.yml index c28d532..1c0836f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 22 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-86040fd18419e7b4e0947660d9c0ff1abe21550528d2d2a549736cd16f85a92d.yml -openapi_spec_hash: 7c5de9d0f633db35fd9e250fcc834d1f -config_hash: 99e0e445bc20c5723030c315bab52940 +configured_endpoints: 26 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/browser-use%2Fbrowser-use-9ff5409663c58ae9e3ecc9ac764956189e3a70600f5ba1b961bb1dedf0208271.yml +openapi_spec_hash: 9865acb75430d9b799502acbae860df0 +config_hash: 9d52be5177b2ede4cb0633c04f4cc4ef diff --git a/CHANGELOG.md b/CHANGELOG.md index 40f889a..6f4c30c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.2.0 (2025-08-15) + +Full Changelog: [v0.1.1...v0.2.0](https://github.com/browser-use/browser-use-node/compare/v0.1.1...v0.2.0) + +### Features + +* **api:** api update ([3df1a94](https://github.com/browser-use/browser-use-node/commit/3df1a94275d67ce41756227e6f0b749b2c3ed009)) +* **api:** manual updates ([7183cef](https://github.com/browser-use/browser-use-node/commit/7183cef2c497b83985d368cb3a559fc0e11e4082)) + ## 0.1.1 (2025-08-14) Full Changelog: [v0.1.0...v0.1.1](https://github.com/browser-use/browser-use-node/compare/v0.1.0...v0.1.1) diff --git a/README.md b/README.md index 2187a00..024fd22 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ const client = new BrowserUse({ apiKey: process.env['BROWSER_USE_API_KEY'], // This is the default and can be omitted }); -const tasks = await client.tasks.list(); +const me = await client.users.me.retrieve(); -console.log(tasks.items); +console.log(me.additionalCreditsBalanceUsd); ``` ### Request & Response types @@ -43,7 +43,7 @@ const client = new BrowserUse({ apiKey: process.env['BROWSER_USE_API_KEY'], // This is the default and can be omitted }); -const tasks: BrowserUse.TaskListResponse = await client.tasks.list(); +const me: BrowserUse.Users.MeRetrieveResponse = await client.users.me.retrieve(); ``` Documentation for each method, request param, and response field are available in docstrings and will appear on hover in most modern editors. @@ -56,7 +56,7 @@ a subclass of `APIError` will be thrown: ```ts -const tasks = await client.tasks.list().catch(async (err) => { +const me = await client.users.me.retrieve().catch(async (err) => { if (err instanceof BrowserUse.APIError) { console.log(err.status); // 400 console.log(err.name); // BadRequestError @@ -96,7 +96,7 @@ const client = new BrowserUse({ }); // Or, configure per-request: -await client.tasks.list({ +await client.users.me.retrieve({ maxRetries: 5, }); ``` @@ -113,7 +113,7 @@ const client = new BrowserUse({ }); // Override per-request: -await client.tasks.list({ +await client.users.me.retrieve({ timeout: 5 * 1000, }); ``` @@ -136,13 +136,13 @@ Unlike `.asResponse()` this method consumes the body, returning once it is parse ```ts const client = new BrowserUse(); -const response = await client.tasks.list().asResponse(); +const response = await client.users.me.retrieve().asResponse(); console.log(response.headers.get('X-My-Header')); console.log(response.statusText); // access the underlying Response object -const { data: tasks, response: raw } = await client.tasks.list().withResponse(); +const { data: me, response: raw } = await client.users.me.retrieve().withResponse(); console.log(raw.headers.get('X-My-Header')); -console.log(tasks.items); +console.log(me.additionalCreditsBalanceUsd); ``` ### Logging @@ -222,7 +222,7 @@ parameter. This library doesn't validate at runtime that the request matches the send will be sent as-is. ```ts -client.tasks.list({ +client.users.me.retrieve({ // ... // @ts-expect-error baz is not yet public baz: 'undocumented option', diff --git a/api.md b/api.md index 9840ce3..1ee6ece 100644 --- a/api.md +++ b/api.md @@ -1,23 +1,49 @@ +# Users + +## Me + +Types: + +- MeRetrieveResponse + +Methods: + +- client.users.me.retrieve() -> MeRetrieveResponse + +### Files + +Types: + +- FileCreatePresignedURLResponse + +Methods: + +- client.users.me.files.createPresignedURL({ ...params }) -> FileCreatePresignedURLResponse + # Tasks Types: +- FileView - LlmModel +- TaskItemView - TaskStatus +- TaskStepView - TaskView -- TaskRetrieveResponse - TaskListResponse -- TaskRetrieveLogsResponse -- TaskRetrieveOutputFileResponse +- TaskGetLogsResponse +- TaskGetOutputFileResponse +- TaskGetUserUploadedFileResponse Methods: - client.tasks.create({ ...params }) -> TaskView -- client.tasks.retrieve(taskID, { ...params }) -> TaskRetrieveResponse +- client.tasks.retrieve(taskID) -> TaskView - client.tasks.update(taskID, { ...params }) -> TaskView - client.tasks.list({ ...params }) -> TaskListResponse -- client.tasks.retrieveLogs(taskID) -> TaskRetrieveLogsResponse -- client.tasks.retrieveOutputFile(fileName, { ...params }) -> TaskRetrieveOutputFileResponse +- client.tasks.getLogs(taskID) -> TaskGetLogsResponse +- client.tasks.getOutputFile(fileID, { ...params }) -> TaskGetOutputFileResponse +- client.tasks.getUserUploadedFile(fileID, { ...params }) -> TaskGetUserUploadedFileResponse # Sessions @@ -32,19 +58,19 @@ Methods: - client.sessions.retrieve(sessionID, { ...params }) -> SessionView - client.sessions.update(sessionID, { ...params }) -> SessionView - client.sessions.list({ ...params }) -> SessionListResponse +- client.sessions.delete(sessionID) -> void ## PublicShare Types: - ShareView -- PublicShareDeleteResponse Methods: - client.sessions.publicShare.create(sessionID) -> ShareView - client.sessions.publicShare.retrieve(sessionID) -> ShareView -- client.sessions.publicShare.delete(sessionID) -> unknown +- client.sessions.publicShare.delete(sessionID) -> void # BrowserProfiles @@ -53,7 +79,6 @@ Types: - BrowserProfileView - ProxyCountryCode - BrowserProfileListResponse -- BrowserProfileDeleteResponse Methods: @@ -61,7 +86,7 @@ Methods: - client.browserProfiles.retrieve(profileID) -> BrowserProfileView - client.browserProfiles.update(profileID, { ...params }) -> BrowserProfileView - client.browserProfiles.list({ ...params }) -> BrowserProfileListResponse -- client.browserProfiles.delete(profileID) -> unknown +- client.browserProfiles.delete(profileID) -> void # AgentProfiles @@ -69,7 +94,6 @@ Types: - AgentProfileView - AgentProfileListResponse -- AgentProfileDeleteResponse Methods: @@ -77,4 +101,4 @@ Methods: - client.agentProfiles.retrieve(profileID) -> AgentProfileView - client.agentProfiles.update(profileID, { ...params }) -> AgentProfileView - client.agentProfiles.list({ ...params }) -> AgentProfileListResponse -- client.agentProfiles.delete(profileID) -> unknown +- client.agentProfiles.delete(profileID) -> void diff --git a/examples/demo.ts b/examples/demo.ts index 6b976bd..967e863 100755 --- a/examples/demo.ts +++ b/examples/demo.ts @@ -1,7 +1,6 @@ #!/usr/bin/env -S npm run tsn -T import { BrowserUse } from 'browser-use-sdk'; -import { TaskView } from 'browser-use-sdk/resources'; import { spinner } from './utils'; // gets API Key from environment variable BROWSER_USE_API_KEY @@ -18,7 +17,7 @@ async function main() { poll: do { // Wait for Task to Finish - const status = (await browseruse.tasks.retrieve(rsp.id, { statusOnly: false })) as TaskView; + const status = await browseruse.tasks.retrieve(rsp.id); switch (status.status) { case 'started': diff --git a/examples/stream.ts b/examples/stream.ts new file mode 100755 index 0000000..d04fbfb --- /dev/null +++ b/examples/stream.ts @@ -0,0 +1,74 @@ +#!/usr/bin/env -S npm run tsn -T + +import { BrowserUse } from 'browser-use-sdk'; + +async function main() { + // gets API Key from environment variable BROWSER_USE_API_KEY + const browseruse = new BrowserUse(); + + console.log('Creating task and starting stream...\n'); + + // Create a task and get the stream + const stream = browseruse.tasks.stream({ + task: 'What is the weather in San Francisco?', + }); + + // Get a reader from the stream + const reader = stream.getReader(); + const decoder = new TextDecoder(); + + try { + // Read the stream chunk by chunk + while (true) { + const { done, value } = await reader.read(); + + if (done) { + console.log('\nStream completed'); + break; + } + + // Decode the chunk and parse the Server-Sent Events format + const chunk = decoder.decode(value, { stream: true }); + const lines = chunk.split('\n'); + + for (const line of lines) { + if (line.startsWith('event: ')) { + const event = line.slice(7); + process.stdout.write(`\n[${event}] `); + } else if (line.startsWith('data: ')) { + const data = line.slice(6); + if (data.trim() && data !== '{}') { + try { + const parsed = JSON.parse(data) as BrowserUse.TaskView; + + process.stdout.write(`${parsed.status}`); + if (parsed.sessionLiveUrl) { + process.stdout.write(` | Live URL: ${parsed.sessionLiveUrl}`); + } + + if (parsed.steps.length > 0) { + const latestStep = parsed.steps[parsed.steps.length - 1]; + process.stdout.write(` | ${latestStep!.nextGoal}`); + } + + if (parsed.status === 'finished') { + process.stdout.write(`\n\nOUTPUT: ${parsed.doneOutput}`); + // Close the reader and exit the main loop when task is finished + reader.releaseLock(); + return; + } + } catch (e) { + process.stdout.write(`Raw data: ${data}`); + } + } + } + } + } + } catch (error) { + console.error('Error reading stream:', error); + } finally { + reader.releaseLock(); + } +} + +main().catch(console.error); diff --git a/examples/structured-output.ts b/examples/structured-output.ts index f03e2ec..6437269 100755 --- a/examples/structured-output.ts +++ b/examples/structured-output.ts @@ -23,15 +23,16 @@ async function main() { const stop = spinner(() => log); // Create Task - const rsp = await browseruse.tasks.createWithStructuredOutput({ + const rsp = await browseruse.tasks.create({ task: 'Extract top 10 Hacker News posts and return the title, url, and score', structuredOutputJson: TaskOutput, }); poll: do { // Wait for Task to Finish - const status = await browseruse.tasks.retrieveWithStructuredOutput(rsp.id, { - structuredOutputJson: TaskOutput, + const status = await browseruse.tasks.retrieve({ + taskId: rsp.id, + schema: TaskOutput, }); switch (status.status) { @@ -52,12 +53,16 @@ async function main() { } case 'finished': + if (status.doneOutput == null) { + throw new Error('No output'); + } + stop(); // Print Structured Output console.log('TOP POSTS:'); - for (const post of status.doneOutput!.posts) { + for (const post of status.doneOutput.posts) { console.log(` - ${post.title} (${post.score}) ${post.url}`); } diff --git a/package.json b/package.json index c3280f7..0ee0bc0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "browser-use-sdk", - "version": "0.1.1", + "version": "0.2.0", "description": "The official TypeScript library for the Browser Use API", "author": "Browser Use ", "types": "dist/index.d.ts", diff --git a/src/client.ts b/src/client.ts index f1dd05f..46030f1 100644 --- a/src/client.ts +++ b/src/client.ts @@ -18,7 +18,6 @@ import * as API from './resources/index'; import { APIPromise } from './core/api-promise'; import { AgentProfileCreateParams, - AgentProfileDeleteResponse, AgentProfileListParams, AgentProfileListResponse, AgentProfileUpdateParams, @@ -27,7 +26,6 @@ import { } from './resources/agent-profiles'; import { BrowserProfileCreateParams, - BrowserProfileDeleteResponse, BrowserProfileListParams, BrowserProfileListResponse, BrowserProfileUpdateParams, @@ -36,16 +34,19 @@ import { ProxyCountryCode, } from './resources/browser-profiles'; import { + FileView, LlmModel, TaskCreateParams, + TaskGetLogsResponse, + TaskGetOutputFileParams, + TaskGetOutputFileResponse, + TaskGetUserUploadedFileParams, + TaskGetUserUploadedFileResponse, + TaskItemView, TaskListParams, TaskListResponse, - TaskRetrieveLogsResponse, - TaskRetrieveOutputFileParams, - TaskRetrieveOutputFileResponse, - TaskRetrieveParams, - TaskRetrieveResponse, TaskStatus, + TaskStepView, TaskUpdateParams, TaskView, Tasks, @@ -59,6 +60,7 @@ import { SessionView, Sessions, } from './resources/sessions/sessions'; +import { Users } from './resources/users/users'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -756,11 +758,13 @@ export class BrowserUse { static toFile = Uploads.toFile; + users: API.Users = new API.Users(this); tasks: API.Tasks = new API.Tasks(this); sessions: API.Sessions = new API.Sessions(this); browserProfiles: API.BrowserProfiles = new API.BrowserProfiles(this); agentProfiles: API.AgentProfiles = new API.AgentProfiles(this); } +BrowserUse.Users = Users; BrowserUse.Tasks = Tasks; BrowserUse.Sessions = Sessions; BrowserUse.BrowserProfiles = BrowserProfiles; @@ -768,20 +772,25 @@ BrowserUse.AgentProfiles = AgentProfiles; export declare namespace BrowserUse { export type RequestOptions = Opts.RequestOptions; + export { Users as Users }; + export { Tasks as Tasks, + type FileView as FileView, type LlmModel as LlmModel, + type TaskItemView as TaskItemView, type TaskStatus as TaskStatus, + type TaskStepView as TaskStepView, type TaskView as TaskView, - type TaskRetrieveResponse as TaskRetrieveResponse, type TaskListResponse as TaskListResponse, - type TaskRetrieveLogsResponse as TaskRetrieveLogsResponse, - type TaskRetrieveOutputFileResponse as TaskRetrieveOutputFileResponse, + type TaskGetLogsResponse as TaskGetLogsResponse, + type TaskGetOutputFileResponse as TaskGetOutputFileResponse, + type TaskGetUserUploadedFileResponse as TaskGetUserUploadedFileResponse, type TaskCreateParams as TaskCreateParams, - type TaskRetrieveParams as TaskRetrieveParams, type TaskUpdateParams as TaskUpdateParams, type TaskListParams as TaskListParams, - type TaskRetrieveOutputFileParams as TaskRetrieveOutputFileParams, + type TaskGetOutputFileParams as TaskGetOutputFileParams, + type TaskGetUserUploadedFileParams as TaskGetUserUploadedFileParams, }; export { @@ -799,7 +808,6 @@ export declare namespace BrowserUse { type BrowserProfileView as BrowserProfileView, type ProxyCountryCode as ProxyCountryCode, type BrowserProfileListResponse as BrowserProfileListResponse, - type BrowserProfileDeleteResponse as BrowserProfileDeleteResponse, type BrowserProfileCreateParams as BrowserProfileCreateParams, type BrowserProfileUpdateParams as BrowserProfileUpdateParams, type BrowserProfileListParams as BrowserProfileListParams, @@ -809,7 +817,6 @@ export declare namespace BrowserUse { AgentProfiles as AgentProfiles, type AgentProfileView as AgentProfileView, type AgentProfileListResponse as AgentProfileListResponse, - type AgentProfileDeleteResponse as AgentProfileDeleteResponse, type AgentProfileCreateParams as AgentProfileCreateParams, type AgentProfileUpdateParams as AgentProfileUpdateParams, type AgentProfileListParams as AgentProfileListParams, diff --git a/src/lib/parse.ts b/src/lib/parse.ts index c872e6e..8c651b8 100644 --- a/src/lib/parse.ts +++ b/src/lib/parse.ts @@ -1,46 +1,34 @@ import z, { type ZodType } from 'zod'; -import type { TaskCreateParams, TaskRetrieveParams, TaskView } from '../resources/tasks'; +import type { TaskCreateParams, TaskView } from '../resources/tasks'; // RUN -export type RunTaskCreateParamsWithStructuredOutput = Omit< - TaskCreateParams, - 'structuredOutputJson' -> & { +export type TaskCreateParamsWithSchema = Omit & { structuredOutputJson: T; }; -export function stringifyStructuredOutput( - req: RunTaskCreateParamsWithStructuredOutput, -): TaskCreateParams { - return { - ...req, - structuredOutputJson: JSON.stringify(z.toJSONSchema(req.structuredOutputJson)), - }; +export function stringifyStructuredOutput(schema: T): string { + return JSON.stringify(z.toJSONSchema(schema)); } // RETRIEVE -export type GetTaskStatusParamsWithStructuredOutput = Omit< - TaskRetrieveParams, - 'statusOnly' -> & { - statusOnly?: false; - structuredOutputJson: T; -}; - -export type TaskViewWithStructuredOutput = Omit & { +export type TaskViewWithSchema = Omit & { doneOutput: z.output | null; }; export function parseStructuredTaskOutput( res: TaskView, - body: GetTaskStatusParamsWithStructuredOutput, -): TaskViewWithStructuredOutput { + schema: T, +): TaskViewWithSchema { + if (res.doneOutput == null) { + return { ...res, doneOutput: null }; + } + try { const parsed = JSON.parse(res.doneOutput); - const response = body.structuredOutputJson.safeParse(parsed); + const response = schema.safeParse(parsed); if (!response.success) { throw new Error(`Invalid structured output: ${response.error.message}`); } diff --git a/src/lib/stream.ts b/src/lib/stream.ts new file mode 100644 index 0000000..7dd6359 --- /dev/null +++ b/src/lib/stream.ts @@ -0,0 +1,70 @@ +import type { TaskView, TaskStepView } from '../resources/tasks'; +import { ExhaustiveSwitchCheck } from './types'; + +export type ReducerEvent = TaskView | null; + +export type BrowserState = Readonly<{ + taskId: string; + sessionId: string; + + liveUrl: string | null; + + steps: ReadonlyArray; +}> | null; + +type BrowserAction = { + kind: 'status'; + status: TaskView; +}; + +export function reducer(state: BrowserState, action: BrowserAction): [BrowserState, ReducerEvent] { + switch (action.kind) { + case 'status': { + // INIT + + if (state == null) { + const liveUrl = action.status.sessionLiveUrl ?? null; + + const state: BrowserState = { + taskId: action.status.id, + sessionId: action.status.sessionId, + liveUrl: liveUrl, + steps: action.status.steps, + }; + + return [state, action.status]; + } + + // UPDATE + + const liveUrl = action.status.sessionLiveUrl ?? null; + const steps: TaskStepView[] = [...state.steps]; + + if (action.status.steps != null) { + const newSteps = action.status.steps.slice(state.steps.length); + + for (const step of newSteps) { + steps.push(step); + } + } + + const newState: BrowserState = { ...state, liveUrl, steps }; + + // CHANGES + + if ((state.liveUrl == null && liveUrl != null) || state.steps.length !== steps.length) { + const update: ReducerEvent = { + ...action.status, + steps: steps, + sessionLiveUrl: liveUrl, + }; + + return [newState, update]; + } + + return [newState, null]; + } + default: + throw new ExhaustiveSwitchCheck(action.kind); + } +} diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..a1b9bda --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,73 @@ +/** + * Distributive Pick - does not collapse unions into a "shared type" only to + * run Pick on it. Instead, it "picks" from each union item separately. + * + * See https://github.com/klimashkin/css-modules-theme/pull/8 + * + * Example: + * Pick<{ type: "pick" } | { type: "omit" }, "type"> + * produces { type: "pick" | "omit" } + * + * UnionPick<{ type: "pick" } | { type: "omit" }, "type"> + * produces { type: "pick" } | { type: "omit" } + */ +export type UnionPick = T extends unknown ? Pick : never; + +/** + * Like UnionPick, but for Omit + */ +export type UnionOmit = T extends unknown ? Omit : never; + +/** + * Utility type for properties that may be undefined until loaded. + */ +export type Loadable = ({ loading: true } & { [K in keyof T]?: never }) | ({ loading: false } & T); + +/** + * Utility type that removes null fields from a type. + */ +export type DeepRequired = { + [P in keyof T]: Exclude; +}; + +/** + * Makes a type check that is only valid when all cases of a switch + * statement have been convered. + */ +export class ExhaustiveSwitchCheck extends Error { + constructor(val: never) { + super(`Unreachable case: ${JSON.stringify(val)}`); + } +} + +/** + * A utiliy type that lets you extract a union member by its `kind` property. + * + * @example + * + * type Shape = + * | { kind: 'circle'; radius: number } + * | { kind: 'square'; sideLength: number } + * | { kind: 'rectangle'; width: number; height: number }; + * + * type Circle = ExtractKind; // { kind: 'circle'; radius: number } + */ +export type ExtractKind = T extends { kind: K } ? T : never; + +/** + * A utiliy type that lets you extract a union member by its `ok` property. + * + * @example + * + * type Result = { ok: true; value: string } | { ok: false; error: string }; + * + * type Ok = ExtractResult; // { ok: true; value: string } + */ +export type ExtractResult = T extends { ok: K } ? T : never; + +/** + * Creates a deep readonly object mutable. + */ +export type DeepMutable = { + -readonly [P in keyof T]: T[P] extends object ? DeepMutable : T[P]; +}; diff --git a/src/resources/agent-profiles.ts b/src/resources/agent-profiles.ts index 5639db6..be769d8 100644 --- a/src/resources/agent-profiles.ts +++ b/src/resources/agent-profiles.ts @@ -2,26 +2,86 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; +import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; export class AgentProfiles extends APIResource { /** - * Create Agent Profile + * Create a new agent profile for the authenticated user. + * + * Agent profiles define how your AI agents behave during tasks. You can create + * multiple profiles for different use cases (e.g., customer support, data + * analysis, web scraping). Free users can create 1 profile; paid users can create + * unlimited profiles. + * + * Key features you can configure: + * + * - System prompt: The core instructions that define the agent's personality and + * behavior + * - Allowed domains: Restrict which websites the agent can access + * - Max steps: Limit how many actions the agent can take in a single task + * - Vision: Enable/disable the agent's ability to see and analyze screenshots + * - Thinking: Enable/disable the agent's reasoning process + * + * Args: + * + * - request: The agent profile configuration including name, description, and + * behavior settings + * + * Returns: + * + * - The newly created agent profile with all its details + * + * Raises: + * + * - 402: If user needs a subscription to create additional profiles */ create(body: AgentProfileCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/agent-profiles', { body, ...options }); } /** - * Get Agent Profile + * Get a specific agent profile by its ID. + * + * Retrieves the complete details of an agent profile, including all its + * configuration settings like system prompts, allowed domains, and behavior flags. + * + * Args: + * + * - profile_id: The unique identifier of the agent profile + * + * Returns: + * + * - Complete agent profile information + * + * Raises: + * + * - 404: If the user agent profile doesn't exist */ retrieve(profileID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/agent-profiles/${profileID}`, options); } /** - * Update Agent Profile + * Update an existing agent profile. + * + * Modify any aspect of an agent profile, such as its name, description, system + * prompt, or behavior settings. Only the fields you provide will be updated; other + * fields remain unchanged. + * + * Args: + * + * - profile_id: The unique identifier of the agent profile to update + * - request: The fields to update (only provided fields will be changed) + * + * Returns: + * + * - The updated agent profile with all its current details + * + * Raises: + * + * - 404: If the user agent profile doesn't exist */ update( profileID: string, @@ -32,7 +92,17 @@ export class AgentProfiles extends APIResource { } /** - * List Agent Profiles + * Get a paginated list of all agent profiles for the authenticated user. + * + * Agent profiles define how your AI agents behave, including their personality, + * capabilities, and limitations. Use this endpoint to see all your configured + * agent profiles. + * + * Returns: + * + * - A paginated list of agent profiles + * - Total count of profiles + * - Page information for navigation */ list( query: AgentProfileListParams | null | undefined = {}, @@ -42,10 +112,25 @@ export class AgentProfiles extends APIResource { } /** - * Delete Agent Profile + * Delete an agent profile. + * + * Permanently removes an agent profile and all its configuration. This action + * cannot be undone. Any tasks that were using this profile will continue to work, + * but you won't be able to create new tasks with the deleted profile. + * + * Args: + * + * - profile_id: The unique identifier of the agent profile to delete + * + * Returns: + * + * - 204 No Content on successful deletion (idempotent) */ - delete(profileID: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/agent-profiles/${profileID}`, options); + delete(profileID: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/agent-profiles/${profileID}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); } } @@ -58,9 +143,9 @@ export class AgentProfiles extends APIResource { * max_agent_steps: Maximum number of steps the agent can take before stopping * allowed_domains: List of domains the agent is allowed to access flash_mode: * Whether flash mode is enabled thinking: Whether thinking mode is enabled vision: - * Whether vision capabilities are enabled system_prompt: Custom system prompt for - * the agent (optionally set by the user) created_at: Timestamp when the profile - * was created updated_at: Timestamp when the profile was last updated + * Whether vision capabilities are enabled custom_system_prompt_extension: Optional + * custom system prompt for the agent created_at: Timestamp when the profile was + * created updated_at: Timestamp when the profile was last updated */ export interface AgentProfileView { id: string; @@ -69,6 +154,8 @@ export interface AgentProfileView { createdAt: string; + customSystemPromptExtension: string; + description: string; flashMode: boolean; @@ -79,8 +166,6 @@ export interface AgentProfileView { name: string; - systemPrompt: string; - thinking: boolean; updatedAt: string; @@ -103,13 +188,13 @@ export interface AgentProfileListResponse { totalItems: number; } -export type AgentProfileDeleteResponse = unknown; - export interface AgentProfileCreateParams { name: string; allowedDomains?: Array; + customSystemPromptExtension?: string; + description?: string; flashMode?: boolean; @@ -118,8 +203,6 @@ export interface AgentProfileCreateParams { maxAgentSteps?: number; - systemPrompt?: string; - thinking?: boolean; vision?: boolean; @@ -128,6 +211,8 @@ export interface AgentProfileCreateParams { export interface AgentProfileUpdateParams { allowedDomains?: Array | null; + customSystemPromptExtension?: string | null; + description?: string | null; flashMode?: boolean | null; @@ -138,8 +223,6 @@ export interface AgentProfileUpdateParams { name?: string | null; - systemPrompt?: string | null; - thinking?: boolean | null; vision?: boolean | null; @@ -155,7 +238,6 @@ export declare namespace AgentProfiles { export { type AgentProfileView as AgentProfileView, type AgentProfileListResponse as AgentProfileListResponse, - type AgentProfileDeleteResponse as AgentProfileDeleteResponse, type AgentProfileCreateParams as AgentProfileCreateParams, type AgentProfileUpdateParams as AgentProfileUpdateParams, type AgentProfileListParams as AgentProfileListParams, diff --git a/src/resources/browser-profiles.ts b/src/resources/browser-profiles.ts index 503fe3d..d68f169 100644 --- a/src/resources/browser-profiles.ts +++ b/src/resources/browser-profiles.ts @@ -2,26 +2,86 @@ import { APIResource } from '../core/resource'; import { APIPromise } from '../core/api-promise'; +import { buildHeaders } from '../internal/headers'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; export class BrowserProfiles extends APIResource { /** - * Create Browser Profile + * Create a new browser profile for the authenticated user. + * + * Browser profiles define how your web browsers behave during AI agent tasks. You + * can create multiple profiles for different use cases (e.g., mobile testing, + * desktop browsing, proxy-enabled scraping). Free users can create up to 10 + * profiles; paid users can create unlimited profiles. + * + * Key features you can configure: + * + * - Viewport dimensions: Set the browser window size for consistent rendering + * - Mobile emulation: Enable mobile device simulation + * - Proxy settings: Route traffic through specific locations or proxy servers + * - Ad blocking: Enable/disable ad blocking for cleaner browsing + * - Cache persistence: Choose whether to save browser data between sessions + * + * Args: + * + * - request: The browser profile configuration including name, description, and + * browser settings + * + * Returns: + * + * - The newly created browser profile with all its details + * + * Raises: + * + * - 402: If user needs a subscription to create additional profiles */ create(body: BrowserProfileCreateParams, options?: RequestOptions): APIPromise { return this._client.post('/browser-profiles', { body, ...options }); } /** - * Get Browser Profile + * Get a specific browser profile by its ID. + * + * Retrieves the complete details of a browser profile, including all its + * configuration settings like viewport dimensions, proxy settings, and behavior + * flags. + * + * Args: + * + * - profile_id: The unique identifier of the browser profile + * + * Returns: + * + * - Complete browser profile information + * + * Raises: + * + * - 404: If the user browser profile doesn't exist */ retrieve(profileID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/browser-profiles/${profileID}`, options); } /** - * Update Browser Profile + * Update an existing browser profile. + * + * Modify any aspect of a browser profile, such as its name, description, viewport + * settings, or proxy configuration. Only the fields you provide will be updated; + * other fields remain unchanged. + * + * Args: + * + * - profile_id: The unique identifier of the browser profile to update + * - request: The fields to update (only provided fields will be changed) + * + * Returns: + * + * - The updated browser profile with all its current details + * + * Raises: + * + * - 404: If the user browser profile doesn't exist */ update( profileID: string, @@ -32,7 +92,17 @@ export class BrowserProfiles extends APIResource { } /** - * List Browser Profiles + * Get a paginated list of all browser profiles for the authenticated user. + * + * Browser profiles define how your web browsers behave during AI agent tasks, + * including settings like viewport size, mobile emulation, proxy configuration, + * and ad blocking. Use this endpoint to see all your configured browser profiles. + * + * Returns: + * + * - A paginated list of browser profiles + * - Total count of profiles + * - Page information for navigation */ list( query: BrowserProfileListParams | null | undefined = {}, @@ -42,10 +112,26 @@ export class BrowserProfiles extends APIResource { } /** - * Delete Browser Profile + * Delete a browser profile. + * + * Permanently removes a browser profile and all its configuration. This action + * cannot be undone. The profile will also be removed from the browser service. Any + * active sessions using this profile will continue to work, but you won't be able + * to create new sessions with the deleted profile. + * + * Args: + * + * - profile_id: The unique identifier of the browser profile to delete + * + * Returns: + * + * - 204 No Content on successful deletion (idempotent) */ - delete(profileID: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/browser-profiles/${profileID}`, options); + delete(profileID: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/browser-profiles/${profileID}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); } } @@ -59,8 +145,8 @@ export class BrowserProfiles extends APIResource { * proxy location store_cache: Whether to store browser cache * browser_viewport_width: Browser viewport width in pixels * browser_viewport_height: Browser viewport height in pixels is_mobile: Whether - * the browser is mobile view created_at: Timestamp when the profile was created - * updated_at: Timestamp when the profile was last updated + * the browser should be in mobile view created_at: Timestamp when the profile was + * created updated_at: Timestamp when the profile was last updated */ export interface BrowserProfileView { id: string; @@ -107,8 +193,6 @@ export interface BrowserProfileListResponse { totalItems: number; } -export type BrowserProfileDeleteResponse = unknown; - export interface BrowserProfileCreateParams { name: string; @@ -164,7 +248,6 @@ export declare namespace BrowserProfiles { type BrowserProfileView as BrowserProfileView, type ProxyCountryCode as ProxyCountryCode, type BrowserProfileListResponse as BrowserProfileListResponse, - type BrowserProfileDeleteResponse as BrowserProfileDeleteResponse, type BrowserProfileCreateParams as BrowserProfileCreateParams, type BrowserProfileUpdateParams as BrowserProfileUpdateParams, type BrowserProfileListParams as BrowserProfileListParams, diff --git a/src/resources/index.ts b/src/resources/index.ts index bdeb4dc..d71e576 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -4,7 +4,6 @@ export { AgentProfiles, type AgentProfileView, type AgentProfileListResponse, - type AgentProfileDeleteResponse, type AgentProfileCreateParams, type AgentProfileUpdateParams, type AgentProfileListParams, @@ -14,7 +13,6 @@ export { type BrowserProfileView, type ProxyCountryCode, type BrowserProfileListResponse, - type BrowserProfileDeleteResponse, type BrowserProfileCreateParams, type BrowserProfileUpdateParams, type BrowserProfileListParams, @@ -30,16 +28,20 @@ export { } from './sessions/sessions'; export { Tasks, + type FileView, type LlmModel, + type TaskItemView, type TaskStatus, + type TaskStepView, type TaskView, - type TaskRetrieveResponse, type TaskListResponse, - type TaskRetrieveLogsResponse, - type TaskRetrieveOutputFileResponse, + type TaskGetLogsResponse, + type TaskGetOutputFileResponse, + type TaskGetUserUploadedFileResponse, type TaskCreateParams, - type TaskRetrieveParams, type TaskUpdateParams, type TaskListParams, - type TaskRetrieveOutputFileParams, + type TaskGetOutputFileParams, + type TaskGetUserUploadedFileParams, } from './tasks'; +export { Users } from './users/users'; diff --git a/src/resources/sessions/index.ts b/src/resources/sessions/index.ts index 2b7f883..2b7a211 100644 --- a/src/resources/sessions/index.ts +++ b/src/resources/sessions/index.ts @@ -1,6 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { PublicShare, type ShareView, type PublicShareDeleteResponse } from './public-share'; +export { PublicShare, type ShareView } from './public-share'; export { Sessions, type SessionStatus, diff --git a/src/resources/sessions/public-share.ts b/src/resources/sessions/public-share.ts index 4d45843..9de5001 100644 --- a/src/resources/sessions/public-share.ts +++ b/src/resources/sessions/public-share.ts @@ -2,29 +2,87 @@ import { APIResource } from '../../core/resource'; import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; export class PublicShare extends APIResource { /** - * Create Session Public Share + * Create a public share for a session. + * + * Generates a public sharing link that allows anyone with the URL to view the + * session and its tasks. If a public share already exists for the session, it will + * return the existing share instead of creating a new one. + * + * Public shares are useful for: + * + * - Sharing results with clients or team members + * - Demonstrating AI agent capabilities + * - Collaborative review of automated tasks + * + * Args: + * + * - session_id: The unique identifier of the agent session to share + * + * Returns: + * + * - Public share information including the share URL and usage statistics + * + * Raises: + * + * - 404: If the user agent session doesn't exist */ create(sessionID: string, options?: RequestOptions): APIPromise { return this._client.post(path`/sessions/${sessionID}/public-share`, options); } /** - * Get Session Public Share + * Get information about the public share for a session. + * + * Retrieves details about the public sharing link for a session, including the + * share token, public URL, view count, and last viewed timestamp. This is useful + * for monitoring how your shared sessions are being accessed. + * + * Args: + * + * - session_id: The unique identifier of the agent session + * + * Returns: + * + * - Public share information including the share URL and usage statistics + * + * Raises: + * + * - 404: If the user agent session doesn't exist or doesn't have a public share */ retrieve(sessionID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/sessions/${sessionID}/public-share`, options); } /** - * Delete Session Public Share + * Remove the public share for a session. + * + * Deletes the public sharing link for a session, making it no longer accessible to + * anyone with the previous share URL. This is useful for removing access to + * sensitive sessions or when you no longer want to share the results. + * + * Args: + * + * - session_id: The unique identifier of the agent session + * + * Returns: + * + * - 204 No Content on successful deletion (idempotent) + * + * Raises: + * + * - 404: If the user agent session doesn't exist */ - delete(sessionID: string, options?: RequestOptions): APIPromise { - return this._client.delete(path`/sessions/${sessionID}/public-share`, options); + delete(sessionID: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/sessions/${sessionID}/public-share`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); } } @@ -46,8 +104,6 @@ export interface ShareView { lastViewedAt?: string | null; } -export type PublicShareDeleteResponse = unknown; - export declare namespace PublicShare { - export { type ShareView as ShareView, type PublicShareDeleteResponse as PublicShareDeleteResponse }; + export { type ShareView as ShareView }; } diff --git a/src/resources/sessions/sessions.ts b/src/resources/sessions/sessions.ts index a5e2b1d..db6ca55 100644 --- a/src/resources/sessions/sessions.ts +++ b/src/resources/sessions/sessions.ts @@ -1,10 +1,12 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; +import * as SessionsAPI from './sessions'; import * as TasksAPI from '../tasks'; import * as PublicShareAPI from './public-share'; -import { PublicShare, PublicShareDeleteResponse, ShareView } from './public-share'; +import { PublicShare, ShareView } from './public-share'; import { APIPromise } from '../../core/api-promise'; +import { buildHeaders } from '../../internal/headers'; import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; @@ -12,7 +14,25 @@ export class Sessions extends APIResource { publicShare: PublicShareAPI.PublicShare = new PublicShareAPI.PublicShare(this._client); /** - * Get Session + * Get detailed information about a specific AI agent session. + * + * Retrieves comprehensive information about a session, including its current + * status, live browser URL (if active), recording URL (if completed), and optional + * task details. This endpoint is useful for monitoring active sessions or + * reviewing completed ones. + * + * Args: + * + * - session_id: The unique identifier of the agent session + * - params: Optional parameters to control what data is included + * + * Returns: + * + * - Complete session information including status, URLs, and optional task details + * + * Raises: + * + * - 404: If the user agent session doesn't exist */ retrieve( sessionID: string, @@ -23,14 +43,51 @@ export class Sessions extends APIResource { } /** - * Update Session + * Update a session's status or perform actions on it. + * + * Currently supports stopping a session, which will: + * + * 1. Stop any running tasks in the session + * 2. End the browser session + * 3. Generate a recording URL if available + * 4. Update the session status to 'stopped' + * + * This is useful for manually stopping long-running sessions or when you want to + * end a session before all tasks are complete. + * + * Args: + * + * - session_id: The unique identifier of the agent session to update + * - request: The action to perform on the session + * + * Returns: + * + * - The updated session information including the new status and recording URL + * + * Raises: + * + * - 404: If the user agent session doesn't exist */ update(sessionID: string, body: SessionUpdateParams, options?: RequestOptions): APIPromise { return this._client.patch(path`/sessions/${sessionID}`, { body, ...options }); } /** - * List Sessions + * Get a paginated list of all AI agent sessions for the authenticated user. + * + * AI agent sessions represent active or completed browsing sessions where your AI + * agents perform tasks. Each session can contain multiple tasks and maintains + * browser state throughout the session lifecycle. + * + * You can filter sessions by status and optionally include task details for each + * session. + * + * Returns: + * + * - A paginated list of agent sessions + * - Total count of sessions + * - Page information for navigation + * - Optional task details for each session (if requested) */ list( query: SessionListParams | null | undefined = {}, @@ -38,14 +95,35 @@ export class Sessions extends APIResource { ): APIPromise { return this._client.get('/sessions', { query, ...options }); } + + /** + * Delete a session and all its associated data. + * + * Permanently removes a session and all its tasks, browser data, and public + * shares. This action cannot be undone. Use this endpoint to clean up old sessions + * and free up storage space. + * + * Args: + * + * - session_id: The unique identifier of the agent session to delete + * + * Returns: + * + * - 204 No Content on successful deletion (idempotent) + */ + delete(sessionID: string, options?: RequestOptions): APIPromise { + return this._client.delete(path`/sessions/${sessionID}`, { + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + }); + } } /** * Enumeration of possible (browser) session states * - * Attributes: ACTIVE: Session is currently active and running (aka browser is - * running) STOPPED: Session has been stopped and is no longer active (aka browser - * is stopped) + * Attributes: ACTIVE: Session is currently active and running (browser is running) + * STOPPED: Session has been stopped and is no longer active (browser is stopped) */ export type SessionStatus = 'active' | 'stopped'; @@ -54,11 +132,11 @@ export type SessionStatus = 'active' | 'stopped'; * * Attributes: id: Unique identifier for the session. status: Current status of the * session (active/stopped). live_url: URL where the browser can be viewed live in - * real-time. record_url: URL to access the recorded session playback. started_at: - * Timestamp when the session was created and started. finished_at: Timestamp when - * the session was stopped (None if still active). tasks: List of tasks associated - * with this session (optional). public_share_url: URL to access the public share - * of the session (optional). + * real-time. started_at: Timestamp when the session was created and started. + * finished_at: Timestamp when the session was stopped (None if still active). + * tasks: Optional list of tasks associated with this session. record_url: URL to + * access the recorded session playback. public_share_url: Optional URL to access + * the public share of the session. */ export interface SessionView { id: string; @@ -68,9 +146,8 @@ export interface SessionView { /** * Enumeration of possible (browser) session states * - * Attributes: ACTIVE: Session is currently active and running (aka browser is - * running) STOPPED: Session has been stopped and is no longer active (aka browser - * is stopped) + * Attributes: ACTIVE: Session is currently active and running (browser is running) + * STOPPED: Session has been stopped and is no longer active (browser is stopped) */ status: SessionStatus; @@ -82,7 +159,7 @@ export interface SessionView { recordUrl?: string | null; - tasks?: Array | null; + tasks?: Array | null; } /** @@ -91,7 +168,7 @@ export interface SessionView { * Attributes: items: List of session views for the current page */ export interface SessionListResponse { - items: Array; + items: Array; pageNumber: number; @@ -100,6 +177,37 @@ export interface SessionListResponse { totalItems: number; } +export namespace SessionListResponse { + /** + * View model for representing a (browser) session with its associated tasks. + * + * Attributes: id: Unique identifier for the session. status: Current status of the + * session (active/stopped). live_url: URL where the browser can be viewed live in + * real-time. started_at: Timestamp when the session was created and started. + * finished_at: Timestamp when the session was stopped (None if still active). + * tasks: Optional list of tasks associated with this session. + */ + export interface Item { + id: string; + + startedAt: string; + + /** + * Enumeration of possible (browser) session states + * + * Attributes: ACTIVE: Session is currently active and running (browser is running) + * STOPPED: Session has been stopped and is no longer active (browser is stopped) + */ + status: SessionsAPI.SessionStatus; + + finishedAt?: string | null; + + liveUrl?: string | null; + + tasks?: Array | null; + } +} + export interface SessionRetrieveParams { includeTasks?: boolean; } @@ -108,7 +216,8 @@ export interface SessionUpdateParams { /** * Available actions that can be performed on a session * - * Attributes: STOP: Stop the session and all its associated tasks + * Attributes: STOP: Stop the session and all its associated tasks (cannot be + * undone) */ action: 'stop'; } @@ -117,9 +226,8 @@ export interface SessionListParams { /** * Enumeration of possible (browser) session states * - * Attributes: ACTIVE: Session is currently active and running (aka browser is - * running) STOPPED: Session has been stopped and is no longer active (aka browser - * is stopped) + * Attributes: ACTIVE: Session is currently active and running (browser is running) + * STOPPED: Session has been stopped and is no longer active (browser is stopped) */ filterBy?: SessionStatus | null; @@ -142,9 +250,5 @@ export declare namespace Sessions { type SessionListParams as SessionListParams, }; - export { - PublicShare as PublicShare, - type ShareView as ShareView, - type PublicShareDeleteResponse as PublicShareDeleteResponse, - }; + export { PublicShare as PublicShare, type ShareView as ShareView }; } diff --git a/src/resources/tasks.ts b/src/resources/tasks.ts index 18ca698..02d7c36 100644 --- a/src/resources/tasks.ts +++ b/src/resources/tasks.ts @@ -2,70 +2,266 @@ import type { ZodType } from 'zod'; -import { APIResource } from '../core/resource'; -import * as TasksAPI from './tasks'; import { APIPromise } from '../core/api-promise'; +import { APIResource } from '../core/resource'; import { RequestOptions } from '../internal/request-options'; import { path } from '../internal/utils/path'; import { parseStructuredTaskOutput, stringifyStructuredOutput, - type TaskViewWithStructuredOutput, - type GetTaskStatusParamsWithStructuredOutput, - type RunTaskCreateParamsWithStructuredOutput, + type TaskCreateParamsWithSchema, + type TaskViewWithSchema, } from '../lib/parse'; +import { BrowserState, reducer } from '../lib/stream'; +import * as TasksAPI from './tasks'; export class Tasks extends APIResource { /** - * Create Task + * Create and start a new AI agent task. + * + * This is the main endpoint for running AI agents. You can either: + * + * 1. Start a new session with a new task + * 2. Add a follow-up task to an existing session + * + * When starting a new session: + * + * - A new browser session is created + * - Credits are deducted from your account + * - The agent begins executing your task immediately + * + * When adding to an existing session: + * + * - The agent continues in the same browser context + * - No additional browser start up costs are charged (browser session is already + * active) + * - The agent can build on previous work + * + * Key features: + * + * - Agent profiles: Define agent behavior and capabilities + * - Browser profiles: Control browser settings and environment (only used for new + * sessions) + * - File uploads: Include documents for the agent to work with + * - Structured output: Define the format you want results in + * - Task metadata: Add custom data for tracking and organization (useful when + * using webhooks) + * + * Args: + * + * - request: Complete task configuration including agent settings, browser + * settings, and task description + * + * Returns: + * + * - The created task with its initial details + * + * Raises: + * + * - 402: If user has insufficient credits for a new session + * - 404: If referenced agent/browser profiles don't exist + * - 400: If session is stopped or already has a running task */ - create(body: TaskCreateParams, options?: RequestOptions): APIPromise { + create( + body: TaskCreateParamsWithSchema, + options?: RequestOptions, + ): APIPromise>; + create(body: TaskCreateParams, options?: RequestOptions): APIPromise; + create( + body: TaskCreateParams | TaskCreateParamsWithSchema, + options?: RequestOptions, + ): APIPromise { + if (body.structuredOutputJson == null || typeof body.structuredOutputJson === 'string') { + return this._client.post('/tasks', { body, ...options }); + } + + if (typeof body.structuredOutputJson === 'object') { + const schema = body.structuredOutputJson; + + const _body: TaskCreateParams = { + ...body, + structuredOutputJson: stringifyStructuredOutput(schema), + }; + + return this._client + .post('/tasks', { body: _body, ...options }) + ._thenUnwrap((rsp) => parseStructuredTaskOutput(rsp as TaskView, schema)); + } + return this._client.post('/tasks', { body, ...options }); } - createWithStructuredOutput( - body: RunTaskCreateParamsWithStructuredOutput, + private async *watch( + data: TaskCreateParams, + config: { interval: number }, options?: RequestOptions, - ): APIPromise> { - return this.create(stringifyStructuredOutput(body), options)._thenUnwrap((rsp) => - parseStructuredTaskOutput(rsp as TaskView, body), - ); + ): AsyncGenerator<{ event: 'status'; data: TaskView }> { + const tick: { current: number } = { current: 0 }; + const state: { current: BrowserState } = { current: null }; + + poll: do { + if (options?.signal?.aborted) { + break poll; + } + + tick.current++; + + let status: TaskView; + + // NOTE: We take action on each tick. + if (state.current == null) { + status = await this.create(data, options); + } else { + status = await this.retrieve(state.current.taskId); + } + + const [newState, event] = reducer(state.current, { kind: 'status', status }); + + if (event != null) { + yield { event: 'status', data: event }; + + if (event.status === 'finished') { + break; + } + } + + state.current = newState; + + await new Promise((resolve) => setTimeout(resolve, config.interval)); + } while (true); } - /** - * Get Task - */ - retrieve( - taskID: string, - query: TaskRetrieveParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get(path`/tasks/${taskID}`, { query, ...options }); + stream(body: TaskCreateParams, options?: RequestOptions) { + const self = this; + + const enc = new TextEncoder(); + + const stream = new ReadableStream({ + async start(controller) { + // open the SSE stream quickly + controller.enqueue(enc.encode(': connected\n\n')); + + try { + for await (const msg of self.watch(body, { interval: 500 }, options)) { + if (options?.signal?.aborted) { + break; + } + + const data = JSON.stringify(msg.data); + + const payload = `event: ${msg.event}\ndata: ${data}\n\n`; + controller.enqueue(enc.encode(payload)); + } + + controller.enqueue(enc.encode('event: end\ndata: {}\n\n')); + } catch (e) { + controller.enqueue(enc.encode(`event: error\ndata: ${JSON.stringify({ message: String(e) })}\n\n`)); + } finally { + controller.close(); + } + }, + }); + + return stream; } - retrieveWithStructuredOutput( - taskID: string, - query: GetTaskStatusParamsWithStructuredOutput, + /** + * Get detailed information about a specific AI agent task. + * + * Retrieves comprehensive information about a task, including its current status, + * progress, and detailed execution data. You can choose to get just the status + * (for quick polling) or full details including steps and file information. + * + * Use this endpoint to: + * + * - Monitor task progress in real-time + * - Review completed task results + * - Debug failed tasks by examining steps + * - Download output files and logs + * + * Args: + * + * - task_id: The unique identifier of the agent task + * + * Returns: + * + * - Complete task information + * + * Raises: + * + * - 404: If the user agent task doesn't exist + */ + retrieve( + req: { taskId: string; schema: T }, options?: RequestOptions, - ): APIPromise> { - // NOTE: We manually remove structuredOutputJson from the query object because - // it's not a valid Browser Use Cloud parameter. - const { structuredOutputJson, ...rest } = query; - - return this.retrieve(taskID, rest, options)._thenUnwrap((rsp) => - parseStructuredTaskOutput(rsp as TaskView, query), - ); + ): APIPromise>; + retrieve(taskID: string, options?: RequestOptions): APIPromise; + retrieve(req: string | { taskId: string; schema: ZodType }, options?: RequestOptions): APIPromise { + if (typeof req === 'string') { + return this._client.get(path`/tasks/${req}`, options); + } + + const { taskId, schema } = req; + + return this._client + .get(path`/tasks/${taskId}`, options) + ._thenUnwrap((rsp) => parseStructuredTaskOutput(rsp as TaskView, schema)); } /** - * Update Task + * Control the execution of an AI agent task. + * + * Allows you to pause, resume, or stop tasks, and optionally stop the entire + * session. This is useful for: + * + * - Pausing long-running tasks to review progress + * - Stopping tasks that are taking too long + * - Ending sessions when you're done with all tasks + * + * Available actions: + * + * - STOP: Stop the current task + * - PAUSE: Pause the task (can be resumed later) + * - RESUME: Resume a paused task + * - STOP_TASK_AND_SESSION: Stop the task and end the entire session + * + * Args: + * + * - task_id: The unique identifier of the agent task to control + * - request: The action to perform on the task + * + * Returns: + * + * - The updated task information + * + * Raises: + * + * - 404: If the user agent task doesn't exist */ update(taskID: string, body: TaskUpdateParams, options?: RequestOptions): APIPromise { return this._client.patch(path`/tasks/${taskID}`, { body, ...options }); } /** - * List Tasks + * Get a paginated list of all AI agent tasks for the authenticated user. + * + * AI agent tasks are the individual jobs that your agents perform within a + * session. Each task represents a specific instruction or goal that the agent + * works on, such as filling out a form, extracting data, or navigating to specific + * pages. + * + * You can control what data is included for each task: + * + * - Task steps: Detailed actions the agent took + * - User uploaded files: Files you provided for the task + * - Output files: Files generated by the agent during the task + * + * Returns: + * + * - A paginated list of agent tasks + * - Total count of tasks + * - Page information for navigation + * - Optional detailed data based on your parameters */ list( query: TaskListParams | null | undefined = {}, @@ -75,25 +271,122 @@ export class Tasks extends APIResource { } /** - * Get Task Logs + * Get a download URL for the execution logs of an AI agent task. + * + * Task logs contain detailed information about how the AI agent executed the task, + * including: + * + * - Step-by-step reasoning and decisions + * - Actions taken on web pages + * - Error messages and debugging information + * - Performance metrics and timing data + * + * This is useful for: + * + * - Understanding how the agent solved the task + * - Debugging failed or unexpected results + * - Optimizing agent behavior and prompts + * - Auditing agent actions for compliance + * + * Args: + * + * - task_id: The unique identifier of the agent task + * + * Returns: + * + * - A presigned download URL for the task log file + * + * Raises: + * + * - 404: If the user agent task doesn't exist + * - 500: If the download URL cannot be generated (should not happen) */ - retrieveLogs(taskID: string, options?: RequestOptions): APIPromise { + getLogs(taskID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/tasks/${taskID}/logs`, options); } /** - * Get Task Output File + * Get a download URL for a specific output file generated by an AI agent task. + * + * AI agents can generate various output files during task execution, such as: + * + * - Screenshots of web pages + * - Extracted data in CSV/JSON format + * - Generated reports or documents + * - Downloaded files from websites + * + * This endpoint provides a secure, time-limited download URL for accessing these + * files. The URL expires after a short time for security. + * + * Args: + * + * - task_id: The unique identifier of the agent task + * - file_id: The unique identifier of the output file + * + * Returns: + * + * - A presigned download URL for the requested file + * + * Raises: + * + * - 404: If the user agent task or output file doesn't exist + * - 500: If the download URL cannot be generated (should not happen) */ - retrieveOutputFile( - fileName: string, - params: TaskRetrieveOutputFileParams, + getOutputFile( + fileID: string, + params: TaskGetOutputFileParams, options?: RequestOptions, - ): APIPromise { + ): APIPromise { const { task_id } = params; - return this._client.get(path`/tasks/${task_id}/output-files/${fileName}`, options); + return this._client.get(path`/tasks/${task_id}/output-files/${fileID}`, options); + } + + /** + * Get a download URL for a specific user uploaded file that was used in the task. + * + * A user can upload files to their account file bucket and reference the name of + * the file in a task. These files are then made available for the agent to use + * during the agent task run. + * + * This endpoint provides a secure, time-limited download URL for accessing these + * files. The URL expires after a short time for security. + * + * Args: + * + * - task_id: The unique identifier of the agent task + * - file_id: The unique identifier of the user uploaded file + * + * Returns: + * + * - A presigned download URL for the requested file + * + * Raises: + * + * - 404: If the user agent task or user uploaded file doesn't exist + * - 500: If the download URL cannot be generated (should not happen) + */ + getUserUploadedFile( + fileID: string, + params: TaskGetUserUploadedFileParams, + options?: RequestOptions, + ): APIPromise { + const { task_id } = params; + return this._client.get(path`/tasks/${task_id}/user-uploaded-files/${fileID}`, options); } } +/** + * View model for representing an output file generated by the agent + * + * Attributes: id: Unique identifier for the output file file_name: Name of the + * output file + */ +export interface FileView { + id: string; + + fileName: string; +} + export type LlmModel = | 'gpt-4o' | 'gpt-4o-mini' @@ -110,37 +403,26 @@ export type LlmModel = | 'claude-sonnet-4-20250514' | 'llama-4-maverick-17b-128e-instruct'; -/** - * Enumeration of possible task execution states - * - * Attributes: STARTED: Task has been initiated and is currently running PAUSED: - * Task execution has been temporarily paused STOPPED: Task execution has been - * stopped (not completed) FINISHED: Task has completed successfully - */ -export type TaskStatus = 'started' | 'paused' | 'stopped' | 'finished'; - /** * View model for representing a task with its execution details * * Attributes: id: Unique identifier for the task session_id: ID of the session - * this task belongs to session_live_url: Live URL of the session llm: The LLM - * model used for this task task: The task prompt/instruction given to the agent - * status: Current status of the task execution started_at: Naive UTC timestamp - * when the task was started finished_at: Naive UTC timestamp when the task - * completed (None if still running) metadata: Additional metadata associated with - * the task (optionally set by the user) is_scheduled: Whether this task was - * created as a scheduled task steps: List of execution steps (optionally included - * per user request) done_output: Final output/result of the task - * user_uploaded_files: List of files uploaded by user for this task (optionally - * included per user request) output_files: List of files generated as output by - * this task (optionally included per user request) browser_use_version: Version of - * browser-use used for this task + * this task belongs to session_live_url: Optional live URL of the session llm: The + * LLM model used for this task task: The task prompt/instruction given to the + * agent status: Current status of the task execution started_at: Naive UTC + * timestamp when the task was started finished_at: Naive UTC timestamp when the + * task completed (None if still running) metadata: Optional additional metadata + * associated with the task set by the user is_scheduled: Whether this task was + * created as a scheduled task steps: Optional list of execution steps done_output: + * Final output/result of the task user_uploaded_files: Optional list of files + * uploaded by user for this task output_files: Optional list of files generated as + * output by this task browser_use_version: Version of browser-use used for this + * task (older tasks may not have this set) is_success: Whether the task was + * successful (self-reported by the agent) */ -export interface TaskView { +export interface TaskItemView { id: string; - doneOutput: string; - isScheduled: boolean; llm: LlmModel; @@ -152,9 +434,9 @@ export interface TaskView { /** * Enumeration of possible task execution states * - * Attributes: STARTED: Task has been initiated and is currently running PAUSED: - * Task execution has been temporarily paused STOPPED: Task execution has been - * stopped (not completed) FINISHED: Task has completed successfully + * Attributes: STARTED: Task has been started and is currently running PAUSED: Task + * execution has been temporarily paused (can be resumed) STOPPED: Task execution + * has been stopped (cannot be resumed) FINISHED: Task has completed successfully */ status: TaskStatus; @@ -162,82 +444,114 @@ export interface TaskView { browserUseVersion?: string | null; + doneOutput?: string | null; + finishedAt?: string | null; + isSuccess?: boolean | null; + metadata?: { [key: string]: unknown }; - outputFiles?: Array | null; + outputFiles?: Array | null; sessionLiveUrl?: string | null; - steps?: Array | null; + steps?: Array | null; - userUploadedFiles?: Array | null; + userUploadedFiles?: Array | null; } -export namespace TaskView { - /** - * View model for representing a single step in a task's execution - * - * Attributes: number: Sequential step number within the task memory: Agent's - * memory/context at this step evaluation_previous_goal: Agent's evaluation of the - * previous goal completion next_goal: The goal for the next step url: Current URL - * the browser is on for this step screenshot_url: URL to the screenshot taken at - * this step actions: List of stringified json actions performed by the agent in - * this step - */ - export interface Step { - actions: Array; +/** + * Enumeration of possible task execution states + * + * Attributes: STARTED: Task has been started and is currently running PAUSED: Task + * execution has been temporarily paused (can be resumed) STOPPED: Task execution + * has been stopped (cannot be resumed) FINISHED: Task has completed successfully + */ +export type TaskStatus = 'started' | 'paused' | 'stopped' | 'finished'; - evaluationPreviousGoal: string; +/** + * View model for representing a single step in a task's execution + * + * Attributes: number: Sequential step number within the task memory: Agent's + * memory at this step evaluation_previous_goal: Agent's evaluation of the previous + * goal completion next_goal: The goal for the next step url: Current URL the + * browser is on for this step screenshot_url: Optional URL to the screenshot taken + * at this step actions: List of stringified json actions performed by the agent in + * this step + */ +export interface TaskStepView { + actions: Array; - memory: string; + evaluationPreviousGoal: string; - nextGoal: string; + memory: string; - number: number; + nextGoal: string; - url: string; + number: number; - screenshotUrl?: string | null; - } + url: string; + + screenshotUrl?: string | null; } /** * View model for representing a task with its execution details * * Attributes: id: Unique identifier for the task session_id: ID of the session - * this task belongs to session_live_url: Live URL of the session llm: The LLM - * model used for this task task: The task prompt/instruction given to the agent - * status: Current status of the task execution started_at: Naive UTC timestamp - * when the task was started finished_at: Naive UTC timestamp when the task - * completed (None if still running) metadata: Additional metadata associated with - * the task (optionally set by the user) is_scheduled: Whether this task was - * created as a scheduled task steps: List of execution steps (optionally included - * per user request) done_output: Final output/result of the task - * user_uploaded_files: List of files uploaded by user for this task (optionally - * included per user request) output_files: List of files generated as output by - * this task (optionally included per user request) browser_use_version: Version of - * browser-use used for this task + * this task belongs to session_live_url: Optional live URL of the session llm: The + * LLM model used for this task task: The task prompt/instruction given to the + * agent status: Current status of the task execution started_at: Naive UTC + * timestamp when the task was started finished_at: Naive UTC timestamp when the + * task completed (None if still running) metadata: Optional additional metadata + * associated with the task set by the user is_scheduled: Whether this task was + * created as a scheduled task steps: List of execution steps done_output: Final + * output/result of the task user_uploaded_files: List of files uploaded by user + * for this task output_files: List of files generated as output by this task + * browser_use_version: Version of browser-use used for this task (older tasks may + * not have this set) is_success: Whether the task was successful (self-reported by + * the agent) */ -export type TaskRetrieveResponse = TaskView | TaskRetrieveResponse.TaskStatusView; +export interface TaskView { + id: string; + + isScheduled: boolean; + + llm: LlmModel; + + outputFiles: Array; + + sessionId: string; + + startedAt: string; -export namespace TaskRetrieveResponse { /** - * Minimal view for returning just the task status + * Enumeration of possible task execution states * - * Attributes: status: Current status of the task + * Attributes: STARTED: Task has been started and is currently running PAUSED: Task + * execution has been temporarily paused (can be resumed) STOPPED: Task execution + * has been stopped (cannot be resumed) FINISHED: Task has completed successfully */ - export interface TaskStatusView { - /** - * Enumeration of possible task execution states - * - * Attributes: STARTED: Task has been initiated and is currently running PAUSED: - * Task execution has been temporarily paused STOPPED: Task execution has been - * stopped (not completed) FINISHED: Task has completed successfully - */ - status: TasksAPI.TaskStatus; - } + status: TaskStatus; + + steps: Array; + + task: string; + + userUploadedFiles: Array; + + browserUseVersion?: string | null; + + doneOutput?: string | null; + + finishedAt?: string | null; + + isSuccess?: boolean | null; + + metadata?: { [key: string]: unknown }; + + sessionLiveUrl?: string | null; } /** @@ -246,7 +560,7 @@ export namespace TaskRetrieveResponse { * Attributes: items: List of task views for the current page */ export interface TaskListResponse { - items: Array; + items: Array; pageNumber: number; @@ -260,7 +574,7 @@ export interface TaskListResponse { * * Attributes: download_url: URL to download the log file */ -export interface TaskRetrieveLogsResponse { +export interface TaskGetLogsResponse { downloadUrl: string; } @@ -269,7 +583,16 @@ export interface TaskRetrieveLogsResponse { * * Attributes: download_url: URL to download the output file */ -export interface TaskRetrieveOutputFileResponse { +export interface TaskGetOutputFileResponse { + downloadUrl: string; +} + +/** + * Response model for user uploaded file requests + * + * Attributes: download_url: URL to download the user uploaded file + */ +export interface TaskGetUserUploadedFileResponse { downloadUrl: string; } @@ -279,19 +602,17 @@ export interface TaskCreateParams { /** * Configuration settings for the AI agent * - * Attributes: llm: The LLM model to use for the agent (default: O3 - best - * performance for now) profile_id: ID of the agent profile to use for the task - * (None for default) + * Attributes: llm: The LLM model to use for the agent profile_id: Unique + * identifier of the agent profile to use for the task */ agentSettings?: TaskCreateParams.AgentSettings; /** * Configuration settings for the browser session * - * Attributes: session_id: ID of existing session to continue (None for new - * session) profile_id: ID of browser profile to use (None for default) - * save_browser_data: Whether to save browser state/data for the user to download - * later + * Attributes: session_id: Unique identifier of existing session to continue + * profile_id: Unique identifier of browser profile to use save_browser_data: + * Whether to save browser state/data for the user to download later */ browserSettings?: TaskCreateParams.BrowserSettings; @@ -308,9 +629,8 @@ export namespace TaskCreateParams { /** * Configuration settings for the AI agent * - * Attributes: llm: The LLM model to use for the agent (default: O3 - best - * performance for now) profile_id: ID of the agent profile to use for the task - * (None for default) + * Attributes: llm: The LLM model to use for the agent profile_id: Unique + * identifier of the agent profile to use for the task */ export interface AgentSettings { llm?: TasksAPI.LlmModel; @@ -321,10 +641,9 @@ export namespace TaskCreateParams { /** * Configuration settings for the browser session * - * Attributes: session_id: ID of existing session to continue (None for new - * session) profile_id: ID of browser profile to use (None for default) - * save_browser_data: Whether to save browser state/data for the user to download - * later + * Attributes: session_id: Unique identifier of existing session to continue + * profile_id: Unique identifier of browser profile to use save_browser_data: + * Whether to save browser state/data for the user to download later */ export interface BrowserSettings { profileId?: string | null; @@ -335,10 +654,6 @@ export namespace TaskCreateParams { } } -export interface TaskRetrieveParams { - statusOnly?: boolean; -} - export interface TaskUpdateParams { /** * Available actions that can be performed on a task @@ -351,6 +666,15 @@ export interface TaskUpdateParams { } export interface TaskListParams { + /** + * Enumeration of possible task filters + * + * Attributes: STARTED: All started tasks PAUSED: All paused tasks STOPPED: All + * stopped tasks FINISHED: All finished tasks SUCCESSFUL: All successful tasks + * UNSUCCESSFUL: All unsuccessful tasks + */ + filterBy?: 'started' | 'paused' | 'stopped' | 'finished' | 'successful' | 'unsuccessful' | null; + includeOutputFiles?: boolean; includeSteps?: boolean; @@ -360,25 +684,34 @@ export interface TaskListParams { pageNumber?: number; pageSize?: number; + + sessionId?: string | null; +} + +export interface TaskGetOutputFileParams { + task_id: string; } -export interface TaskRetrieveOutputFileParams { +export interface TaskGetUserUploadedFileParams { task_id: string; } export declare namespace Tasks { export { + type FileView as FileView, type LlmModel as LlmModel, + type TaskItemView as TaskItemView, type TaskStatus as TaskStatus, + type TaskStepView as TaskStepView, type TaskView as TaskView, - type TaskRetrieveResponse as TaskRetrieveResponse, type TaskListResponse as TaskListResponse, - type TaskRetrieveLogsResponse as TaskRetrieveLogsResponse, - type TaskRetrieveOutputFileResponse as TaskRetrieveOutputFileResponse, + type TaskGetLogsResponse as TaskGetLogsResponse, + type TaskGetOutputFileResponse as TaskGetOutputFileResponse, + type TaskGetUserUploadedFileResponse as TaskGetUserUploadedFileResponse, type TaskCreateParams as TaskCreateParams, - type TaskRetrieveParams as TaskRetrieveParams, type TaskUpdateParams as TaskUpdateParams, type TaskListParams as TaskListParams, - type TaskRetrieveOutputFileParams as TaskRetrieveOutputFileParams, + type TaskGetOutputFileParams as TaskGetOutputFileParams, + type TaskGetUserUploadedFileParams as TaskGetUserUploadedFileParams, }; } diff --git a/src/resources/users.ts b/src/resources/users.ts new file mode 100644 index 0000000..db908c7 --- /dev/null +++ b/src/resources/users.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './users/index'; diff --git a/src/resources/users/index.ts b/src/resources/users/index.ts new file mode 100644 index 0000000..666f33a --- /dev/null +++ b/src/resources/users/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Me, type MeRetrieveResponse } from './me/index'; +export { Users } from './users'; diff --git a/src/resources/users/me.ts b/src/resources/users/me.ts new file mode 100644 index 0000000..54b12df --- /dev/null +++ b/src/resources/users/me.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './me/index'; diff --git a/src/resources/users/me/files.ts b/src/resources/users/me/files.ts new file mode 100644 index 0000000..bc7a119 --- /dev/null +++ b/src/resources/users/me/files.ts @@ -0,0 +1,95 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +export class Files extends APIResource { + /** + * Get a presigned URL for uploading files that AI agents can use during tasks. + * + * This endpoint generates a secure, time-limited upload URL that allows you to + * upload files directly to our storage system. These files can then be referenced + * in AI agent tasks for the agent to work with. + * + * Supported use cases: + * + * - Uploading documents for data extraction tasks + * - Providing reference materials for agents + * - Sharing files that agents need to process + * - Including images or PDFs for analysis + * + * The upload URL expires after 2 minutes for security. Files are automatically + * organized by user ID and can be referenced in task creation using the returned + * file name. + * + * Args: + * + * - request: File upload details including name, content type, and size + * + * Returns: + * + * - Presigned upload URL and form fields for direct file upload + * + * Raises: + * + * - 400: If the content type is unsupported + * - 500: If the upload URL generation fails (should not happen) + */ + createPresignedURL( + body: FileCreatePresignedURLParams, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/users/me/files/presigned-url', { body, ...options }); + } +} + +/** + * Response model for presigned upload URL + * + * Attributes: url: The URL to upload the file to method: The HTTP method to use + * for the upload fields: The form fields to include in the upload request + * file_name: The name of the file to upload (should be referenced when user wants + * to use the file in a task) expires_in: The number of seconds until the presigned + * URL expires + */ +export interface FileCreatePresignedURLResponse { + expiresIn: number; + + fields: { [key: string]: string }; + + fileName: string; + + method: 'POST'; + + url: string; +} + +export interface FileCreatePresignedURLParams { + contentType: + | 'image/jpg' + | 'image/jpeg' + | 'image/png' + | 'image/gif' + | 'image/webp' + | 'image/svg+xml' + | 'application/pdf' + | 'application/msword' + | 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + | 'application/vnd.ms-excel' + | 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + | 'text/plain' + | 'text/csv' + | 'text/markdown'; + + fileName: string; + + sizeBytes: number; +} + +export declare namespace Files { + export { + type FileCreatePresignedURLResponse as FileCreatePresignedURLResponse, + type FileCreatePresignedURLParams as FileCreatePresignedURLParams, + }; +} diff --git a/src/resources/users/me/index.ts b/src/resources/users/me/index.ts new file mode 100644 index 0000000..347401d --- /dev/null +++ b/src/resources/users/me/index.ts @@ -0,0 +1,4 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Files, type FileCreatePresignedURLResponse, type FileCreatePresignedURLParams } from './files'; +export { Me, type MeRetrieveResponse } from './me'; diff --git a/src/resources/users/me/me.ts b/src/resources/users/me/me.ts new file mode 100644 index 0000000..fbc4508 --- /dev/null +++ b/src/resources/users/me/me.ts @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as FilesAPI from './files'; +import { FileCreatePresignedURLParams, FileCreatePresignedURLResponse, Files } from './files'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +export class Me extends APIResource { + files: FilesAPI.Files = new FilesAPI.Files(this._client); + + /** + * Get information about the currently authenticated user. + * + * Retrieves your user profile information including: + * + * - Credit balances (monthly and additional credits in USD) + * - Account details (email, name, signup date) + * + * This endpoint is useful for: + * + * - Checking your remaining credits before running tasks + * - Displaying user information in your application + * + * Returns: + * + * - Complete user profile information including credits and account details + * + * Raises: + * + * - 404: If the user profile cannot be found + */ + retrieve(options?: RequestOptions): APIPromise { + return this._client.get('/users/me', options); + } +} + +/** + * View model for user information + * + * Attributes: monthly_credits_balance_usd: The monthly credits balance in USD + * additional_credits_balance_usd: The additional credits balance in USD email: The + * email address of the user name: The name of the user signed_up_at: The date and + * time the user signed up + */ +export interface MeRetrieveResponse { + additionalCreditsBalanceUsd: number; + + monthlyCreditsBalanceUsd: number; + + signedUpAt: string; + + email?: string | null; + + name?: string | null; +} + +Me.Files = Files; + +export declare namespace Me { + export { type MeRetrieveResponse as MeRetrieveResponse }; + + export { + Files as Files, + type FileCreatePresignedURLResponse as FileCreatePresignedURLResponse, + type FileCreatePresignedURLParams as FileCreatePresignedURLParams, + }; +} diff --git a/src/resources/users/users.ts b/src/resources/users/users.ts new file mode 100644 index 0000000..d8cbc33 --- /dev/null +++ b/src/resources/users/users.ts @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as MeAPI from './me/me'; +import { Me, MeRetrieveResponse } from './me/me'; + +export class Users extends APIResource { + me: MeAPI.Me = new MeAPI.Me(this._client); +} + +Users.Me = Me; + +export declare namespace Users { + export { Me as Me, type MeRetrieveResponse as MeRetrieveResponse }; +} diff --git a/src/version.ts b/src/version.ts index b322647..bade2ff 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.1.1'; // x-release-please-version +export const VERSION = '0.2.0'; // x-release-please-version diff --git a/tests/api-resources/agent-profiles.test.ts b/tests/api-resources/agent-profiles.test.ts index 35b4f59..5884295 100644 --- a/tests/api-resources/agent-profiles.test.ts +++ b/tests/api-resources/agent-profiles.test.ts @@ -25,11 +25,11 @@ describe('resource agentProfiles', () => { const response = await client.agentProfiles.create({ name: 'x', allowedDomains: ['string'], + customSystemPromptExtension: 'x', description: 'x', flashMode: true, highlightElements: true, maxAgentSteps: 1, - systemPrompt: 'x', thinking: true, vision: true, }); diff --git a/tests/api-resources/sessions/sessions.test.ts b/tests/api-resources/sessions/sessions.test.ts index ad07ad4..8e44b21 100644 --- a/tests/api-resources/sessions/sessions.test.ts +++ b/tests/api-resources/sessions/sessions.test.ts @@ -73,4 +73,16 @@ describe('resource sessions', () => { ), ).rejects.toThrow(BrowserUse.NotFoundError); }); + + // Prism tests are disabled + test.skip('delete', async () => { + const responsePromise = client.sessions.delete('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); }); diff --git a/tests/api-resources/tasks.test.ts b/tests/api-resources/tasks.test.ts index b856936..e74fa97 100644 --- a/tests/api-resources/tasks.test.ts +++ b/tests/api-resources/tasks.test.ts @@ -49,18 +49,6 @@ describe('resource tasks', () => { expect(dataAndResponse.response).toBe(rawResponse); }); - // Prism tests are disabled - test.skip('retrieve: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.tasks.retrieve( - '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', - { statusOnly: true }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BrowserUse.NotFoundError); - }); - // Prism tests are disabled test.skip('update: only required params', async () => { const responsePromise = client.tasks.update('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { action: 'stop' }); @@ -96,11 +84,13 @@ describe('resource tasks', () => { await expect( client.tasks.list( { + filterBy: 'started', includeOutputFiles: true, includeSteps: true, includeUserUploadedFiles: true, pageNumber: 1, pageSize: 1, + sessionId: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', }, { path: '/_stainless_unknown_path' }, ), @@ -108,8 +98,8 @@ describe('resource tasks', () => { }); // Prism tests are disabled - test.skip('retrieveLogs', async () => { - const responsePromise = client.tasks.retrieveLogs('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); + test.skip('getLogs', async () => { + const responsePromise = client.tasks.getLogs('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -120,8 +110,29 @@ describe('resource tasks', () => { }); // Prism tests are disabled - test.skip('retrieveOutputFile: only required params', async () => { - const responsePromise = client.tasks.retrieveOutputFile('file_name', { + test.skip('getOutputFile: only required params', async () => { + const responsePromise = client.tasks.getOutputFile('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + task_id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('getOutputFile: required and optional params', async () => { + const response = await client.tasks.getOutputFile('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { + task_id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', + }); + }); + + // Prism tests are disabled + test.skip('getUserUploadedFile: only required params', async () => { + const responsePromise = client.tasks.getUserUploadedFile('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { task_id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', }); const rawResponse = await responsePromise.asResponse(); @@ -134,8 +145,8 @@ describe('resource tasks', () => { }); // Prism tests are disabled - test.skip('retrieveOutputFile: required and optional params', async () => { - const response = await client.tasks.retrieveOutputFile('file_name', { + test.skip('getUserUploadedFile: required and optional params', async () => { + const response = await client.tasks.getUserUploadedFile('182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', { task_id: '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e', }); }); diff --git a/tests/api-resources/users/me/files.test.ts b/tests/api-resources/users/me/files.test.ts new file mode 100644 index 0000000..4bd615c --- /dev/null +++ b/tests/api-resources/users/me/files.test.ts @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import BrowserUse from 'browser-use-sdk'; + +const client = new BrowserUse({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource files', () => { + // Prism tests are disabled + test.skip('createPresignedURL: only required params', async () => { + const responsePromise = client.users.me.files.createPresignedURL({ + contentType: 'image/jpg', + fileName: 'x', + sizeBytes: 1, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + // Prism tests are disabled + test.skip('createPresignedURL: required and optional params', async () => { + const response = await client.users.me.files.createPresignedURL({ + contentType: 'image/jpg', + fileName: 'x', + sizeBytes: 1, + }); + }); +}); diff --git a/tests/api-resources/users/me/me.test.ts b/tests/api-resources/users/me/me.test.ts new file mode 100644 index 0000000..f31ccda --- /dev/null +++ b/tests/api-resources/users/me/me.test.ts @@ -0,0 +1,22 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import BrowserUse from 'browser-use-sdk'; + +const client = new BrowserUse({ + apiKey: 'My API Key', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +describe('resource me', () => { + // Prism tests are disabled + test.skip('retrieve', async () => { + const responsePromise = client.users.me.retrieve(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +});