@morphllm/morphsdk 0.2.94 → 0.2.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-YJ354BA2.js → chunk-2AMEQAO2.js} +2 -2
- package/dist/chunk-2AMEQAO2.js.map +1 -0
- package/dist/{chunk-EI4UKP24.js → chunk-2HMEZZKK.js} +2 -2
- package/dist/{chunk-EI4UKP24.js.map → chunk-2HMEZZKK.js.map} +1 -1
- package/dist/{chunk-UJ7LVT5G.js → chunk-2VERUKO2.js} +1 -1
- package/dist/chunk-2VERUKO2.js.map +1 -0
- package/dist/{chunk-R7WN43L2.js → chunk-4KMBU6T3.js} +4 -4
- package/dist/{chunk-IH3KN4AT.js → chunk-AIXF4GQC.js} +2 -2
- package/dist/{chunk-VHOWYK66.js → chunk-BGEEES52.js} +23 -33
- package/dist/chunk-BGEEES52.js.map +1 -0
- package/dist/{chunk-4WO7PJNT.js → chunk-EZEYREHA.js} +8 -8
- package/dist/{chunk-BVVDDTI7.js → chunk-L5WXPMCH.js} +2 -2
- package/dist/{chunk-FIA6LBW2.js → chunk-OTPYEYMZ.js} +2 -2
- package/dist/{chunk-5QIWYEHJ.js → chunk-PE4KGDA6.js} +1 -8
- package/dist/chunk-PE4KGDA6.js.map +1 -0
- package/dist/{chunk-SQN4DUQS.js → chunk-Q6Y4R236.js} +26 -2
- package/dist/chunk-Q6Y4R236.js.map +1 -0
- package/dist/{chunk-TXYCM4NP.js → chunk-QH4BSXOD.js} +3 -3
- package/dist/{chunk-M7GFXRKL.js → chunk-QJP62BXH.js} +157 -72
- package/dist/chunk-QJP62BXH.js.map +1 -0
- package/dist/{chunk-AV6YV2MH.js → chunk-R7IQWNSA.js} +8 -8
- package/dist/chunk-R7IQWNSA.js.map +1 -0
- package/dist/{chunk-ESRZJRTQ.js → chunk-SI2CKRKJ.js} +86 -56
- package/dist/chunk-SI2CKRKJ.js.map +1 -0
- package/dist/{chunk-FMWNVTJJ.js → chunk-TSENDJQI.js} +6 -6
- package/dist/chunk-TSENDJQI.js.map +1 -0
- package/dist/{chunk-IUG2FHNN.js → chunk-XH7P7HVT.js} +1 -8
- package/dist/chunk-XH7P7HVT.js.map +1 -0
- package/dist/{chunk-WSQMWVSD.js → chunk-YZ5NCWO2.js} +6 -6
- package/dist/chunk-YZ5NCWO2.js.map +1 -0
- package/dist/client.cjs +280 -162
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +18 -18
- package/dist/index.cjs +280 -162
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18 -18
- package/dist/tools/browser/anthropic.cjs +54 -23
- package/dist/tools/browser/anthropic.cjs.map +1 -1
- package/dist/tools/browser/anthropic.js +7 -7
- package/dist/tools/browser/core.cjs +262 -124
- package/dist/tools/browser/core.cjs.map +1 -1
- package/dist/tools/browser/core.d.ts +24 -24
- package/dist/tools/browser/core.js +5 -5
- package/dist/tools/browser/errors.cjs.map +1 -1
- package/dist/tools/browser/errors.d.ts +1 -1
- package/dist/tools/browser/errors.js +1 -1
- package/dist/tools/browser/index.cjs +277 -139
- package/dist/tools/browser/index.cjs.map +1 -1
- package/dist/tools/browser/index.d.ts +3 -3
- package/dist/tools/browser/index.js +12 -12
- package/dist/tools/browser/index.js.map +1 -1
- package/dist/tools/browser/live.cjs +25 -1
- package/dist/tools/browser/live.cjs.map +1 -1
- package/dist/tools/browser/live.js +1 -1
- package/dist/tools/browser/openai.cjs +54 -23
- package/dist/tools/browser/openai.cjs.map +1 -1
- package/dist/tools/browser/openai.js +7 -7
- package/dist/tools/browser/profiles/core.cjs +85 -54
- package/dist/tools/browser/profiles/core.cjs.map +1 -1
- package/dist/tools/browser/profiles/core.d.ts +33 -25
- package/dist/tools/browser/profiles/core.js +5 -3
- package/dist/tools/browser/profiles/index.cjs +85 -54
- package/dist/tools/browser/profiles/index.cjs.map +1 -1
- package/dist/tools/browser/profiles/index.d.ts +2 -2
- package/dist/tools/browser/profiles/index.js +5 -3
- package/dist/tools/browser/profiles/types.cjs +1 -1
- package/dist/tools/browser/profiles/types.cjs.map +1 -1
- package/dist/tools/browser/profiles/types.d.ts +28 -9
- package/dist/tools/browser/profiles/types.js +1 -1
- package/dist/tools/browser/prompts.cjs +1 -1
- package/dist/tools/browser/prompts.cjs.map +1 -1
- package/dist/tools/browser/prompts.d.ts +1 -1
- package/dist/tools/browser/prompts.js +1 -1
- package/dist/tools/browser/types.cjs.map +1 -1
- package/dist/tools/browser/types.d.ts +54 -52
- package/dist/tools/browser/vercel.cjs +56 -25
- package/dist/tools/browser/vercel.cjs.map +1 -1
- package/dist/tools/browser/vercel.d.ts +1 -1
- package/dist/tools/browser/vercel.js +7 -7
- package/dist/tools/fastapply/anthropic.cjs +0 -7
- package/dist/tools/fastapply/anthropic.cjs.map +1 -1
- package/dist/tools/fastapply/anthropic.js +1 -1
- package/dist/tools/fastapply/index.cjs +0 -14
- package/dist/tools/fastapply/index.cjs.map +1 -1
- package/dist/tools/fastapply/index.js +2 -2
- package/dist/tools/fastapply/openai.cjs +0 -7
- package/dist/tools/fastapply/openai.cjs.map +1 -1
- package/dist/tools/fastapply/openai.js +1 -1
- package/dist/tools/index.cjs +0 -14
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.js +2 -2
- package/dist/tools/warp_grep/agent/runner.cjs +18 -98
- package/dist/tools/warp_grep/agent/runner.cjs.map +1 -1
- package/dist/tools/warp_grep/agent/runner.js +2 -3
- package/dist/tools/warp_grep/anthropic.cjs +18 -98
- package/dist/tools/warp_grep/anthropic.cjs.map +1 -1
- package/dist/tools/warp_grep/anthropic.js +8 -9
- package/dist/tools/warp_grep/client.cjs +18 -98
- package/dist/tools/warp_grep/client.cjs.map +1 -1
- package/dist/tools/warp_grep/client.js +7 -8
- package/dist/tools/warp_grep/gemini.cjs +18 -98
- package/dist/tools/warp_grep/gemini.cjs.map +1 -1
- package/dist/tools/warp_grep/gemini.js +7 -8
- package/dist/tools/warp_grep/gemini.js.map +1 -1
- package/dist/tools/warp_grep/harness.js +10 -10
- package/dist/tools/warp_grep/index.cjs +18 -98
- package/dist/tools/warp_grep/index.cjs.map +1 -1
- package/dist/tools/warp_grep/index.js +10 -11
- package/dist/tools/warp_grep/openai.cjs +18 -98
- package/dist/tools/warp_grep/openai.cjs.map +1 -1
- package/dist/tools/warp_grep/openai.js +8 -9
- package/dist/tools/warp_grep/providers/local.js +2 -2
- package/dist/tools/warp_grep/vercel.cjs +18 -98
- package/dist/tools/warp_grep/vercel.cjs.map +1 -1
- package/dist/tools/warp_grep/vercel.js +8 -9
- package/dist/{vercel-CsnNSdze.d.ts → vercel-CVF27qFK.d.ts} +10 -10
- package/package.json +1 -1
- package/dist/chunk-5QIWYEHJ.js.map +0 -1
- package/dist/chunk-AV6YV2MH.js.map +0 -1
- package/dist/chunk-ESRZJRTQ.js.map +0 -1
- package/dist/chunk-FMWNVTJJ.js.map +0 -1
- package/dist/chunk-IUG2FHNN.js.map +0 -1
- package/dist/chunk-M7GFXRKL.js.map +0 -1
- package/dist/chunk-SQN4DUQS.js.map +0 -1
- package/dist/chunk-UJ7LVT5G.js.map +0 -1
- package/dist/chunk-VHOWYK66.js.map +0 -1
- package/dist/chunk-WSQMWVSD.js.map +0 -1
- package/dist/chunk-YJ354BA2.js.map +0 -1
- /package/dist/{chunk-R7WN43L2.js.map → chunk-4KMBU6T3.js.map} +0 -0
- /package/dist/{chunk-IH3KN4AT.js.map → chunk-AIXF4GQC.js.map} +0 -0
- /package/dist/{chunk-4WO7PJNT.js.map → chunk-EZEYREHA.js.map} +0 -0
- /package/dist/{chunk-BVVDDTI7.js.map → chunk-L5WXPMCH.js.map} +0 -0
- /package/dist/{chunk-FIA6LBW2.js.map → chunk-OTPYEYMZ.js.map} +0 -0
- /package/dist/{chunk-TXYCM4NP.js.map → chunk-QH4BSXOD.js.map} +0 -0
|
@@ -7,7 +7,7 @@ import { RetryConfig } from '../utils/resilience.js';
|
|
|
7
7
|
/**
|
|
8
8
|
* Available browser automation models
|
|
9
9
|
*/
|
|
10
|
-
type BrowserModel = 'gemini-3-flash-preview' | 'morph-computer-use-v0';
|
|
10
|
+
type BrowserModel = 'gemini-3-flash-preview' | 'morph-computer-use-v0' | 'morph-computer-use-v1';
|
|
11
11
|
/**
|
|
12
12
|
* Configuration for the browser worker service
|
|
13
13
|
*/
|
|
@@ -43,7 +43,7 @@ interface BrowserTaskInput {
|
|
|
43
43
|
/** Starting URL (e.g., https://3000-xyz.e2b.dev) */
|
|
44
44
|
url?: string;
|
|
45
45
|
/** Maximum number of browser actions to take (1-50, default: 10) */
|
|
46
|
-
|
|
46
|
+
maxSteps?: number;
|
|
47
47
|
/** Model to use for task execution (default: morph-computer-use-v0) */
|
|
48
48
|
model?: BrowserModel;
|
|
49
49
|
/** Browserless region: 'sfo' (US West) or 'lon' (Europe) */
|
|
@@ -51,34 +51,36 @@ interface BrowserTaskInput {
|
|
|
51
51
|
/** Enable stealth mode to avoid bot detection (default: true) */
|
|
52
52
|
stealth?: boolean;
|
|
53
53
|
/** Browser viewport width (default: 1280) */
|
|
54
|
-
|
|
54
|
+
viewportWidth?: number;
|
|
55
55
|
/** Browser viewport height (default: 720) */
|
|
56
|
-
|
|
56
|
+
viewportHeight?: number;
|
|
57
57
|
/** User-defined reference/tracking ID (e.g., "PR-1234", "jira-PROJ-567") */
|
|
58
|
-
|
|
59
|
-
/** Optional repository ID to associate with this session */
|
|
60
|
-
|
|
58
|
+
externalId?: string;
|
|
59
|
+
/** Optional repository database ID (UUID) to associate with this session - for internal use */
|
|
60
|
+
repoId?: string;
|
|
61
|
+
/** Optional repository full name (e.g., "owner/repo") - for external SDK users */
|
|
62
|
+
repoFullName?: string;
|
|
61
63
|
/** Optional commit UUID to associate with this session */
|
|
62
|
-
|
|
64
|
+
commitId?: string;
|
|
63
65
|
/** Record session video to S3 (default: false) */
|
|
64
|
-
|
|
66
|
+
recordVideo?: boolean;
|
|
65
67
|
/** Video width (default: 1280) */
|
|
66
|
-
|
|
68
|
+
videoWidth?: number;
|
|
67
69
|
/** Video height (default: 720) */
|
|
68
|
-
|
|
70
|
+
videoHeight?: number;
|
|
69
71
|
/** Enable window resizing for responsive/mobile testing. Disables stealth mode. (default: false) */
|
|
70
|
-
|
|
72
|
+
allowResizing?: boolean;
|
|
71
73
|
/** Serialized structured output schema (internal use) */
|
|
72
|
-
|
|
74
|
+
structuredOutput?: string;
|
|
73
75
|
/** Site authentication - global credentials or per-domain dict (follows browser-use pattern) */
|
|
74
76
|
auth?: AuthCredentials | Record<string, AuthCredentials>;
|
|
75
77
|
/** Profile ID - restore cookies/localStorage from a saved browser profile */
|
|
76
|
-
|
|
78
|
+
profileId?: string;
|
|
77
79
|
}
|
|
78
80
|
/**
|
|
79
81
|
* Input with Zod schema for structured output
|
|
80
82
|
*/
|
|
81
|
-
interface BrowserTaskInputWithSchema<T> extends Omit<BrowserTaskInput, '
|
|
83
|
+
interface BrowserTaskInputWithSchema<T> extends Omit<BrowserTaskInput, 'structuredOutput'> {
|
|
82
84
|
/** Zod schema for structured output */
|
|
83
85
|
schema: any;
|
|
84
86
|
}
|
|
@@ -93,27 +95,27 @@ interface BrowserTaskResult {
|
|
|
93
95
|
/** Error message if task failed */
|
|
94
96
|
error?: string;
|
|
95
97
|
/** Number of browser actions taken */
|
|
96
|
-
|
|
98
|
+
stepsTaken?: number;
|
|
97
99
|
/** Total execution time in milliseconds */
|
|
98
|
-
|
|
100
|
+
executionTimeMs?: number;
|
|
99
101
|
/** All URLs visited during execution */
|
|
100
102
|
urls?: (string | null)[];
|
|
101
103
|
/** Names of all actions executed */
|
|
102
|
-
|
|
104
|
+
actionNames?: string[];
|
|
103
105
|
/** Per-step errors (null for steps without errors) */
|
|
104
106
|
errors?: (string | null)[];
|
|
105
107
|
/** All model actions with parameters */
|
|
106
|
-
|
|
108
|
+
modelActions?: any[];
|
|
107
109
|
/** Whether agent marked task as done */
|
|
108
|
-
|
|
110
|
+
isDone?: boolean;
|
|
109
111
|
/** Truncated action history with essential fields */
|
|
110
|
-
|
|
112
|
+
actionHistory?: any[][];
|
|
111
113
|
/** All action results */
|
|
112
|
-
|
|
114
|
+
actionResults?: any[];
|
|
113
115
|
/** Whether any errors occurred */
|
|
114
|
-
|
|
116
|
+
hasErrors?: boolean;
|
|
115
117
|
/** Total number of steps executed */
|
|
116
|
-
|
|
118
|
+
numberOfSteps?: number;
|
|
117
119
|
/** Judge validation result if available */
|
|
118
120
|
judgement?: {
|
|
119
121
|
reasoning?: string;
|
|
@@ -123,17 +125,17 @@ interface BrowserTaskResult {
|
|
|
123
125
|
reached_captcha?: boolean;
|
|
124
126
|
};
|
|
125
127
|
/** Whether judge validated the execution */
|
|
126
|
-
|
|
128
|
+
isValidated?: boolean;
|
|
127
129
|
/** UUID of saved replay record (if session replay enabled) */
|
|
128
|
-
|
|
130
|
+
replayId?: string;
|
|
129
131
|
/** Browserless replay URL (if session replay enabled) */
|
|
130
|
-
|
|
131
|
-
/** Recording ID (if
|
|
132
|
-
|
|
132
|
+
replayUrl?: string;
|
|
133
|
+
/** Recording ID (if recordVideo=true) */
|
|
134
|
+
recordingId?: string;
|
|
133
135
|
/** Recording status: PENDING, PROCESSING, COMPLETED, ERROR */
|
|
134
|
-
|
|
136
|
+
recordingStatus?: string;
|
|
135
137
|
/** Task ID for async task tracking */
|
|
136
|
-
|
|
138
|
+
taskId?: string;
|
|
137
139
|
/** Task status: pending, running, completed, failed */
|
|
138
140
|
status?: string;
|
|
139
141
|
/** Structured output (JSON string) */
|
|
@@ -173,7 +175,7 @@ interface IframeOptions extends LiveSessionOptions {
|
|
|
173
175
|
* Task result with convenience methods for async execution
|
|
174
176
|
*/
|
|
175
177
|
interface BrowserTaskWithPromise extends BrowserTaskResult {
|
|
176
|
-
|
|
178
|
+
taskId: string;
|
|
177
179
|
/** Live URL to watch task execution in real-time */
|
|
178
180
|
liveUrl: string;
|
|
179
181
|
/** Wait for task completion */
|
|
@@ -192,7 +194,7 @@ interface BrowserTaskWithPromise extends BrowserTaskResult {
|
|
|
192
194
|
* Task result with schema validation
|
|
193
195
|
*/
|
|
194
196
|
interface BrowserTaskWithPromiseAndSchema<T> extends BrowserTaskResult {
|
|
195
|
-
|
|
197
|
+
taskId: string;
|
|
196
198
|
/** Live URL to watch task execution in real-time */
|
|
197
199
|
liveUrl: string;
|
|
198
200
|
/** Parsed and validated output */
|
|
@@ -220,23 +222,23 @@ interface RecordingStatus {
|
|
|
220
222
|
/** Current status */
|
|
221
223
|
status: 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'ERROR';
|
|
222
224
|
/** Presigned S3 URL for rrweb replay JSON (interactive DOM replay) */
|
|
223
|
-
|
|
225
|
+
replayUrl?: string;
|
|
224
226
|
/** Presigned S3 URL for network logs (NDJSON format) */
|
|
225
|
-
|
|
227
|
+
networkUrl?: string;
|
|
226
228
|
/** Presigned S3 URL for console logs (NDJSON format) */
|
|
227
|
-
|
|
229
|
+
consoleUrl?: string;
|
|
228
230
|
/** Presigned S3 URL for native browser video (WebM or MP4 format, real-time recording) */
|
|
229
|
-
|
|
231
|
+
videoUrl?: string;
|
|
230
232
|
/** Total rrweb events captured */
|
|
231
|
-
|
|
233
|
+
totalEvents?: number;
|
|
232
234
|
/** Total bytes of all files */
|
|
233
|
-
|
|
235
|
+
fileSize?: number;
|
|
234
236
|
/** Duration in milliseconds */
|
|
235
237
|
duration?: number;
|
|
236
238
|
/** Error message if status=ERROR */
|
|
237
239
|
error?: string;
|
|
238
240
|
/** When recording was created */
|
|
239
|
-
|
|
241
|
+
createdAt: string;
|
|
240
242
|
}
|
|
241
243
|
/**
|
|
242
244
|
* Browser error with screenshot captured at error time
|
|
@@ -251,9 +253,9 @@ interface BrowserError {
|
|
|
251
253
|
/** CDP timestamp in seconds since browser start */
|
|
252
254
|
timestamp: number;
|
|
253
255
|
/** Presigned S3 URL to screenshot JPEG (captured 500ms after error) */
|
|
254
|
-
|
|
256
|
+
screenshotUrl?: string;
|
|
255
257
|
/** When screenshot was captured (Unix timestamp) */
|
|
256
|
-
|
|
258
|
+
capturedAt?: number;
|
|
257
259
|
/** HTTP status code (for network errors) */
|
|
258
260
|
status?: number;
|
|
259
261
|
}
|
|
@@ -262,9 +264,9 @@ interface BrowserError {
|
|
|
262
264
|
*/
|
|
263
265
|
interface ErrorsResponse {
|
|
264
266
|
/** Recording ID */
|
|
265
|
-
|
|
267
|
+
recordingId: string;
|
|
266
268
|
/** Total number of errors */
|
|
267
|
-
|
|
269
|
+
totalErrors: number;
|
|
268
270
|
/** Errors with real-time screenshots */
|
|
269
271
|
errors: BrowserError[];
|
|
270
272
|
}
|
|
@@ -273,7 +275,7 @@ interface ErrorsResponse {
|
|
|
273
275
|
*/
|
|
274
276
|
interface WebpOptions {
|
|
275
277
|
/** Maximum duration in seconds (1-120, default: 60) */
|
|
276
|
-
|
|
278
|
+
maxDuration?: number;
|
|
277
279
|
/** Frame rate (5-30, default: 15) */
|
|
278
280
|
fps?: number;
|
|
279
281
|
/** Output width in pixels (320-1920, default: 780) */
|
|
@@ -283,14 +285,14 @@ interface WebpOptions {
|
|
|
283
285
|
/** Enable auto-zoom that follows click/input actions (default: false) */
|
|
284
286
|
autoZoom?: boolean;
|
|
285
287
|
/** Maximum file size in MB (0.5-50). Uses iterative reduction to guarantee budget. */
|
|
286
|
-
|
|
288
|
+
maxSizeMb?: number;
|
|
287
289
|
}
|
|
288
290
|
/**
|
|
289
291
|
* Response from getWebp()
|
|
290
292
|
*/
|
|
291
293
|
interface WebpResponse {
|
|
292
294
|
/** Presigned S3 URL for the WebP file */
|
|
293
|
-
|
|
295
|
+
webpUrl: string;
|
|
294
296
|
/** Whether the WebP was served from cache */
|
|
295
297
|
cached: boolean;
|
|
296
298
|
/** Width of the WebP (may differ from requested if budget-constrained) */
|
|
@@ -298,15 +300,15 @@ interface WebpResponse {
|
|
|
298
300
|
/** Frame rate of the WebP (may differ from requested if budget-constrained) */
|
|
299
301
|
fps: number;
|
|
300
302
|
/** Max duration used (may differ from requested if budget-constrained) */
|
|
301
|
-
|
|
303
|
+
maxDuration: number;
|
|
302
304
|
/** File size in bytes */
|
|
303
|
-
|
|
305
|
+
fileSize?: number;
|
|
304
306
|
/** Max size budget in MB (if specified) */
|
|
305
|
-
|
|
307
|
+
maxSizeMb?: number;
|
|
306
308
|
/** Whether the file fits within the budget */
|
|
307
|
-
|
|
309
|
+
budgetMet?: boolean;
|
|
308
310
|
/** Quality setting used (may differ from requested if budget-constrained) */
|
|
309
|
-
|
|
311
|
+
qualityUsed?: number;
|
|
310
312
|
/** Number of encoding attempts needed to meet budget */
|
|
311
313
|
attempts?: number;
|
|
312
314
|
}
|
|
@@ -121,15 +121,15 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
121
121
|
error: 'Task description is required. Example: "Go to example.com and click the login button"'
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
-
if (input.
|
|
124
|
+
if (input.maxSteps !== void 0 && (input.maxSteps < 1 || input.maxSteps > 50)) {
|
|
125
125
|
return {
|
|
126
126
|
success: false,
|
|
127
|
-
error: "
|
|
127
|
+
error: "maxSteps must be between 1 and 50. Use more steps for complex multi-page flows."
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
130
|
if (debug) {
|
|
131
|
-
console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.
|
|
132
|
-
console.log(`[Browser] Recording: ${input.
|
|
131
|
+
console.log(`[Browser] Task: "${input.task.slice(0, 60)}..." url=${input.url || "none"} maxSteps=${input.maxSteps ?? 10}`);
|
|
132
|
+
console.log(`[Browser] Recording: ${input.recordVideo ? "yes" : "no"} | Calling ${apiUrl}/browser-task`);
|
|
133
133
|
}
|
|
134
134
|
const startTime = Date.now();
|
|
135
135
|
try {
|
|
@@ -143,20 +143,20 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
143
143
|
body: JSON.stringify({
|
|
144
144
|
task: input.task,
|
|
145
145
|
url: input.url,
|
|
146
|
-
max_steps: input.
|
|
146
|
+
max_steps: input.maxSteps ?? 10,
|
|
147
147
|
model: input.model ?? "morph-computer-use-v0",
|
|
148
|
-
viewport_width: input.
|
|
149
|
-
viewport_height: input.
|
|
150
|
-
external_id: input.
|
|
151
|
-
repo_id: input.
|
|
152
|
-
commit_id: input.
|
|
153
|
-
record_video: input.
|
|
154
|
-
video_width: input.
|
|
155
|
-
video_height: input.
|
|
156
|
-
allow_resizing: input.
|
|
157
|
-
structured_output: input.
|
|
148
|
+
viewport_width: input.viewportWidth ?? 1280,
|
|
149
|
+
viewport_height: input.viewportHeight ?? 720,
|
|
150
|
+
external_id: input.externalId,
|
|
151
|
+
repo_id: input.repoId,
|
|
152
|
+
commit_id: input.commitId,
|
|
153
|
+
record_video: input.recordVideo ?? false,
|
|
154
|
+
video_width: input.videoWidth ?? input.viewportWidth ?? 1280,
|
|
155
|
+
video_height: input.videoHeight ?? input.viewportHeight ?? 720,
|
|
156
|
+
allow_resizing: input.allowResizing ?? false,
|
|
157
|
+
structured_output: input.structuredOutput,
|
|
158
158
|
auth: input.auth,
|
|
159
|
-
profile_id: input.
|
|
159
|
+
profile_id: input.profileId
|
|
160
160
|
})
|
|
161
161
|
},
|
|
162
162
|
config.retryConfig
|
|
@@ -164,17 +164,17 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
164
164
|
const response = await withTimeout(
|
|
165
165
|
fetchPromise,
|
|
166
166
|
timeout,
|
|
167
|
-
`Browser task timed out after ${timeout}ms. Consider increasing timeout or reducing
|
|
167
|
+
`Browser task timed out after ${timeout}ms. Consider increasing timeout or reducing maxSteps.`
|
|
168
168
|
);
|
|
169
169
|
if (!response.ok) {
|
|
170
170
|
const errorText = await response.text().catch(() => response.statusText);
|
|
171
171
|
if (debug) console.error(`[Browser] Error: ${response.status} - ${errorText}`);
|
|
172
172
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
173
173
|
}
|
|
174
|
-
const result = await response.json();
|
|
174
|
+
const result = mapTaskResult(await response.json());
|
|
175
175
|
const elapsed = Date.now() - startTime;
|
|
176
176
|
if (debug) {
|
|
177
|
-
console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.
|
|
177
|
+
console.log(`[Browser] \u2705 ${result.success ? "Success" : "Failed"} in ${elapsed}ms | steps=${result.stepsTaken ?? 0} recordingId=${result.recordingId ?? "none"}`);
|
|
178
178
|
}
|
|
179
179
|
return result;
|
|
180
180
|
} catch (error) {
|
|
@@ -196,6 +196,37 @@ async function executeBrowserTask(input, config = {}) {
|
|
|
196
196
|
};
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
+
function mapTaskResult(api) {
|
|
200
|
+
if (!api || typeof api !== "object") {
|
|
201
|
+
return api;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
success: api.success,
|
|
205
|
+
result: api.result,
|
|
206
|
+
error: api.error,
|
|
207
|
+
stepsTaken: api.steps_taken,
|
|
208
|
+
executionTimeMs: api.execution_time_ms,
|
|
209
|
+
urls: api.urls,
|
|
210
|
+
actionNames: api.action_names,
|
|
211
|
+
errors: api.errors,
|
|
212
|
+
modelActions: api.model_actions,
|
|
213
|
+
isDone: api.is_done,
|
|
214
|
+
actionHistory: api.action_history,
|
|
215
|
+
actionResults: api.action_results,
|
|
216
|
+
hasErrors: api.has_errors,
|
|
217
|
+
numberOfSteps: api.number_of_steps,
|
|
218
|
+
judgement: api.judgement,
|
|
219
|
+
isValidated: api.is_validated,
|
|
220
|
+
replayId: api.replay_id,
|
|
221
|
+
replayUrl: api.replay_url,
|
|
222
|
+
recordingId: api.recording_id,
|
|
223
|
+
recordingStatus: api.recording_status,
|
|
224
|
+
taskId: api.task_id,
|
|
225
|
+
status: api.status,
|
|
226
|
+
output: api.output,
|
|
227
|
+
debugUrl: api.debug_url
|
|
228
|
+
};
|
|
229
|
+
}
|
|
199
230
|
|
|
200
231
|
// tools/browser/prompts.ts
|
|
201
232
|
var BROWSER_TOOL_DESCRIPTION = `Test and verify your implemented code in a live browser. This tool executes natural language test instructions and returns a video recording plus detailed logs to help you debug issues.
|
|
@@ -233,31 +264,31 @@ Include verification steps:
|
|
|
233
264
|
## Requirements
|
|
234
265
|
- **URL**: Must be publicly accessible (use tunnels like ngrok, Cloudflare, or deploy to staging)
|
|
235
266
|
- **Timing**: Use this after implementation, not during coding
|
|
236
|
-
- **Complexity**: Set
|
|
267
|
+
- **Complexity**: Set maxSteps higher (20-30) for multi-step user workflows`;
|
|
237
268
|
|
|
238
269
|
// tools/browser/vercel.ts
|
|
239
270
|
function createBrowserTool(config) {
|
|
240
271
|
const schema = import_zod.z.object({
|
|
241
272
|
task: import_zod.z.string().describe('Natural language description of what to do (e.g., "Test checkout flow for buying a pineapple")'),
|
|
242
273
|
url: import_zod.z.string().optional().describe("Starting URL (e.g., https://3000-xyz.e2b.dev)"),
|
|
243
|
-
|
|
274
|
+
maxSteps: import_zod.z.number().min(1).max(50).default(10).describe("Maximum number of browser actions to take"),
|
|
244
275
|
region: import_zod.z.enum(["sfo", "lon"]).default("sfo").describe("Browserless region: sfo (US West) or lon (Europe)")
|
|
245
276
|
});
|
|
246
277
|
return (0, import_ai.tool)({
|
|
247
278
|
description: BROWSER_TOOL_DESCRIPTION,
|
|
248
279
|
inputSchema: schema,
|
|
249
280
|
execute: async (params) => {
|
|
250
|
-
const { task, url,
|
|
281
|
+
const { task, url, maxSteps, region } = params;
|
|
251
282
|
const result = await executeBrowserTask(
|
|
252
|
-
{ task, url,
|
|
283
|
+
{ task, url, maxSteps, region },
|
|
253
284
|
config
|
|
254
285
|
);
|
|
255
286
|
if (result.success) {
|
|
256
287
|
return {
|
|
257
288
|
success: true,
|
|
258
289
|
result: result.result,
|
|
259
|
-
|
|
260
|
-
|
|
290
|
+
stepsTaken: result.stepsTaken,
|
|
291
|
+
executionTimeMs: result.executionTimeMs
|
|
261
292
|
};
|
|
262
293
|
}
|
|
263
294
|
return {
|