@nuanu-ai/agentbrowse 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/commands/act.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/commands/act.ts"],"names":[],"mappings":"AAAA;;GAEG;AAoCH,wBAAsB,GAAG,CACvB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
|
package/dist/commands/act.js
CHANGED
|
@@ -3,28 +3,71 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { connectStagehand, getPageInfo } from '../stagehand.js';
|
|
5
5
|
import { outputJSON, outputError } from '../output.js';
|
|
6
|
+
const ROOT_SELECTORS = new Set(['/', '/html', 'xpath=/', 'xpath=/html']);
|
|
7
|
+
const CONCRETE_TARGET_METHODS = new Set([
|
|
8
|
+
'click',
|
|
9
|
+
'doubleClick',
|
|
10
|
+
'fill',
|
|
11
|
+
'type',
|
|
12
|
+
'hover',
|
|
13
|
+
'dragAndDrop',
|
|
14
|
+
'selectOption',
|
|
15
|
+
'selectOptionFromDropdown',
|
|
16
|
+
'clickAndHold',
|
|
17
|
+
]);
|
|
18
|
+
// Stagehand's act prompt says "return an empty object" when no element matches,
|
|
19
|
+
// but its act schema requires a concrete elementId/method pair. In practice,
|
|
20
|
+
// that contradiction sometimes produces a synthetic page-root action
|
|
21
|
+
// (`xpath=/html`) which Playwright accepts as a successful no-op click/type.
|
|
22
|
+
function isSyntheticRootSuccess(result) {
|
|
23
|
+
if (!result.success || !Array.isArray(result.actions) || result.actions.length === 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const [firstAction] = result.actions;
|
|
27
|
+
const selector = firstAction?.selector?.trim();
|
|
28
|
+
const method = firstAction?.method?.trim();
|
|
29
|
+
return ROOT_SELECTORS.has(selector ?? '') && CONCRETE_TARGET_METHODS.has(method ?? '');
|
|
30
|
+
}
|
|
6
31
|
export async function act(cdpUrl, instruction, variables) {
|
|
7
32
|
let stagehand;
|
|
33
|
+
let url = 'unknown';
|
|
34
|
+
let title = 'unknown';
|
|
35
|
+
let failureMessage = null;
|
|
8
36
|
try {
|
|
9
37
|
stagehand = await connectStagehand(cdpUrl);
|
|
10
38
|
}
|
|
11
39
|
catch (err) {
|
|
12
|
-
outputError(`Failed to connect to browser: ${err instanceof Error ? err.message : String(err)}`);
|
|
40
|
+
return outputError(`Failed to connect to browser: ${err instanceof Error ? err.message : String(err)}`);
|
|
13
41
|
}
|
|
14
42
|
try {
|
|
15
43
|
const result = await stagehand.act(instruction, variables ? { variables } : undefined);
|
|
16
|
-
|
|
44
|
+
({ url, title } = await getPageInfo(stagehand));
|
|
17
45
|
await stagehand.close();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
46
|
+
if (isSyntheticRootSuccess(result)) {
|
|
47
|
+
failureMessage =
|
|
48
|
+
`Act failed: Stagehand selected the page root instead of a concrete element. ` +
|
|
49
|
+
`This usually means no actionable match was found for: ${instruction} ` +
|
|
50
|
+
`(page: ${title} — ${url})`;
|
|
51
|
+
}
|
|
52
|
+
else if (!result.success) {
|
|
53
|
+
const message = typeof result.message === 'string' && result.message.trim().length > 0
|
|
54
|
+
? result.message.trim()
|
|
55
|
+
: `Stagehand could not complete the requested action: ${instruction}`;
|
|
56
|
+
failureMessage = `Act failed: ${message} (page: ${title} — ${url})`;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return outputJSON({
|
|
60
|
+
success: true,
|
|
61
|
+
action: result.actionDescription ?? instruction,
|
|
62
|
+
message: result.message,
|
|
63
|
+
url,
|
|
64
|
+
title,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
25
67
|
}
|
|
26
68
|
catch (err) {
|
|
27
69
|
await stagehand.close();
|
|
28
|
-
|
|
70
|
+
failureMessage = `Act failed: ${err instanceof Error ? err.message : String(err)} (page: ${title} — ${url})`;
|
|
29
71
|
}
|
|
72
|
+
return outputError(failureMessage ?? `Act failed: Stagehand could not complete the requested action: ${instruction}`);
|
|
30
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/commands/observe.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/commands/observe.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAsB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCjF"}
|
package/dist/commands/observe.js
CHANGED
|
@@ -19,6 +19,7 @@ export async function observe(cdpUrl, instruction) {
|
|
|
19
19
|
await stagehand.close();
|
|
20
20
|
outputJSON({
|
|
21
21
|
success: true,
|
|
22
|
+
message: actions.length === 0 ? 'No actions found by Stagehand observe.' : undefined,
|
|
22
23
|
actions: actions.map((a) => ({
|
|
23
24
|
description: a.description,
|
|
24
25
|
selector: a.selector,
|
package/dist/output.js
CHANGED
|
@@ -10,7 +10,7 @@ function formatValue(value) {
|
|
|
10
10
|
/** Write result to stdout and exit. Errors go to stderr with exit 1. */
|
|
11
11
|
export function outputJSON(result) {
|
|
12
12
|
if (!result.success) {
|
|
13
|
-
process.stderr.write(`${result.error}\n`);
|
|
13
|
+
process.stderr.write(`${result.error ?? 'Unknown error'}\n`);
|
|
14
14
|
process.exit(1);
|
|
15
15
|
}
|
|
16
16
|
const { success: _, ...rest } = result;
|