@mablhq/mabl-cli 2.94.5 → 2.94.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mablhq/mabl-cli",
3
- "version": "2.94.5",
3
+ "version": "2.94.10",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "The official mabl command line interface tool",
6
6
  "main": "index.js",
@@ -7,6 +7,7 @@ exports.TestGenerationOrchestrator = void 0;
7
7
  const async_retry_1 = __importDefault(require("async-retry"));
8
8
  const mablApi_1 = require("../../mablApi");
9
9
  const toolExecutors_1 = require("./toolExecutors");
10
+ const boundingBoxUtils_1 = require("../sharedUtils/boundingBoxUtils");
10
11
  const contentActions_1 = require("../background/capture/contentActions");
11
12
  const generation_types_1 = require("../sharedUtils/generation-types");
12
13
  const messageConversion_1 = require("../sharedUtils/messageConversion");
@@ -252,7 +253,9 @@ class TestGenerationOrchestrator {
252
253
  };
253
254
  this.logger.info('[runGenerationLoop] Tool call information', JSON.stringify(toolCall, undefined, 2));
254
255
  if (toolExecutor.needsFind(toolCall)) {
255
- const boundingBox = TestGenerationOrchestrator.buildBoundingBox(toolCall.toolParams?.elementBoundingBox);
256
+ const boundingBox = toolCall.toolParams?.elementBoundingBox
257
+ ? (0, boundingBoxUtils_1.convertToolLibraryBoundingBox)(toolCall.toolParams.elementBoundingBox)
258
+ : undefined;
256
259
  if (!boundingBox) {
257
260
  this.logger.error(`Tool ${originalToolCall.name} requires element location but no bounding box was provided by the API`);
258
261
  skippedTools.push({
@@ -452,17 +455,6 @@ class TestGenerationOrchestrator {
452
455
  return true;
453
456
  }
454
457
  }
455
- static buildBoundingBox(responseBoundingBox) {
456
- if (!responseBoundingBox) {
457
- return undefined;
458
- }
459
- return {
460
- x: responseBoundingBox.left,
461
- y: responseBoundingBox.top,
462
- width: responseBoundingBox.right - responseBoundingBox.left,
463
- height: responseBoundingBox.bottom - responseBoundingBox.top,
464
- };
465
- }
466
458
  async captureToolOutputContext(success, toolName, tabsBefore = []) {
467
459
  const { needsScreenshot, needsUrl, needsTabInfo } = (0, toolExecutors_1.toolNeedsPostExecutionContext)(toolName, success);
468
460
  const context = {};
@@ -6,7 +6,8 @@ exports.deleteLastStepsExecutor = {
6
6
  needsFind: () => false,
7
7
  getStepType: () => mablApi_1.ExecuteToolName.DeleteLastSteps,
8
8
  execute: (payload, _stateProvider, eventHandler, logger) => {
9
- const toolParams = payload.toolCall.toolParams;
9
+ const toolParams = payload.toolCall
10
+ .toolParams;
10
11
  const { stepsToDelete } = toolParams;
11
12
  if (typeof stepsToDelete !== 'number' || stepsToDelete <= 0) {
12
13
  logger.error('Invalid stepsToDelete for RecordDeleteLastStepsExecutor');
@@ -9,7 +9,8 @@ exports.recordAssertElementExecutor = {
9
9
  needsFind: () => true,
10
10
  getStepType: () => 'assert',
11
11
  execute: async (payload, stateProvider, eventHandler, logger) => {
12
- const toolParams = payload.toolCall.toolParams;
12
+ const toolParams = payload.toolCall
13
+ .toolParams;
13
14
  if (!payload.find || !payload.contextInfo) {
14
15
  logger.error('RecordAssertElementExecutor requires find and contextInfo');
15
16
  return {
@@ -37,6 +38,6 @@ exports.recordAssertElementExecutor = {
37
38
  elementAttrProp: 'innerText',
38
39
  },
39
40
  };
40
- return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(step, payload.contextInfo, true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
41
+ return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(step, payload.contextInfo, true, undefined, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
41
42
  },
42
43
  };
@@ -6,14 +6,9 @@ const generation_types_1 = require("../../sharedUtils/generation-types");
6
6
  const ExtractDescriptor_1 = require("../../../mablscript/types/ExtractDescriptor");
7
7
  const AssertStep_1 = require("../../../mablscript/steps/AssertStep");
8
8
  const stepExecution_1 = require("../../sharedUtils/stepExecution");
9
- const translateMablscript_1 = require("../../sharedUtils/capture/translateMablscript");
10
- const mablscriptFind_1 = require("../../../mablscriptFind");
11
9
  const stepCapture_1 = require("../../background/capture/stepCapture");
12
10
  exports.recordAssertionExecutor = {
13
- needsFind: (toolCall) => {
14
- const toolParams = toolCall.toolParams;
15
- return isAssertToolParams(toolParams) && !!toolParams.elementBoundingBox;
16
- },
11
+ needsFind: () => false,
17
12
  getStepType: () => 'assert',
18
13
  execute: async (payload, stateProvider, eventHandler, logger) => {
19
14
  const toolParams = payload.toolCall.toolParams;
@@ -23,28 +18,14 @@ exports.recordAssertionExecutor = {
23
18
  success: false,
24
19
  };
25
20
  }
26
- const isElementAssert = !!toolParams.elementBoundingBox;
27
- if (isElementAssert) {
28
- if (!payload.find || !payload.contextInfo) {
29
- logger.error('Record assertion tool executor with element bounding box requires find and context info');
30
- return {
31
- success: false,
32
- };
33
- }
34
- }
35
- if ((0, toolExecutors_1.isFindOneEventMessage)(payload.find)) {
36
- delete payload.find.stepType;
37
- }
38
- const step = (0, toolExecutors_1.isFindOneEventMessage)(payload.find)
39
- ? { ...payload.find, listener: 'mouse-select' }
40
- : {
41
- selectionType: 'viewport',
42
- listener: 'viewport-assert',
43
- findDescriptor: {
44
- type: 'viewport',
45
- },
46
- action: 'record',
47
- };
21
+ const step = {
22
+ selectionType: 'viewport',
23
+ listener: 'viewport-assert',
24
+ findDescriptor: {
25
+ type: 'viewport',
26
+ },
27
+ action: 'record',
28
+ };
48
29
  step.assertion = {
49
30
  assertionType: 'ai_prompt',
50
31
  assertionTarget: 'element',
@@ -54,14 +35,11 @@ exports.recordAssertionExecutor = {
54
35
  },
55
36
  extractionType: ExtractDescriptor_1.ExtractType.EXTRACT_PROMPT,
56
37
  onFailure: AssertStep_1.OnFailure.FailTestAtEnd,
57
- selectionType: isElementAssert ? 'element' : 'viewport',
58
- elementScreenshot: isElementAssert,
38
+ selectionType: 'viewport',
39
+ elementScreenshot: false,
59
40
  };
60
41
  const contextInfo = payload.contextInfo ?? (await stateProvider.getActiveContextInfo());
61
- const findDescriptor = isElementAssert && (0, toolExecutors_1.isFindOneEventMessage)(payload.find)
62
- ?
63
- (0, translateMablscript_1.createFindDescriptor)(payload.find, new mablscriptFind_1.ElementSelectorStore())
64
- : { type: 'viewport' };
42
+ const findDescriptor = { type: 'viewport' };
65
43
  const variables = stateProvider.getVariables();
66
44
  const testAssertionResult = await (0, stepExecution_1.runAIAssertion)(eventHandler, variables, findDescriptor, step.assertion, contextInfo.frameId, `${contextInfo.tabId}`);
67
45
  step.assertion.aiPrompt.criteria =
@@ -74,7 +52,7 @@ exports.recordAssertionExecutor = {
74
52
  success: false,
75
53
  };
76
54
  }
77
- return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(step, contextInfo, true, payload.toolCall.toolParams?.description, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
55
+ return (0, toolExecutors_1.recordStepAndTrackResult)(() => (0, stepCapture_1.recordTrainedStep)(step, contextInfo, true, undefined, stateProvider, eventHandler), 0, stateProvider, eventHandler, logger);
78
56
  },
79
57
  };
80
58
  function isAssertToolParams(toolParams) {
@@ -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
  };
@@ -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
+ }
@@ -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 ?? [])