@mablhq/mabl-cli 2.94.5 → 2.96.5

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.
Files changed (28) hide show
  1. package/api/featureSet.js +5 -1
  2. package/api/mablApiClient.js +8 -0
  3. package/commands/branches/branches_cmds/delete.js +63 -0
  4. package/execution/index.js +2 -2
  5. package/mablscript/importer.js +1 -0
  6. package/package.json +1 -1
  7. package/trainer/cli/CliEventHandler.js +69 -2
  8. package/trainer/cli/CliStateProvider.js +5 -1
  9. package/trainer/cli/CliTestGenerationState.js +25 -0
  10. package/trainer/cli/buildCliArtifacts.js +43 -19
  11. package/trainer/cli/runAgenticGeneration.js +15 -5
  12. package/trainer/generation/AgenticGenerationRunner.js +6 -2
  13. package/trainer/generation/TestGenerationOrchestrator.js +12 -15
  14. package/trainer/generation/toolExecutors/CompleteTaskExecutor.js +23 -11
  15. package/trainer/generation/toolExecutors/DeleteLastStepsExecutor.js +2 -1
  16. package/trainer/generation/toolExecutors/RecordAssertElementExecutor.js +3 -2
  17. package/trainer/generation/toolExecutors/RecordAssertionExecutor.js +13 -35
  18. package/trainer/generation/toolExecutors/RecordClickExecutor.js +4 -4
  19. package/trainer/generation/toolExecutors/RecordEnterTextExecutor.js +1 -1
  20. package/trainer/generation/toolExecutors/RecordHoverExecutor.js +1 -1
  21. package/trainer/generation/toolExecutors/RecordStartTaskExecutor.js +24 -4
  22. package/trainer/generation/toolExecutors/ScrollExecutor.js +6 -2
  23. package/trainer/generation/toolExecutors/VisitUrlExecutor.js +1 -1
  24. package/trainer/generation/toolExecutors/WaitExecutor.js +1 -1
  25. package/trainer/sharedUtils/boundingBoxUtils.js +11 -0
  26. package/trainer/sharedUtils/contextBuilder.js +7 -0
  27. package/trainer/sharedUtils/mablscript/extended/ExecuteStepGroupStep.js +3 -0
  28. package/trainer/sharedUtils/messageConversion.js +31 -0
@@ -37,10 +37,10 @@ exports.recordClickExecutor = {
37
37
  success: false,
38
38
  };
39
39
  }
40
+ const toolParams = payload.toolCall.toolParams;
40
41
  if ((0, toolExecutors_1.isFindOneEventMessage)(payload.find) && payload.find.selectOptions) {
41
- const elementDescription = payload.toolCall.toolParams?.elementDescription || 'unknown element';
42
- const elementBoundingBox = payload.toolCall.toolParams
43
- ?.elementBoundingBox;
42
+ const elementDescription = toolParams.elementDescription || 'unknown element';
43
+ const elementBoundingBox = toolParams.elementBoundingBox;
44
44
  const { errorMessage, applicationStatement } = buildNativeSelectErrorMessage(elementDescription, elementBoundingBox, payload.find.selectOptions);
45
45
  return {
46
46
  success: false,
@@ -49,6 +49,6 @@ exports.recordClickExecutor = {
49
49
  applicationInfo: [applicationStatement],
50
50
  };
51
51
  }
52
- return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(payload.find, payload.contextInfo, true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), CLICK_STEP_WAIT_TIME_MS, stateProvider, eventHandler, logger);
52
+ return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(payload.find, payload.contextInfo, true, undefined, stateProvider, eventHandler), CLICK_STEP_WAIT_TIME_MS, stateProvider, eventHandler, logger);
53
53
  },
54
54
  };
@@ -26,6 +26,6 @@ exports.recordEnterTextExecutor = {
26
26
  else {
27
27
  findEvent.inputValue = textToEnter;
28
28
  }
29
- return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(findEvent, payload.contextInfo, true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), ENTER_TEXT_STEP_WAIT_TIME_MS, stateProvider, eventHandler, logger);
29
+ return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(findEvent, payload.contextInfo, true, undefined, stateProvider, eventHandler), ENTER_TEXT_STEP_WAIT_TIME_MS, stateProvider, eventHandler, logger);
30
30
  },
31
31
  };
@@ -14,6 +14,6 @@ exports.recordHoverExecutor = {
14
14
  success: false,
15
15
  };
16
16
  }
17
- return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(payload.find, payload.contextInfo, true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), HOVER_STEP_WAIT_TIME_MS, stateProvider, eventHandler, logger);
17
+ return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(payload.find, payload.contextInfo, true, undefined, stateProvider, eventHandler), HOVER_STEP_WAIT_TIME_MS, stateProvider, eventHandler, logger);
18
18
  },
19
19
  };
@@ -5,12 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.recordStartTaskExecutor = void 0;
7
7
  exports.recordStartTaskStep = recordStartTaskStep;
8
- const toolExecutors_1 = require("../toolExecutors");
8
+ exports.recordStartTaskEchoStep = recordStartTaskEchoStep;
9
9
  const generation_types_1 = require("../../sharedUtils/generation-types");
10
+ const ExecuteStepGroupStep_1 = __importDefault(require("../../sharedUtils/mablscript/extended/ExecuteStepGroupStep"));
10
11
  const EchoStep_1 = __importDefault(require("../../sharedUtils/mablscript/canonical/EchoStep"));
11
12
  function recordStartTaskStep(taskDescription) {
12
- const steps = [new EchoStep_1.default(`${generation_types_1.START_TASK_PREFIX} ${taskDescription}`)];
13
- return { steps, stepsToReplay: steps.length };
13
+ const stepGroup = new ExecuteStepGroupStep_1.default([], taskDescription);
14
+ return { steps: [stepGroup], stepsToReplay: 1 };
15
+ }
16
+ function recordStartTaskEchoStep(taskDescription) {
17
+ const echoStep = new EchoStep_1.default(`${generation_types_1.START_TASK_PREFIX} ${taskDescription}`);
18
+ return { steps: [echoStep], stepsToReplay: 1 };
14
19
  }
15
20
  exports.recordStartTaskExecutor = {
16
21
  needsFind: () => false,
@@ -20,6 +25,21 @@ exports.recordStartTaskExecutor = {
20
25
  logger.error('Record start task executor requires step description');
21
26
  return { success: false };
22
27
  }
23
- return (0, toolExecutors_1.recordStepAndTrackResult)(() => Promise.resolve(recordStartTaskStep(payload.toolCall.toolDescription)), 0, stateProvider, eventHandler, logger);
28
+ const taskDescription = payload.toolCall.toolDescription;
29
+ const useStepGroups = stateProvider.hasStepGroupsFeature();
30
+ if (useStepGroups) {
31
+ const stepGroup = new ExecuteStepGroupStep_1.default([], taskDescription);
32
+ await eventHandler.dispatchSteps([stepGroup], {
33
+ skipActiveGroupInsertion: true,
34
+ });
35
+ if (!eventHandler.isInsideStepGroup()) {
36
+ eventHandler.moveCursorIntoGroup();
37
+ }
38
+ }
39
+ else {
40
+ const echoStep = new EchoStep_1.default(`${generation_types_1.START_TASK_PREFIX} ${taskDescription}`);
41
+ await eventHandler.dispatchSteps([echoStep]);
42
+ }
43
+ return { success: true };
24
44
  },
25
45
  };
@@ -4,6 +4,7 @@ exports.scrollExecutor = void 0;
4
4
  const mablApi_1 = require("../../../mablApi");
5
5
  const utilities_1 = require("../../utilities");
6
6
  const contentActions_1 = require("../../background/capture/contentActions");
7
+ const boundingBoxUtils_1 = require("../../sharedUtils/boundingBoxUtils");
7
8
  const DEFAULT_SCROLL_WAIT_TIME_MILLISECONDS = 1000;
8
9
  exports.scrollExecutor = {
9
10
  needsFind: () => false,
@@ -17,12 +18,15 @@ exports.scrollExecutor = {
17
18
  errorCause: 'IllegalArguments',
18
19
  };
19
20
  }
21
+ const internalBoundingBox = toolParams.elementBoundingBox
22
+ ? (0, boundingBoxUtils_1.convertToolLibraryBoundingBox)(toolParams.elementBoundingBox)
23
+ : undefined;
20
24
  let scrollStatus;
21
25
  if (toolParams.direction === 'up') {
22
- scrollStatus = await (0, contentActions_1.sendScrollUpMessage)(stateProvider.getTrainingContext(), toolParams.scrollFactor, toolParams.elementTargetPoint, toolParams.elementBoundingBox);
26
+ scrollStatus = await (0, contentActions_1.sendScrollUpMessage)(stateProvider.getTrainingContext(), toolParams.scrollFactor, toolParams.elementTargetPoint, internalBoundingBox);
23
27
  }
24
28
  else if (toolParams.direction === 'down') {
25
- scrollStatus = await (0, contentActions_1.sendScrollDownMessage)(stateProvider.getTrainingContext(), toolParams.scrollFactor, toolParams.elementTargetPoint, toolParams.elementBoundingBox);
29
+ scrollStatus = await (0, contentActions_1.sendScrollDownMessage)(stateProvider.getTrainingContext(), toolParams.scrollFactor, toolParams.elementTargetPoint, internalBoundingBox);
26
30
  }
27
31
  else {
28
32
  logger.error(`Unknown scroll direction (${toolParams.direction}) in scroll executor`);
@@ -20,6 +20,6 @@ exports.visitUrlExecutor = {
20
20
  action: 'record',
21
21
  listener: 'visit-url',
22
22
  url: toolParams.url,
23
- }, contextInfo, true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
23
+ }, contextInfo, true, undefined, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
24
24
  },
25
25
  };
@@ -15,7 +15,7 @@ exports.waitExecutor = {
15
15
  action: 'record',
16
16
  listener: 'wait',
17
17
  time: toolParams?.waitTime ?? DEFAULT_WAIT_STEP_WAIT_TIME_SECONDS,
18
- }, payload.contextInfo ?? (await stateProvider.getActiveContextInfo()), true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
18
+ }, payload.contextInfo ?? (await stateProvider.getActiveContextInfo()), true, undefined, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
19
19
  }
20
20
  await (0, utilities_1.sleep)((toolParams?.waitTime ?? DEFAULT_WAIT_STEP_WAIT_TIME_SECONDS) * 1000);
21
21
  return {
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToolLibraryBoundingBox = convertToolLibraryBoundingBox;
4
+ function convertToolLibraryBoundingBox(toolLibBox) {
5
+ return {
6
+ x: toolLibBox.left,
7
+ y: toolLibBox.top,
8
+ width: toolLibBox.right - toolLibBox.left,
9
+ height: toolLibBox.bottom - toolLibBox.top,
10
+ };
11
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CURSOR_MARKER = void 0;
4
4
  exports.parseTaskFromEchoStep = parseTaskFromEchoStep;
5
+ exports.parseTaskFromStep = parseTaskFromStep;
5
6
  exports.convertStepToSuccessContext = convertStepToSuccessContext;
6
7
  exports.getSupportedTools = getSupportedTools;
7
8
  exports.makeStepDescriptionForStartTask = makeStepDescriptionForStartTask;
@@ -13,6 +14,12 @@ function parseTaskFromEchoStep(step) {
13
14
  ? step.message.slice(generation_types_1.START_TASK_PREFIX.length).trim()
14
15
  : undefined;
15
16
  }
17
+ function parseTaskFromStep(step) {
18
+ if ((0, mablscript_step_types_1.isStepGroupStep)(step)) {
19
+ return step.description;
20
+ }
21
+ return undefined;
22
+ }
16
23
  function convertStepToSuccessContext(step) {
17
24
  if (!step) {
18
25
  return undefined;
@@ -49,6 +49,9 @@ class ExecuteStepGroupStep extends BaseStep_1.default {
49
49
  });
50
50
  return [...new Set(variables)];
51
51
  }
52
+ willGenerateMablscript() {
53
+ return false;
54
+ }
52
55
  }
53
56
  exports.default = ExecuteStepGroupStep;
54
57
  function humanizeExecuteStepGroupStep(step) {
@@ -4,6 +4,7 @@ exports.createUserTextMessage = createUserTextMessage;
4
4
  exports.createUserFileMessage = createUserFileMessage;
5
5
  exports.createToolOutputMessagePart = createToolOutputMessagePart;
6
6
  exports.createToolOutputMessage = createToolOutputMessage;
7
+ exports.createToolOutputFromResult = createToolOutputFromResult;
7
8
  exports.extractToolCallsFromMessages = extractToolCallsFromMessages;
8
9
  exports.filterClientSideToolCalls = filterClientSideToolCalls;
9
10
  exports.filterToolCallsWithoutOutputs = filterToolCallsWithoutOutputs;
@@ -85,6 +86,36 @@ function createToolOutputMessage(toolOutputMessageParts) {
85
86
  parts: toolOutputMessageParts,
86
87
  };
87
88
  }
89
+ function createToolOutputFromResult(params) {
90
+ const { toolCallId, toolName, wrappedResult } = params;
91
+ const { result, isError } = wrappedResult;
92
+ const contentItems = [];
93
+ contentItems.push({
94
+ type: 'json',
95
+ json: result.toolResponse,
96
+ });
97
+ if (result.imageContentItems) {
98
+ for (const img of result.imageContentItems) {
99
+ if (img.type === 'image-data' && img.image_data && img.media_type) {
100
+ const imageDataContentItem = {
101
+ type: 'image-data',
102
+ image_data: img.image_data,
103
+ media_type: img.media_type,
104
+ };
105
+ contentItems.push(imageDataContentItem);
106
+ }
107
+ }
108
+ }
109
+ const output = isError
110
+ ? { type: 'error-content', error_content: contentItems }
111
+ : { type: 'content', content: contentItems };
112
+ return {
113
+ type: 'tool_output',
114
+ tool_name: toolName,
115
+ tool_call_id: toolCallId,
116
+ output,
117
+ };
118
+ }
88
119
  function extractToolCallsFromMessages(messages, logger) {
89
120
  const modelMessages = messages.filter((m) => m.role === 'model');
90
121
  return modelMessages.flatMap((m) => (m.parts ?? [])