@mablhq/mabl-cli 2.105.4 → 2.105.14

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/index.d.ts CHANGED
@@ -2,6 +2,12 @@ import {BrowserContext, Locator, Page, Frame} from 'playwright-core';
2
2
  import {TestType, Download} from '@playwright/test';
3
3
 
4
4
  declare module '@mablhq/mabl-cli' {
5
+ export type SnippetLogLevel = 'info' | 'warn' | 'error';
6
+ export interface SnippetLogLine {
7
+ message: string;
8
+ level: SnippetLogLevel;
9
+ }
10
+
5
11
  export type AuthServerPolicy = 'off' | 'none' | 'all';
6
12
  export enum TestResultStatus {
7
13
  passed = 'passed',
@@ -299,6 +305,12 @@ export type AgenticGenerationOptions =
299
305
  export interface AgenticGenerationResult {
300
306
  success: boolean;
301
307
  error?: string;
308
+ /**
309
+ * The original error when an unexpected infrastructure failure occurred
310
+ * (e.g., browser failed to launch, API returned 5xx during setup).
311
+ * Callers can rethrow this to signal a fatal job failure for monitoring.
312
+ */
313
+ fatalError?: Error;
302
314
  steps: string[];
303
315
  trainingSessionId: string;
304
316
  rawSteps: any[];
@@ -119,7 +119,9 @@ class MablStep extends MablAction_1.MablAction {
119
119
  }
120
120
  toLineDiffFormat(_omitStepId = false) {
121
121
  const lineDiffProperties = {
122
- annotation: this.annotation,
122
+ annotation: this.annotation && Object.keys(this.annotation).length > 0
123
+ ? this.annotation
124
+ : undefined,
123
125
  disabled: this.isDisabled(),
124
126
  mablscript: this.toMablscript(),
125
127
  };
@@ -85,7 +85,7 @@ class MablStepV2 extends MablStep_1.MablStep {
85
85
  return false;
86
86
  }
87
87
  getResolvedDescription() {
88
- return this.annotation?.description ?? this.getDescription();
88
+ return this.annotation?.description || this.getDescription();
89
89
  }
90
90
  toLineDiffFormat(omitStepId = false) {
91
91
  const descriptor = { ...this.toStepDescriptor() };
@@ -93,7 +93,9 @@ class MablStepV2 extends MablStep_1.MablStep {
93
93
  delete descriptor.id;
94
94
  }
95
95
  const lineDiffProperties = {
96
- annotation: this.annotation,
96
+ annotation: this.annotation && Object.keys(this.annotation).length > 0
97
+ ? this.annotation
98
+ : undefined,
97
99
  disabled: this.isDisabled(),
98
100
  descriptor,
99
101
  };
@@ -130,8 +130,11 @@ class FindAction extends MablAction_1.MablAction {
130
130
  if (findType === 'find_cookie') {
131
131
  return new FindAction(findType, [findTarget]);
132
132
  }
133
+ const primarySelector = findTarget && typeof findTarget === 'object' && 'selector' in findTarget
134
+ ? findTarget.selector
135
+ : findTarget;
133
136
  return new FindAction(findType, [
134
- findTarget,
137
+ primarySelector,
135
138
  stepArgs.find.foundElementSelectors,
136
139
  findOptions,
137
140
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mablhq/mabl-cli",
3
- "version": "2.105.4",
3
+ "version": "2.105.14",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "The official mabl command line interface tool",
6
6
  "main": "index.js",
@@ -193,6 +193,7 @@ async function runAgenticGeneration(options) {
193
193
  steps: result.steps,
194
194
  trainingSessionId: result.trainingSessionId,
195
195
  error: result.error,
196
+ fatalError: result.fatalError,
196
197
  rawSteps: result.rawSteps,
197
198
  saveResult: result.saveResult,
198
199
  };
@@ -110,7 +110,7 @@ class AgenticGenerationRunner {
110
110
  }
111
111
  : undefined;
112
112
  if (!pendingToolCall) {
113
- this.logger.info('No pending tool call to finalize — session may have ended cleanly');
113
+ await this.resolveOrphanedToolCalls(sessionId, loopResult, saveResult);
114
114
  return;
115
115
  }
116
116
  const savedSuccessfully = saveResult?.success && saveResult.testId;
@@ -148,6 +148,48 @@ class AgenticGenerationRunner {
148
148
  this.logger.error('Failed to finalize agent session', error instanceof Error ? error : undefined);
149
149
  }
150
150
  }
151
+ async resolveOrphanedToolCalls(sessionId, loopResult, saveResult) {
152
+ const session = await this.config.apiClient.getAgentSession(sessionId);
153
+ const allToolCalls = (0, messageConversion_1.extractToolCallsFromMessages)(session.messages, this.logger);
154
+ const clientToolCalls = (0, messageConversion_1.filterClientSideToolCalls)(allToolCalls);
155
+ const unansweredToolCalls = (0, messageConversion_1.filterToolCallsWithoutOutputs)(clientToolCalls, session.messages);
156
+ const savedSuccessfully = saveResult?.success && saveResult.testId;
157
+ const artifacts = [];
158
+ if (savedSuccessfully) {
159
+ artifacts.push({
160
+ artifact_type: 'remote',
161
+ entity_kind: mablApi_1.ArtifactEntityKind.Test,
162
+ entity_id: saveResult.testId,
163
+ entity_name: saveResult.savedTest?.name,
164
+ });
165
+ }
166
+ if (unansweredToolCalls.length > 0) {
167
+ this.logger.info(`Found ${unansweredToolCalls.length} unanswered tool call(s) in session — responding with error`);
168
+ const errorMessage = savedSuccessfully
169
+ ? 'Test saved'
170
+ : loopResult.failureReason ?? 'Generation failed';
171
+ const toolOutputParts = unansweredToolCalls.map((tc) => (0, messageConversion_1.createToolOutputMessagePart)({
172
+ toolCallId: tc.id,
173
+ toolName: tc.name,
174
+ result: {
175
+ success: !!savedSuccessfully,
176
+ testId: saveResult?.testId,
177
+ testUrl: saveResult?.testUrl,
178
+ message: errorMessage,
179
+ },
180
+ }));
181
+ const toolOutputMessage = (0, messageConversion_1.createToolOutputMessage)(toolOutputParts);
182
+ await this.config.apiClient.appendAgentSessionMessage(sessionId, toolOutputMessage, artifacts.length > 0 ? artifacts : undefined);
183
+ }
184
+ else if (artifacts.length > 0) {
185
+ this.logger.info(`No pending tool calls — associating saved test ${saveResult.testId} with session ${sessionId}`);
186
+ const message = (0, messageConversion_1.createErrorTextMessage)(loopResult.failureReason ?? 'Generation ended');
187
+ await this.config.apiClient.appendAgentSessionMessage(sessionId, message, artifacts);
188
+ }
189
+ else {
190
+ this.logger.info('No pending tool calls to finalize — session may have ended cleanly');
191
+ }
192
+ }
151
193
  async createBrowserAndNavigate() {
152
194
  this.logger.info('Creating browser and navigating to URL');
153
195
  const { testContext, accountFeatures } = await (0, createTrainingTestContext_1.createTrainingTestContext)({
@@ -339,6 +381,7 @@ class AgenticGenerationRunner {
339
381
  return {
340
382
  success: false,
341
383
  error: errorMessage,
384
+ fatalError: error instanceof Error ? error : new Error(errorMessage),
342
385
  steps: [],
343
386
  trainingSessionId: this.state?.getTrainingSessionId() ?? '',
344
387
  status: generation_types_1.TestGenerationStatus.Failed,
@@ -425,7 +425,11 @@ class MablscriptImporter {
425
425
  }
426
426
  }
427
427
  convertStepGroupStep(mablStepGroup, isMobileFlow) {
428
- const convertedSteps = mablStepGroup.steps.map((nestedMablStep) => this.convertMablStepToTrainerStep(nestedMablStep, isMobileFlow));
428
+ const convertedSteps = mablStepGroup.steps.map((nestedMablStep) => {
429
+ const step = this.convertMablStepToTrainerStep(nestedMablStep, isMobileFlow);
430
+ step.setDisabled(nestedMablStep.isDisabled());
431
+ return step;
432
+ });
429
433
  const intentDescription = mablStepGroup.intent?.description;
430
434
  const stepGroup = new ExecuteStepGroupStep_1.default(convertedSteps, intentDescription);
431
435
  const existingStepId = mablStepGroup.stepId();
@@ -26,6 +26,7 @@ function parseStepToV2Format(step, isMablscriptFlow, variables) {
26
26
  },
27
27
  actionCode: StepGroupActionCode,
28
28
  id: stepId,
29
+ ...(step.disabled ? { disabled: true } : {}),
29
30
  },
30
31
  };
31
32
  }