diff --git a/.gitignore b/.gitignore index fd14d889b..eea3e7465 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,6 @@ /scripts/node_modules # bun specific -.bun -bun.lock bun-debug.log* # testing diff --git a/.husky/pre-commit b/.husky/pre-commit index b93406c1f..f54fc9cd5 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -cd apps/sim && npx lint-staged \ No newline at end of file +bunx lint-staged \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index e0cdf4082..60df87199 100644 --- a/.prettierignore +++ b/.prettierignore @@ -32,7 +32,4 @@ coverage **/public/sw.js **/public/workbox-*.js **/public/worker-*.js -**/public/fallback-*.js - -# Documentation -apps/docs/**/*.mdx \ No newline at end of file +**/public/fallback-*.js \ No newline at end of file diff --git a/apps/docs/content/docs/tools/browser_use.mdx b/apps/docs/content/docs/tools/browser_use.mdx index b8059bc04..643ffa300 100644 --- a/apps/docs/content/docs/tools/browser_use.mdx +++ b/apps/docs/content/docs/tools/browser_use.mdx @@ -66,23 +66,22 @@ Runs a browser automation task using BrowserUse #### Input -| Parameter | Type | Required | Description | -| -------------- | ------ | -------- | ---------------------------------------------------------------------------------------- | -| `task` | string | Yes | What should the browser agent do | -| `apiKey` | string | Yes | API key for BrowserUse API | -| `pollInterval` | number | No | Interval between polling requests in milliseconds \(default: 5000\) | -| `maxPollTime` | number | No | Maximum time to poll for task completion in milliseconds \(default: 300000 - 5 minutes\) | +| Parameter | Type | Required | Description | +| ------------------- | ------- | -------- | --------------------------------------------------------------- | +| `task` | string | Yes | What should the browser agent do | +| `variables` | json | No | Optional variables to use as secrets \(format: \{key: value\}\) | +| `save_browser_data` | boolean | No | Whether to save browser data | +| `model` | string | No | LLM model to use \(default: gpt-4o\) | +| `apiKey` | string | Yes | API key for BrowserUse API | #### Output -| Parameter | Type | -| ---------- | ------ | -| `id` | string | -| `task` | string | -| `output` | string | -| `status` | string | -| `steps` | string | -| `live_url` | string | +| Parameter | Type | +| --------- | ------ | +| `id` | string | +| `success` | string | +| `output` | string | +| `steps` | string | ## Block Configuration @@ -94,15 +93,13 @@ Runs a browser automation task using BrowserUse ### Outputs -| Output | Type | Description | -| ------------ | ------ | ------------------------ | -| `response` | object | Output from response | -| ↳ `id` | string | id of the response | -| ↳ `task` | string | task of the response | -| ↳ `output` | any | output of the response | -| ↳ `status` | string | status of the response | -| ↳ `steps` | json | steps of the response | -| ↳ `live_url` | any | live_url of the response | +| Output | Type | Description | +| ----------- | ------- | ----------------------- | +| `response` | object | Output from response | +| ↳ `id` | string | id of the response | +| ↳ `success` | boolean | success of the response | +| ↳ `output` | any | output of the response | +| ↳ `steps` | json | steps of the response | ## Notes diff --git a/apps/docs/content/docs/tools/clay.mdx b/apps/docs/content/docs/tools/clay.mdx index 1034718ed..f94df3855 100644 --- a/apps/docs/content/docs/tools/clay.mdx +++ b/apps/docs/content/docs/tools/clay.mdx @@ -1,6 +1,6 @@ --- title: Clay -description: Populate Clay workbook with data +description: Populate Clay workbook --- import { BlockInfoCard } from '@/components/ui/block-info-card' diff --git a/apps/docs/content/docs/tools/discord.mdx b/apps/docs/content/docs/tools/discord.mdx index bbce58594..4104533ee 100644 --- a/apps/docs/content/docs/tools/discord.mdx +++ b/apps/docs/content/docs/tools/discord.mdx @@ -5,17 +5,28 @@ description: Interact with Discord import { BlockInfoCard } from '@/components/ui/block-info-card' - - - - - - -`} + iconSvg={` + + + + `} /> {/* MANUAL-CONTENT-START:intro */} diff --git a/apps/docs/content/docs/tools/meta.json b/apps/docs/content/docs/tools/meta.json index 3d3ef15bc..f331ca1a8 100644 --- a/apps/docs/content/docs/tools/meta.json +++ b/apps/docs/content/docs/tools/meta.json @@ -45,4 +45,4 @@ "x", "youtube" ] -} +} \ No newline at end of file diff --git a/apps/sim/blocks/blocks/browser_use.ts b/apps/sim/blocks/blocks/browser_use.ts index f2b51ca3e..10e26fc87 100644 --- a/apps/sim/blocks/blocks/browser_use.ts +++ b/apps/sim/blocks/blocks/browser_use.ts @@ -5,11 +5,9 @@ import { BlockConfig } from '../types' interface BrowserUseResponse extends ToolResponse { output: { id: string - task: string - output: string | null - status: string + success: boolean + output: any steps: any[] - live_url: string | null } } @@ -31,6 +29,34 @@ export const BrowserUseBlock: BlockConfig = { layout: 'full', placeholder: 'Describe what the browser agent should do...', }, + { + id: 'variables', + title: 'Variables (Secrets)', + type: 'table', + layout: 'full', + columns: ['Key', 'Value'], + }, + { + id: 'model', + title: 'Model', + type: 'dropdown', + layout: 'half', + options: [ + { label: 'gpt-4o', id: 'gpt-4o' }, + { label: 'gpt-4.1', id: 'gpt-4.1' }, + { label: 'gemini-2.0-flash', id: 'gemini-2.0-flash' }, + { label: 'gemini-2.0-flash-lite', id: 'gemini-2.0-flash-lite' }, + { label: 'claude-3-7-sonnet-20250219', id: 'claude-3-7-sonnet-20250219' }, + { label: 'llama-4-maverick-17b-128e-instruct', id: 'llama-4-maverick-17b-128e-instruct' }, + ], + }, + { + id: 'save_browser_data', + title: 'Save Browser Data', + type: 'switch', + layout: 'half', + placeholder: 'Save browser data', + }, { id: 'apiKey', title: 'API Key', @@ -39,20 +65,6 @@ export const BrowserUseBlock: BlockConfig = { password: true, placeholder: 'Enter your BrowserUse API key', }, - { - id: 'pollInterval', - title: 'Poll Interval (ms)', - type: 'short-input', - layout: 'half', - placeholder: '5000', - }, - { - id: 'maxPollTime', - title: 'Max Poll Time (ms)', - type: 'short-input', - layout: 'half', - placeholder: '300000', - }, ], tools: { access: ['browser_use_run_task'], @@ -60,18 +72,17 @@ export const BrowserUseBlock: BlockConfig = { inputs: { task: { type: 'string', required: true }, apiKey: { type: 'string', required: true }, - pollInterval: { type: 'number', required: false }, - maxPollTime: { type: 'number', required: false }, + variables: { type: 'json', required: false }, + model: { type: 'string', required: false }, + save_browser_data: { type: 'boolean', required: false }, }, outputs: { response: { type: { id: 'string', - task: 'string', + success: 'boolean', output: 'any', - status: 'string', steps: 'json', - live_url: 'any', }, }, }, diff --git a/apps/sim/package.json b/apps/sim/package.json index 6710ee3b1..4db0dc179 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -24,13 +24,6 @@ "test:watch": "vitest", "test:coverage": "vitest run --coverage", "email:dev": "email dev --dir components/emails", - "cli:build": "bun run build -w packages/simstudio", - "cli:dev": "bun run build -w packages/simstudio && cd packages/simstudio && bun ./dist/index.js", - "cli:publish": "cd packages/simstudio && bun publish", - "cli:start": "cd packages/simstudio && bun ./dist/index.js start", - "build:standalone": "bun scripts/build-standalone.js", - "build:cli": "bun run cli:build && bun run build:standalone", - "publish:cli": "bun run build:cli && bun run cli:publish", "check-types": "tsc --noEmit" }, "dependencies": { diff --git a/apps/sim/tools/browser_use/run_task.ts b/apps/sim/tools/browser_use/run_task.ts index 61d56cd64..82e5bede7 100644 --- a/apps/sim/tools/browser_use/run_task.ts +++ b/apps/sim/tools/browser_use/run_task.ts @@ -1,9 +1,12 @@ import { createLogger } from '@/lib/logs/console-logger' import { ToolConfig } from '../types' -import { BrowserUseRunTaskParams, BrowserUseRunTaskResponse, BrowserUseTaskOutput } from './types' +import { BrowserUseRunTaskParams, BrowserUseRunTaskResponse } from './types' const logger = createLogger('BrowserUseTool') +const POLL_INTERVAL_MS = 5000 // 5 seconds between polls +const MAX_POLL_TIME_MS = 180000 // 3 minutes maximum polling time + export const runTaskTool: ToolConfig = { id: 'browser_use_run_task', name: 'Browser Use', @@ -16,24 +19,27 @@ export const runTaskTool: ToolConfig ({ - task: params.task, - }), + body: (params) => { + const requestBody: Record = { + task: params.task, + } + + if (params.variables) { + let secrets: Record = {} + + if (Array.isArray(params.variables)) { + logger.info('Converting variables array to dictionary format') + params.variables.forEach((row) => { + if (row.cells && row.cells.Key && row.cells.Value !== undefined) { + secrets[row.cells.Key] = row.cells.Value + logger.info(`Added secret for key: ${row.cells.Key}`) + } else if (row.Key && row.Value !== undefined) { + secrets[row.Key] = row.Value + logger.info(`Added secret for key: ${row.Key}`) + } + }) + } else if (typeof params.variables === 'object' && params.variables !== null) { + logger.info('Using variables object directly') + secrets = params.variables + } + + if (Object.keys(secrets).length > 0) { + logger.info(`Found ${Object.keys(secrets).length} secrets to include`) + requestBody.secrets = secrets + } else { + logger.warn('No usable secrets found in variables') + } + } + + if (params.model) { + requestBody.llm_model = params.model + } + + if (params.save_browser_data) { + requestBody.save_browser_data = params.save_browser_data + } + + requestBody.use_adblock = true + requestBody.highlight_elements = true + + return requestBody + }, }, transformResponse: async (response: Response) => { @@ -57,16 +105,14 @@ export const runTaskTool: ToolConfig= 1000 - ? params.pollInterval - : 5000 - - const maxPollTime = - typeof params.maxPollTime === 'number' && params.maxPollTime >= 5000 - ? params.maxPollTime - : 300000 - let elapsedTime = 0 - while (elapsedTime < maxPollTime) { + while (elapsedTime < MAX_POLL_TIME_MS) { try { const statusResponse = await fetch( `https://api.browser-use.com/api/v1/task/${taskId}/status`, @@ -130,7 +165,6 @@ export const runTaskTool: ToolConfig setTimeout(resolve, pollInterval)) - elapsedTime += pollInterval + await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS)) + elapsedTime += POLL_INTERVAL_MS } catch (error: any) { logger.error('Error polling for task status:', { message: error.message || 'Unknown error', @@ -184,17 +222,16 @@ export const runTaskTool: ToolConfig { try { - // Check if error message contains a JSON string (from 422 errors) const errorData = JSON.parse(error.message) if (errorData.detail && Array.isArray(errorData.detail)) { const formattedError = errorData.detail diff --git a/apps/sim/tools/browser_use/types.ts b/apps/sim/tools/browser_use/types.ts index e1eeefb1e..34d29cc1c 100644 --- a/apps/sim/tools/browser_use/types.ts +++ b/apps/sim/tools/browser_use/types.ts @@ -3,8 +3,9 @@ import { ToolResponse } from '../types' export interface BrowserUseRunTaskParams { task: string apiKey: string - pollInterval?: number - maxPollTime?: number + variables?: Record + model?: string + save_browser_data?: boolean } export interface BrowserUseTaskStep { @@ -12,15 +13,15 @@ export interface BrowserUseTaskStep { step: number evaluation_previous_goal: string next_goal: string + url?: string + extracted_data?: Record } export interface BrowserUseTaskOutput { id: string - task: string - output: string | null - status: 'created' | 'running' | 'finished' | 'stopped' | 'paused' | 'failed' + success: boolean + output: any steps: BrowserUseTaskStep[] - live_url: string | null } export interface BrowserUseRunTaskResponse extends ToolResponse { diff --git a/package.json b/package.json index b3f9c0b2b..0d573a6c8 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,8 @@ "test": "turbo run test", "format": "prettier --write .", "format:check": "prettier --check .", - "lint": "turbo run lint" + "lint": "turbo run lint", + "prepare": "bun husky" }, "overrides": { "react": "19.1.0",