@mablhq/mabl-cli 2.94.10 → 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.
@@ -15,6 +15,7 @@ exports.getQueryIds = getQueryIds;
15
15
  exports.getSnippetIdsFromJsonFlow = getSnippetIdsFromJsonFlow;
16
16
  exports.getSnippetIdsFromMablscriptFlow = getSnippetIdsFromMablscriptFlow;
17
17
  exports.getSnippetIdsFromApiFlow = getSnippetIdsFromApiFlow;
18
+ exports.getSnippetIdsFromFlow = getSnippetIdsFromFlow;
18
19
  exports.getSnippetIdsFromFlows = getSnippetIdsFromFlows;
19
20
  const esprima_1 = require("esprima");
20
21
  const estraverse_1 = require("estraverse");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mablhq/mabl-cli",
3
- "version": "2.94.10",
3
+ "version": "2.96.5",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "description": "The official mabl command line interface tool",
6
6
  "main": "index.js",
@@ -8,6 +8,7 @@ const mablApi_1 = require("../../mablApi");
8
8
  const generation_types_1 = require("../sharedUtils/generation-types");
9
9
  const mablscript_step_types_1 = require("../sharedUtils/mablscript-step-types");
10
10
  const ExecuteFlowStep_1 = __importDefault(require("../sharedUtils/mablscript/extended/ExecuteFlowStep"));
11
+ const ExecuteStepGroupStep_1 = __importDefault(require("../sharedUtils/mablscript/extended/ExecuteStepGroupStep"));
11
12
  const importer_1 = require("../../mablscript/importer");
12
13
  const chalk = require('chalk');
13
14
  class CliEventHandler {
@@ -97,6 +98,44 @@ class CliEventHandler {
97
98
  completeTask() {
98
99
  console.log('Task completed');
99
100
  }
101
+ moveCursorIntoGroup() {
102
+ this.state.moveCursorIntoGroup();
103
+ }
104
+ moveCursorOutOfGroup() {
105
+ this.state.moveCursorOutOfGroup();
106
+ }
107
+ isInsideStepGroup() {
108
+ return this.state.isInsideStepGroup();
109
+ }
110
+ getNextStepIndex() {
111
+ return this.state.getNextStepIndex();
112
+ }
113
+ setNextStepIndex(index) {
114
+ this.state.setNextStepIndex(index);
115
+ }
116
+ getStepAtPath(path) {
117
+ if (path.length === 0) {
118
+ return undefined;
119
+ }
120
+ let currentSteps = this.state.getSteps();
121
+ let step;
122
+ for (let i = 0; i < path.length; i++) {
123
+ const index = path[i];
124
+ if (index < 0 || index >= currentSteps.length) {
125
+ return undefined;
126
+ }
127
+ step = currentSteps[index];
128
+ if (i < path.length - 1) {
129
+ if (step instanceof ExecuteStepGroupStep_1.default) {
130
+ currentSteps = step.stepsInGroup;
131
+ }
132
+ else {
133
+ return undefined;
134
+ }
135
+ }
136
+ }
137
+ return step;
138
+ }
100
139
  addAgentLogEntry(entry) {
101
140
  switch (entry.type) {
102
141
  case generation_types_1.AgentLogEntryType.ToolExecuted:
@@ -186,7 +225,7 @@ class CliEventHandler {
186
225
  flowInvariantId: flow.invariant_id,
187
226
  flow,
188
227
  });
189
- this.state.addSteps([flowStep]);
228
+ await this.dispatchSteps([flowStep]);
190
229
  }
191
230
  try {
192
231
  const mablSteps = (0, importer_1.parseMablScriptIntoSteps)(flow);
@@ -229,7 +268,23 @@ class CliEventHandler {
229
268
  return Promise.resolve();
230
269
  }
231
270
  async dispatchSteps(steps, options) {
232
- if (options?.index) {
271
+ const cursor = this.state.getNextStepIndex();
272
+ if (cursor.length > 1 && !options?.skipActiveGroupInsertion) {
273
+ const containerPath = cursor.slice(0, -1);
274
+ const stepGroup = this.getStepAtPath(containerPath);
275
+ if ((0, mablscript_step_types_1.isStepGroupStep)(stepGroup)) {
276
+ const insertIdx = cursor[cursor.length - 1];
277
+ stepGroup.stepsInGroup.splice(insertIdx, 0, ...steps);
278
+ this.state.setNextStepIndex([
279
+ ...containerPath,
280
+ insertIdx + steps.length,
281
+ ]);
282
+ }
283
+ else {
284
+ this.state.addSteps(steps);
285
+ }
286
+ }
287
+ else if (options?.index) {
233
288
  this.state.insertStepsAtCursor(steps);
234
289
  }
235
290
  else {
@@ -239,6 +294,12 @@ class CliEventHandler {
239
294
  console.log(` ${options.description}`);
240
295
  }
241
296
  for (const step of steps) {
297
+ if ((0, mablscript_step_types_1.isStepGroupStep)(step) || (0, mablscript_step_types_1.isStepWithReusableFlow)(step)) {
298
+ if (this.verbose) {
299
+ console.log(` Step ${step.stepType}: container step, skipping execution`);
300
+ }
301
+ continue;
302
+ }
242
303
  this.resetReplayResponse();
243
304
  const result = await this.runSingleStep(step);
244
305
  if (this.verbose) {
@@ -251,6 +312,12 @@ class CliEventHandler {
251
312
  level: result.level,
252
313
  });
253
314
  }
315
+ if (options?.skipActiveGroupInsertion && steps.length > 0) {
316
+ const lastStep = steps[steps.length - 1];
317
+ if ((0, mablscript_step_types_1.isStepGroupStep)(lastStep) && lastStep.stepsInGroup.length === 0) {
318
+ this.moveCursorIntoGroup();
319
+ }
320
+ }
254
321
  }
255
322
  syncVariablesFromExecutionContext() {
256
323
  const executionVars = this.stepExecutor.getVariables();
@@ -2,10 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CliStateProvider = void 0;
4
4
  class CliStateProvider {
5
- constructor(state, trainingContext, flowCache) {
5
+ constructor(state, trainingContext, flowCache, accountFeatures) {
6
6
  this.state = state;
7
7
  this.trainingContext = trainingContext;
8
8
  this.flowCache = flowCache;
9
+ this.accountFeatures = accountFeatures;
9
10
  }
10
11
  getTestGenerationStatus() {
11
12
  return this.state.getStatus();
@@ -121,5 +122,8 @@ class CliStateProvider {
121
122
  clearArtifacts() {
122
123
  this.state.clearArtifacts();
123
124
  }
125
+ hasStepGroupsFeature() {
126
+ return this.accountFeatures?.hasStepGroups() ?? false;
127
+ }
124
128
  }
125
129
  exports.CliStateProvider = CliStateProvider;
@@ -104,6 +104,31 @@ class CliTestGenerationState {
104
104
  setActiveURL(url) {
105
105
  this.activeURL = url;
106
106
  }
107
+ moveCursorIntoGroup() {
108
+ const lastIndex = this.nextStepIndex[this.nextStepIndex.length - 1];
109
+ if (lastIndex > 0) {
110
+ this.nextStepIndex = [
111
+ ...this.nextStepIndex.slice(0, -1),
112
+ lastIndex - 1,
113
+ 0,
114
+ ];
115
+ }
116
+ else {
117
+ this.nextStepIndex = [...this.nextStepIndex, 0];
118
+ }
119
+ }
120
+ moveCursorOutOfGroup() {
121
+ if (this.nextStepIndex.length > 1) {
122
+ const parentPath = this.nextStepIndex.slice(0, -1);
123
+ this.nextStepIndex = [
124
+ ...parentPath.slice(0, -1),
125
+ parentPath[parentPath.length - 1] + 1,
126
+ ];
127
+ }
128
+ }
129
+ isInsideStepGroup() {
130
+ return this.nextStepIndex.length > 1;
131
+ }
107
132
  getVariables() {
108
133
  return this.variables;
109
134
  }
@@ -8,9 +8,9 @@ exports.buildTestInfoArtifact = buildTestInfoArtifact;
8
8
  exports.buildAllArtifacts = buildAllArtifacts;
9
9
  const variable_utils_1 = require("../sharedUtils/variable-utils");
10
10
  const humanize_1 = require("../sharedUtils/mablscript/humanize");
11
- const mablscript_step_types_1 = require("../sharedUtils/mablscript-step-types");
12
11
  const type_utils_1 = require("../sharedUtils/type-utils");
13
12
  const contextBuilder_1 = require("../sharedUtils/contextBuilder");
13
+ const mablscript_step_types_1 = require("../sharedUtils/mablscript-step-types");
14
14
  const uuid_1 = require("uuid");
15
15
  function createJsonArtifact(id, name, description, value) {
16
16
  return {
@@ -24,18 +24,42 @@ function createJsonArtifact(id, name, description, value) {
24
24
  },
25
25
  };
26
26
  }
27
- function processStepsWithDescriptions(steps, variables, cursorIndex, state) {
27
+ function processStepsWithDescriptions(steps, variables, cursorIndex, state, depth = 0) {
28
28
  const stepList = [];
29
29
  const tasks = [];
30
30
  let currentTaskIndex = -1;
31
31
  let cursorFound = false;
32
+ const cursorAtThisDepth = cursorIndex[depth];
33
+ const cursorIsAtThisDepth = cursorIndex.length === depth + 1;
32
34
  steps.forEach((step, index) => {
33
- const isAtCursor = cursorIndex.length === 1 && cursorIndex[0] === index;
35
+ const isAtCursor = cursorIsAtThisDepth && cursorAtThisDepth === index;
34
36
  if (isAtCursor && !cursorFound) {
35
37
  cursorFound = true;
36
38
  }
37
- const parsedTask = (0, contextBuilder_1.parseTaskFromEchoStep)(step);
38
- if ((0, mablscript_step_types_1.isStepWithReusableFlow)(step) &&
39
+ if ((0, mablscript_step_types_1.isStepGroupStep)(step)) {
40
+ const groupDescription = step.description ?? 'Unnamed Step Group';
41
+ stepList.push(`Start task: ${groupDescription}`);
42
+ tasks.push(groupDescription);
43
+ const taskIsBeforeCursor = cursorAtThisDepth > index;
44
+ if (taskIsBeforeCursor) {
45
+ currentTaskIndex++;
46
+ }
47
+ const cursorIsInsideThisGroup = cursorIndex.length > depth + 1 && cursorAtThisDepth === index;
48
+ if (cursorIsInsideThisGroup) {
49
+ const nestedResult = processStepsWithDescriptions(step.stepsInGroup, variables, cursorIndex, state, depth + 1);
50
+ stepList.push(...nestedResult.stepList);
51
+ if (nestedResult.cursorFound) {
52
+ cursorFound = true;
53
+ }
54
+ }
55
+ else {
56
+ step.stepsInGroup.forEach((nestedStep) => {
57
+ stepList.push((0, humanize_1.humanizeStepDescription)(nestedStep, variables));
58
+ });
59
+ }
60
+ stepList.push(`End task: ${groupDescription}`);
61
+ }
62
+ else if ((0, mablscript_step_types_1.isStepWithReusableFlow)(step) &&
39
63
  step.flow &&
40
64
  !(0, type_utils_1.isAutoLoginFlow)(step.flow)) {
41
65
  const flowName = step.flow.description ?? 'Unknown flow';
@@ -48,20 +72,16 @@ function processStepsWithDescriptions(steps, variables, cursorIndex, state) {
48
72
  stepList.push(`End execute flow: ${flowName}`);
49
73
  }
50
74
  else {
51
- const stepDescription = parsedTask
52
- ? `${parsedTask}`
53
- : (0, humanize_1.humanizeStepDescription)(step, variables);
54
- stepList.push(stepDescription);
55
- }
56
- if (parsedTask) {
57
- tasks.push(parsedTask);
58
- const wasBeforeCursor = !cursorFound && !isAtCursor;
59
- if (wasBeforeCursor) {
60
- currentTaskIndex++;
61
- }
75
+ stepList.push((0, humanize_1.humanizeStepDescription)(step, variables));
62
76
  }
63
77
  });
64
- return { stepList, tasks, currentTaskIndex };
78
+ if (!cursorFound &&
79
+ cursorIsAtThisDepth &&
80
+ cursorAtThisDepth === steps.length) {
81
+ cursorFound = true;
82
+ stepList.push(contextBuilder_1.CURSOR_MARKER);
83
+ }
84
+ return { stepList, tasks, currentTaskIndex, cursorFound };
65
85
  }
66
86
  function buildVariablesMap(variables, cursorIndex) {
67
87
  const variablesList = (0, variable_utils_1.getUsableVariablesAsList)(variables, cursorIndex);
@@ -80,16 +100,20 @@ function buildTestExecutionStateArtifact(options) {
80
100
  const steps = state.getSteps();
81
101
  const variables = state.getVariables();
82
102
  const variablesMap = buildVariablesMap(variables, cursorIndex);
83
- const { stepList, tasks, currentTaskIndex } = processStepsWithDescriptions(steps, variables, cursorIndex, state);
103
+ const { stepList, tasks, currentTaskIndex, cursorFound } = processStepsWithDescriptions(steps, variables, cursorIndex, state);
104
+ if (!cursorFound) {
105
+ stepList.push(contextBuilder_1.CURSOR_MARKER);
106
+ }
84
107
  const lastToolsExecuted = state.getLastToolsExecuted();
85
108
  const lastTaskStatus = lastToolsExecuted?.map((tool) => ({
86
109
  success: tool.toolResult?.success ?? false,
87
110
  steps_created: tool.toolResult?.createdStepsInfo?.map((info) => info.humanizedStep.step) ?? [],
88
111
  action: tool.toolCall?.toolName,
89
112
  })) ?? [];
113
+ const flattenedCursorPosition = stepList.indexOf(contextBuilder_1.CURSOR_MARKER);
90
114
  const testExecutionState = {
91
115
  fullStepList: stepList,
92
- cursorPosition: cursorIndex[0] ?? 0,
116
+ cursorPosition: flattenedCursorPosition >= 0 ? flattenedCursorPosition : stepList.length,
93
117
  currentTaskIndex: tasks.length === 0 ? 0 : currentTaskIndex,
94
118
  variables: variablesMap,
95
119
  lastTaskStatus,
@@ -47,6 +47,8 @@ const CliEventHandler_1 = require("./CliEventHandler");
47
47
  const ViewportStep_1 = __importDefault(require("../sharedUtils/mablscript/canonical/ViewportStep"));
48
48
  const VisitUrlStep_1 = __importDefault(require("../sharedUtils/mablscript/canonical/VisitUrlStep"));
49
49
  const domUtil_1 = require("../../domUtil");
50
+ const mablscript_step_types_1 = require("../sharedUtils/mablscript-step-types");
51
+ const humanize_1 = require("../sharedUtils/mablscript/humanize");
50
52
  const sessionHelpers_1 = require("./sessionHelpers");
51
53
  const chalk = require('chalk');
52
54
  function createReadlineInterface() {
@@ -62,6 +64,16 @@ function printStartupInfo(resolvedSession, headless) {
62
64
  console.log(chalk.gray(' Headless:'), chalk.white(String(headless)));
63
65
  console.log();
64
66
  }
67
+ function printStepsRecursively(steps, variables, prefix = '', indent = ' ') {
68
+ steps.forEach((step, index) => {
69
+ const stepNumber = prefix ? `${prefix}.${index + 1}` : `${index + 1}`;
70
+ const description = step.annotations?.description || (0, humanize_1.humanizeStepDescription)(step, variables);
71
+ console.log(chalk.gray(`${indent}${stepNumber}.`), chalk.white(description));
72
+ if ((0, mablscript_step_types_1.isStepGroupStep)(step) && step.stepsInGroup.length > 0) {
73
+ printStepsRecursively(step.stepsInGroup, variables, stepNumber, indent + ' ');
74
+ }
75
+ });
76
+ }
65
77
  function createResultProcessor() {
66
78
  return (result) => {
67
79
  const isError = result.status === 'failed';
@@ -135,7 +147,7 @@ async function runAgenticGeneration(options) {
135
147
  return state;
136
148
  },
137
149
  createTrainingContext: (page, browser, onNewTabDetected) => new CliTrainingContext_1.CliTrainingContext({ page, browser, onNewTabDetected }),
138
- createStateProvider: (state, trainingContext, flowCache) => new CliStateProvider_1.CliStateProvider(state, trainingContext, flowCache),
150
+ createStateProvider: (state, trainingContext, flowCache, accountFeatures) => new CliStateProvider_1.CliStateProvider(state, trainingContext, flowCache, accountFeatures),
139
151
  createEventHandler: (opts) => new CliEventHandler_1.CliEventHandler({
140
152
  state: opts.state,
141
153
  trainingContext: opts.trainingContext,
@@ -148,11 +160,9 @@ async function runAgenticGeneration(options) {
148
160
  processResult: createResultProcessor(),
149
161
  });
150
162
  const result = await runner.run();
151
- if (result.steps.length > 0) {
163
+ if (result.rawSteps.length > 0) {
152
164
  console.log(chalk.bold('Generated Steps:'));
153
- result.steps.forEach((step, index) => {
154
- console.log(chalk.gray(` ${index + 1}.`), chalk.white(step));
155
- });
165
+ printStepsRecursively(result.rawSteps, result.variables);
156
166
  console.log();
157
167
  }
158
168
  if (result.saveResult) {
@@ -102,13 +102,14 @@ class AgenticGenerationRunner {
102
102
  }
103
103
  async createBrowserAndNavigate() {
104
104
  this.logger.info('Creating browser and navigating to URL');
105
- const { testContext } = await (0, createTrainingTestContext_1.createTrainingTestContext)({
105
+ const { testContext, accountFeatures } = await (0, createTrainingTestContext_1.createTrainingTestContext)({
106
106
  workspaceId: this.config.workspaceId,
107
107
  applicationId: this.config.applicationId,
108
108
  url: this.config.url,
109
109
  apiClient: this.config.apiClient,
110
110
  idPrefix: 'gen',
111
111
  });
112
+ this.accountFeatures = accountFeatures;
112
113
  const browserConfig = {
113
114
  height: 900,
114
115
  width: 1280,
@@ -156,7 +157,7 @@ class AgenticGenerationRunner {
156
157
  });
157
158
  });
158
159
  await this.trainingContext.initialize();
159
- this.stateProvider = this.providers.createStateProvider(this.state, this.trainingContext, this.flowCache);
160
+ this.stateProvider = this.providers.createStateProvider(this.state, this.trainingContext, this.flowCache, this.accountFeatures);
160
161
  this.eventHandler = this.providers.createEventHandler({
161
162
  state: this.state,
162
163
  trainingContext: this.trainingContext,
@@ -243,6 +244,7 @@ class AgenticGenerationRunner {
243
244
  trainingSessionId: loopResult.trainingSessionId,
244
245
  status: loopResult.status,
245
246
  rawSteps: loopResult.steps,
247
+ variables: loopResult.variables,
246
248
  error: loopResult.pendingAskForHelp.question,
247
249
  };
248
250
  }
@@ -255,6 +257,7 @@ class AgenticGenerationRunner {
255
257
  trainingSessionId: loopResult.trainingSessionId,
256
258
  status: loopResult.status,
257
259
  rawSteps: loopResult.steps,
260
+ variables: loopResult.variables,
258
261
  error: loopResult.status === generation_types_1.TestGenerationStatus.Failed
259
262
  ? 'Generation failed'
260
263
  : undefined,
@@ -270,6 +273,7 @@ class AgenticGenerationRunner {
270
273
  trainingSessionId: this.state?.getTrainingSessionId() ?? '',
271
274
  status: generation_types_1.TestGenerationStatus.Failed,
272
275
  rawSteps: [],
276
+ variables: this.state?.getVariables() ?? {},
273
277
  };
274
278
  }
275
279
  async cleanup() {
@@ -514,7 +514,7 @@ class TestGenerationOrchestrator {
514
514
  const cursorPosition = cursorIndex[0];
515
515
  let hasStartTaskBeforeCursor = false;
516
516
  for (let i = 0; i < cursorPosition && i < steps.length; i++) {
517
- const parsedTask = (0, contextBuilder_1.parseTaskFromEchoStep)(steps[i]);
517
+ const parsedTask = (0, contextBuilder_1.parseTaskFromStep)(steps[i]) ?? (0, contextBuilder_1.parseTaskFromEchoStep)(steps[i]);
518
518
  if (parsedTask) {
519
519
  hasStartTaskBeforeCursor = true;
520
520
  break;
@@ -556,8 +556,13 @@ class TestGenerationOrchestrator {
556
556
  return;
557
557
  }
558
558
  this.logger.info(`Adding initial start task step: ${firstTaskDescription}`);
559
- const startTaskResult = (0, RecordStartTaskExecutor_1.recordStartTaskStep)(firstTaskDescription);
560
- await this.eventHandler.dispatchSteps(startTaskResult.steps);
559
+ const useStepGroups = this.stateProvider.hasStepGroupsFeature();
560
+ const startTaskResult = useStepGroups
561
+ ? (0, RecordStartTaskExecutor_1.recordStartTaskStep)(firstTaskDescription)
562
+ : (0, RecordStartTaskExecutor_1.recordStartTaskEchoStep)(firstTaskDescription);
563
+ await this.eventHandler.dispatchSteps(startTaskResult.steps, {
564
+ skipActiveGroupInsertion: useStepGroups,
565
+ });
561
566
  }
562
567
  }
563
568
  exports.TestGenerationOrchestrator = TestGenerationOrchestrator;
@@ -1,12 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.completeTaskExecutor = void 0;
4
- const mablApi_1 = require("../../../mablApi");
5
4
  const RecordStartTaskExecutor_1 = require("./RecordStartTaskExecutor");
6
5
  const contextBuilder_1 = require("../../sharedUtils/contextBuilder");
7
6
  exports.completeTaskExecutor = {
8
7
  needsFind: () => false,
9
- getStepType: () => mablApi_1.ExecuteToolName.CompleteTask,
8
+ getStepType: () => 'complete_task',
10
9
  execute: async (payload, stateProvider, eventHandler, logger) => {
11
10
  const lastToolsExecuted = stateProvider.getLastToolsExecuted();
12
11
  const someStepFailed = lastToolsExecuted?.some((tool) => !!tool.generatedSteps && !tool.toolResult.success);
@@ -17,7 +16,11 @@ exports.completeTaskExecutor = {
17
16
  errorMessage: 'Cannot complete task because a generated step failed.',
18
17
  });
19
18
  }
20
- const { isLastTask, nextTaskDescription, newTaskIndex } = checkTaskStatus(stateProvider, logger);
19
+ const useStepGroups = stateProvider.hasStepGroupsFeature();
20
+ if (useStepGroups) {
21
+ eventHandler.moveCursorOutOfGroup();
22
+ }
23
+ const { isLastTask, nextTaskDescription, newTaskIndex } = checkTaskStatus(stateProvider, eventHandler, logger);
21
24
  eventHandler.completeTask();
22
25
  const stopCondition = payload.session.stopCondition;
23
26
  if (stopCondition === 'generated-task') {
@@ -41,8 +44,17 @@ exports.completeTaskExecutor = {
41
44
  if (nextTaskDescription) {
42
45
  logger.info(`Creating start task step for next task: ${nextTaskDescription}`);
43
46
  try {
44
- const startTaskResult = (0, RecordStartTaskExecutor_1.recordStartTaskStep)(nextTaskDescription);
45
- await eventHandler.dispatchSteps(startTaskResult.steps);
47
+ const startTaskResult = useStepGroups
48
+ ? (0, RecordStartTaskExecutor_1.recordStartTaskStep)(nextTaskDescription)
49
+ : (0, RecordStartTaskExecutor_1.recordStartTaskEchoStep)(nextTaskDescription);
50
+ await eventHandler.dispatchSteps(startTaskResult.steps, {
51
+ skipActiveGroupInsertion: useStepGroups,
52
+ });
53
+ if (useStepGroups) {
54
+ if (!eventHandler.isInsideStepGroup()) {
55
+ eventHandler.moveCursorIntoGroup();
56
+ }
57
+ }
46
58
  }
47
59
  catch (error) {
48
60
  logger.error('Error creating next start task step:', error);
@@ -59,7 +71,7 @@ exports.completeTaskExecutor = {
59
71
  });
60
72
  },
61
73
  };
62
- function checkTaskStatus(stateProvider, logger) {
74
+ function checkTaskStatus(stateProvider, eventHandler, logger) {
63
75
  const testOutlineArtifact = stateProvider.getArtifact('test_outline');
64
76
  const simpleOutlineArtifact = stateProvider.getArtifact('simple_test_outline');
65
77
  const hasTestOutline = testOutlineArtifact && testOutlineArtifact.artifact_type === 'inline';
@@ -71,33 +83,33 @@ function checkTaskStatus(stateProvider, logger) {
71
83
  if (hasTestOutline) {
72
84
  const data = testOutlineArtifact.artifact_data?.value;
73
85
  if (data?.tasks) {
74
- return getTaskInfo(data, stateProvider, logger);
86
+ return getTaskInfo(data, stateProvider, eventHandler, logger);
75
87
  }
76
88
  logger.warn('test_outline artifact exists but has no data or tasks');
77
89
  }
78
90
  if (hasSimpleOutline) {
79
91
  const data = simpleOutlineArtifact.artifact_data?.value;
80
92
  if (data?.tasks) {
81
- return getTaskInfo(data, stateProvider, logger);
93
+ return getTaskInfo(data, stateProvider, eventHandler, logger);
82
94
  }
83
95
  logger.warn('simple_test_outline artifact exists but has no data or tasks');
84
96
  }
85
97
  logger.warn('Outline artifacts found but contain no valid task data, assuming not last task');
86
98
  return { isLastTask: false };
87
99
  }
88
- function getTaskInfo(outline, stateProvider, logger) {
100
+ function getTaskInfo(outline, stateProvider, eventHandler, logger) {
89
101
  if (!outline?.tasks || outline.tasks.length === 0) {
90
102
  logger.info('No tasks in outline, not ending test');
91
103
  return { isLastTask: false };
92
104
  }
93
105
  const steps = stateProvider.getSteps();
94
- const cursorIndex = stateProvider.getNextStepIndex();
106
+ const cursorIndex = eventHandler.getNextStepIndex();
95
107
  let currentTaskIndex = 0;
96
108
  if (cursorIndex.length === 1) {
97
109
  const cursorPosition = cursorIndex[0];
98
110
  let taskCount = 0;
99
111
  for (let i = 0; i < cursorPosition && i < steps.length; i++) {
100
- const parsedTask = (0, contextBuilder_1.parseTaskFromEchoStep)(steps[i]);
112
+ const parsedTask = (0, contextBuilder_1.parseTaskFromStep)(steps[i]) ?? (0, contextBuilder_1.parseTaskFromEchoStep)(steps[i]);
101
113
  if (parsedTask) {
102
114
  taskCount++;
103
115
  }
@@ -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
  };
@@ -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) {