@e2e-dev/decision 0.2.0 → 0.2.1-nightly-20261010091034
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/.build.json +1 -1
- package/dist/dispatch.js +3 -0
- package/dist/elements.d.ts +5 -2
- package/dist/elements.js +15 -0
- package/dist/executor.js +8 -3
- package/dist/questions.js +1 -0
- package/package.json +4 -4
package/dist/.build.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.2.
|
|
1
|
+
{"version":"0.2.1-nightly-20261010091034"}
|
package/dist/dispatch.js
CHANGED
|
@@ -15,6 +15,9 @@ export async function perform(ctx, action) {
|
|
|
15
15
|
case 'back':
|
|
16
16
|
await actions.back();
|
|
17
17
|
return undefined;
|
|
18
|
+
case 'dismiss_keyboard':
|
|
19
|
+
await actions.dismissKeyboard();
|
|
20
|
+
return undefined;
|
|
18
21
|
case 'tap':
|
|
19
22
|
await actions.tap(node(action.target));
|
|
20
23
|
return undefined;
|
package/dist/elements.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ExecutorNode, ExecutorPixels, StepExecutorContext } from 'e2e';
|
|
2
2
|
/** Operations the executor offers on elements. */
|
|
3
3
|
export type Operation = 'tap' | 'type' | 'typeSecret' | 'submit' | 'select' | 'check' | 'hover' | 'secondary_tap' | 'double_tap' | 'long_press' | 'drag' | 'scroll_to' | 'upload' | 'tap_at';
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Viewport, history, and keyboard controls, offered when the engine declares
|
|
6
|
+
* the verb; `dismiss_keyboard` only while an on-screen keyboard is showing.
|
|
7
|
+
*/
|
|
8
|
+
export type Control = 'scroll_up' | 'scroll_down' | 'back' | 'dismiss_keyboard';
|
|
6
9
|
/** Terminal choices: the step claims completion, reports a product failure, or gives up. */
|
|
7
10
|
export type Terminal = 'done' | 'failed' | 'blocked';
|
|
8
11
|
/** One row of the element table the decision model reads. */
|
package/dist/elements.js
CHANGED
|
@@ -14,6 +14,8 @@ const tappable = new Set([
|
|
|
14
14
|
const typable = new Set(['textbox', 'searchbox', 'spinbutton', 'combobox']);
|
|
15
15
|
const secretTypable = new Set(['textbox', 'searchbox', 'combobox']);
|
|
16
16
|
const checkable = new Set(['checkbox', 'radio', 'switch']);
|
|
17
|
+
/** Roles a device tree gives the soft keyboard and its keys; an iOS number pad lists only its keys. */
|
|
18
|
+
const keyboardRoles = new Set(['keyboard', 'key']);
|
|
17
19
|
/** Live regions whose text reports what the app just did; a log can run long, so each line and their count are bounded. */
|
|
18
20
|
const liveRegions = new Set(['status', 'alert', 'log']);
|
|
19
21
|
const MAX_STATUSES = 20;
|
|
@@ -204,6 +206,8 @@ export function actionSpace(ctx, observation, canType) {
|
|
|
204
206
|
}
|
|
205
207
|
if (verbs.has('back'))
|
|
206
208
|
controls.add('back');
|
|
209
|
+
if (verbs.has('dismissKeyboard') && keyboardShowing(observation.tree))
|
|
210
|
+
controls.add('dismiss_keyboard');
|
|
207
211
|
return {
|
|
208
212
|
elements,
|
|
209
213
|
element: (key) => byIndex.get(targetKeyIndex(key)),
|
|
@@ -251,6 +255,17 @@ export function targetKeyIndex(key) {
|
|
|
251
255
|
const at = key.indexOf(':');
|
|
252
256
|
return at === -1 ? key : key.slice(0, at);
|
|
253
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* Whether the tree lists an on-screen keyboard. Offering the control only
|
|
260
|
+
* then keeps a choice that does nothing out of the operation question.
|
|
261
|
+
*/
|
|
262
|
+
function keyboardShowing(node) {
|
|
263
|
+
if (node.states?.hidden === true)
|
|
264
|
+
return false;
|
|
265
|
+
if (keyboardRoles.has(node.role ?? ''))
|
|
266
|
+
return true;
|
|
267
|
+
return (node.children ?? []).some(keyboardShowing);
|
|
268
|
+
}
|
|
254
269
|
/** Label the model reads: name, placeholder, or text. */
|
|
255
270
|
function nodeLabel(node) {
|
|
256
271
|
return node.name ?? node.attributes?.['placeholder'] ?? node.text ?? '';
|
package/dist/executor.js
CHANGED
|
@@ -211,7 +211,7 @@ class Step {
|
|
|
211
211
|
const acting = { ...view, space: view.space };
|
|
212
212
|
this.settle(acting);
|
|
213
213
|
if (stalled(this.history))
|
|
214
|
-
return blocked('Three actions in a row changed nothing on screen.');
|
|
214
|
+
return blocked('Three actions in a row failed or changed nothing on screen.');
|
|
215
215
|
const decided = await this.ask(operationRequest(this.ctx, acting.space, this.history, acting.path));
|
|
216
216
|
if (decided === undefined)
|
|
217
217
|
return blocked(this.budgetMessage());
|
|
@@ -406,6 +406,7 @@ const CONTROL_LABELS = {
|
|
|
406
406
|
scroll_up: 'scroll viewport up',
|
|
407
407
|
scroll_down: 'scroll viewport down',
|
|
408
408
|
back: 'back one step in history',
|
|
409
|
+
dismiss_keyboard: 'dismiss the keyboard',
|
|
409
410
|
};
|
|
410
411
|
/** The field a text ask describes: the element's label, role, and value; a textbox named by its key when the table has no row. */
|
|
411
412
|
function fieldOf(key, element) {
|
|
@@ -443,11 +444,15 @@ function seedHistory(ctx) {
|
|
|
443
444
|
}
|
|
444
445
|
return seeded;
|
|
445
446
|
}
|
|
446
|
-
/**
|
|
447
|
+
/**
|
|
448
|
+
* Three recorded actions in a row that failed or left the page unchanged. A
|
|
449
|
+
* failed action is no progress even when the page changed on its own, as a
|
|
450
|
+
* ticking timer does.
|
|
451
|
+
*/
|
|
447
452
|
function stalled(history) {
|
|
448
453
|
if (history.length < 3)
|
|
449
454
|
return false;
|
|
450
|
-
return history.slice(-3).every((entry) => entry.pageChanged === false);
|
|
455
|
+
return history.slice(-3).every((entry) => entry.error !== undefined || entry.pageChanged === false);
|
|
451
456
|
}
|
|
452
457
|
/** No nodes to build an action space from. A truncated observation still acts on what is there. */
|
|
453
458
|
function emptyTree(observation) {
|
package/dist/questions.js
CHANGED
|
@@ -49,6 +49,7 @@ const OPERATIONS = {
|
|
|
49
49
|
scroll_up: 'Scroll the viewport up.',
|
|
50
50
|
scroll_down: 'Scroll the viewport down.',
|
|
51
51
|
back: 'Go back to the previous page, as the browser back button does.',
|
|
52
|
+
dismiss_keyboard: 'The on-screen keyboard is up. Controls it covers are missing from the elements; hide it to reach them.',
|
|
52
53
|
};
|
|
53
54
|
/** The fallback criterion of a target question. */
|
|
54
55
|
const NONE_TARGET = 'No offered target fits the goal.';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@e2e-dev/decision",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1-nightly-20261010091034",
|
|
4
4
|
"description": "Decision-model executors for e2e",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -30,18 +30,18 @@
|
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"ai": "^7.0.134",
|
|
33
|
-
"e2e": "
|
|
33
|
+
"e2e": "0.19.1-nightly-20261010091034"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@ai-sdk/openai": "4.0.90",
|
|
37
37
|
"@ai-sdk/typesafe-ai": "3.0.16",
|
|
38
|
-
"@e2e-dev/web": "0.14.
|
|
38
|
+
"@e2e-dev/web": "0.14.1-nightly-20261010091034",
|
|
39
39
|
"@types/node": "26.6.2",
|
|
40
40
|
"@types/pngjs": "6.0.5",
|
|
41
41
|
"ai": "7.0.134",
|
|
42
42
|
"ajv": "8.20.0",
|
|
43
43
|
"ajv-formats": "3.0.1",
|
|
44
|
-
"e2e": "0.19.
|
|
44
|
+
"e2e": "0.19.1-nightly-20261010091034",
|
|
45
45
|
"typescript": "7.0.2",
|
|
46
46
|
"vitest": "5.0.1"
|
|
47
47
|
},
|