@flowriki/agent 0.1.0-beta.23 → 0.1.0-beta.24
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/{chunk-5J5D7IIT.js → chunk-EBT7VSPY.js} +239 -10
- package/dist/cli.js +1 -1
- package/dist/engine.js +1 -1
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import os from "os";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
8
|
import { spawnSync } from "child_process";
|
|
9
|
-
var AGENT_VERSION = "0.1.0-beta.
|
|
9
|
+
var AGENT_VERSION = "0.1.0-beta.24";
|
|
10
10
|
async function prepareBrowsers() {
|
|
11
11
|
if (browsersReady()) {
|
|
12
12
|
return { ok: true, already: true, message: "chromium is already installed" };
|
|
@@ -135,7 +135,7 @@ function forgetConnection(service, env = process.env) {
|
|
|
135
135
|
}
|
|
136
136
|
var fingerprint = (secret) => crypto2.createHash("sha256").update(secret).digest("hex").slice(0, 12);
|
|
137
137
|
|
|
138
|
-
// ../contracts/dist/chunk-
|
|
138
|
+
// ../contracts/dist/chunk-MQTBBCDK.js
|
|
139
139
|
import { z } from "zod";
|
|
140
140
|
var PROTOCOL_VERSION = 1;
|
|
141
141
|
var PAIRING_CODE_TTL_MS = 5 * 60 * 1e3;
|
|
@@ -290,7 +290,10 @@ var AGENT_FEATURES = /* @__PURE__ */ new Set([
|
|
|
290
290
|
"authentication.v1",
|
|
291
291
|
/** More than one participant, each with a browser session of its own —
|
|
292
292
|
* which also covers starting one over and sharing a captured output. */
|
|
293
|
-
"actors.v1"
|
|
293
|
+
"actors.v1",
|
|
294
|
+
/** Replaying other flows' steps before a recording starts capturing, so a
|
|
295
|
+
* flow can be recorded from where its prerequisites leave the browser. */
|
|
296
|
+
"prerequisites.v1"
|
|
294
297
|
]);
|
|
295
298
|
var AgentMessageSchema = z.discriminatedUnion("type", [
|
|
296
299
|
AckSchema,
|
|
@@ -458,7 +461,7 @@ import path7 from "path";
|
|
|
458
461
|
// ../engine-playwright/dist/index.js
|
|
459
462
|
import path3 from "path";
|
|
460
463
|
|
|
461
|
-
// ../test-model/dist/chunk-
|
|
464
|
+
// ../test-model/dist/chunk-TSFRTYLG.js
|
|
462
465
|
import { z as z3 } from "zod";
|
|
463
466
|
var LocatorOverrideSchema = z3.object({
|
|
464
467
|
strategy: z3.enum(["css", "xpath", "id", "testId", "text", "label", "placeholder", "altText", "title"]),
|
|
@@ -759,6 +762,12 @@ var ActorDefinitionSchema = z3.object({
|
|
|
759
762
|
name: z3.string().min(1),
|
|
760
763
|
startSignedIn: z3.object({ profileId: z3.string().min(1), accountId: z3.string().optional() }).strict().optional()
|
|
761
764
|
}).strict();
|
|
765
|
+
var FlowSignInSchema = z3.object({
|
|
766
|
+
profileId: z3.string().min(1),
|
|
767
|
+
accountId: z3.string().optional(),
|
|
768
|
+
from: z3.enum(["loginPage", "here"]).optional()
|
|
769
|
+
}).strict();
|
|
770
|
+
var FlowPrerequisitesSchema = z3.array(z3.object({ flowId: z3.string().min(1) }).strict());
|
|
762
771
|
var CURRENT_SCHEMA_VERSION = 5;
|
|
763
772
|
var FlowDocumentSchema = z3.object({
|
|
764
773
|
schemaVersion: z3.literal(CURRENT_SCHEMA_VERSION),
|
|
@@ -800,6 +809,24 @@ var FlowDocumentSchema = z3.object({
|
|
|
800
809
|
path: z3.string().optional(),
|
|
801
810
|
actors: z3.array(ActorDefinitionSchema).optional(),
|
|
802
811
|
defaultActorId: z3.string().optional(),
|
|
812
|
+
/** SIGN IN FIRST: the account this flow starts as, before anything else runs.
|
|
813
|
+
*
|
|
814
|
+
* A setting rather than step one, which is what it used to be saved as. As a
|
|
815
|
+
* step it could not be switched off without deleting it, and a flow reused
|
|
816
|
+
* as somebody else's prerequisite could not tell "my own sign-in" from a
|
|
817
|
+
* sign-in that is part of what it tests. `parseFlowDocument` lifts an old
|
|
818
|
+
* step one into this field, so both spellings read the same. A reference to
|
|
819
|
+
* a profile, never a copy of its steps. */
|
|
820
|
+
signIn: FlowSignInSchema.optional(),
|
|
821
|
+
/** Flows replayed, in this order, after signing in and before this flow's
|
|
822
|
+
* own steps — to reach the state it starts from.
|
|
823
|
+
*
|
|
824
|
+
* LINKS, NOT COPIES: re-record "Save basic info" once and every flow that
|
|
825
|
+
* starts after it follows. Each runs WITHOUT its own sign-in; this flow's
|
|
826
|
+
* is the only one. Explicit and flat — nothing here pulls in a
|
|
827
|
+
* prerequisite's prerequisites at run time, so what runs is exactly this
|
|
828
|
+
* list. The editor fills those in when a flow is added. */
|
|
829
|
+
prerequisites: FlowPrerequisitesSchema.optional(),
|
|
803
830
|
/** Bumped on every save. An edit carries the revision it was made against,
|
|
804
831
|
* so a save built on a stale copy is refused instead of overwriting work
|
|
805
832
|
* somebody else — or a debug session on the same machine — has since done.
|
|
@@ -895,8 +922,19 @@ function parseFlowDocument(input) {
|
|
|
895
922
|
version += 1;
|
|
896
923
|
raw.schemaVersion = version;
|
|
897
924
|
}
|
|
925
|
+
liftSignInFirst(raw);
|
|
898
926
|
return FlowDocumentSchema.parse(raw);
|
|
899
927
|
}
|
|
928
|
+
var SIGN_IN_FIRST_STEP_ID = "sign-in-first";
|
|
929
|
+
function liftSignInFirst(raw) {
|
|
930
|
+
const first = raw.steps?.[0];
|
|
931
|
+
const auth = first?.auth;
|
|
932
|
+
if (!first || first.type !== "signIn" || first.disabled === true || first.actorId !== void 0) return;
|
|
933
|
+
if (!auth || typeof auth.profileId !== "string" || !auth.profileId) return;
|
|
934
|
+
if (raw["signIn"] !== void 0 || Array.isArray(raw["actors"]) && raw["actors"].length > 0) return;
|
|
935
|
+
raw["signIn"] = auth;
|
|
936
|
+
raw.steps = raw.steps.slice(1);
|
|
937
|
+
}
|
|
900
938
|
|
|
901
939
|
// ../test-model/dist/index.js
|
|
902
940
|
import { z as z4 } from "zod";
|
|
@@ -1177,6 +1215,65 @@ function sessionLanes(occurrences, defaultActorId) {
|
|
|
1177
1215
|
}
|
|
1178
1216
|
return rows;
|
|
1179
1217
|
}
|
|
1218
|
+
function randomUUID() {
|
|
1219
|
+
const crypto5 = globalThis.crypto;
|
|
1220
|
+
if (crypto5?.randomUUID) return crypto5.randomUUID();
|
|
1221
|
+
return `${Date.now().toString(16)}-${Math.random().toString(16).slice(2, 14)}`;
|
|
1222
|
+
}
|
|
1223
|
+
var mintPage = (remap, pageId) => {
|
|
1224
|
+
if (pageId === "main") return "main";
|
|
1225
|
+
const existing = remap.pages.get(pageId);
|
|
1226
|
+
if (existing) return existing;
|
|
1227
|
+
const fresh = `pg_${randomUUID().replace(/-/g, "").slice(0, 12)}`;
|
|
1228
|
+
remap.pages.set(pageId, fresh);
|
|
1229
|
+
return fresh;
|
|
1230
|
+
};
|
|
1231
|
+
function retarget(target, remap) {
|
|
1232
|
+
if (!target.pageId) return target;
|
|
1233
|
+
return { ...target, pageId: mintPage(remap, target.pageId) };
|
|
1234
|
+
}
|
|
1235
|
+
function copyStep(step, remap) {
|
|
1236
|
+
const copied = retarget({ ...step, id: remap.steps.get(step.id) }, remap);
|
|
1237
|
+
if (copied.opensPage) copied.opensPage = mintPage(remap, copied.opensPage);
|
|
1238
|
+
if (copied.to) copied.to = retarget({ ...copied.to }, remap);
|
|
1239
|
+
if (copied.scroll?.container) {
|
|
1240
|
+
copied.scroll = { ...copied.scroll, container: retarget({ ...copied.scroll.container }, remap) };
|
|
1241
|
+
}
|
|
1242
|
+
copied.proposals = step.proposals.map((assertion) => ({ ...assertion }));
|
|
1243
|
+
return copied;
|
|
1244
|
+
}
|
|
1245
|
+
function copyFlowIntoCase(flow, context) {
|
|
1246
|
+
const remap = { steps: /* @__PURE__ */ new Map(), pages: /* @__PURE__ */ new Map() };
|
|
1247
|
+
for (const step of flow.steps) {
|
|
1248
|
+
remap.steps.set(step.id, `st_${randomUUID().replace(/-/g, "").slice(0, 12)}`);
|
|
1249
|
+
}
|
|
1250
|
+
const steps = flow.steps.map((step) => copyStep(step, remap));
|
|
1251
|
+
return {
|
|
1252
|
+
occurrenceId: `occ_${randomUUID().replace(/-/g, "").slice(0, 12)}`,
|
|
1253
|
+
name: flow.name,
|
|
1254
|
+
// WHO RUNS THIS COPY. The flow said which of its participants it belongs
|
|
1255
|
+
// to; dropping that here made every copy run as the main participant, so a
|
|
1256
|
+
// flow recorded as the approver silently became the buyer doing approvals.
|
|
1257
|
+
// The case has to be given the participant too — see `mergeParticipants`.
|
|
1258
|
+
...flow.defaultActorId && flow.defaultActorId !== "default" ? { actorId: flow.defaultActorId } : {},
|
|
1259
|
+
...flow.baseUrl ? { baseUrl: flow.baseUrl } : {},
|
|
1260
|
+
startPath: flow.startPath,
|
|
1261
|
+
navigateFirst: false,
|
|
1262
|
+
steps,
|
|
1263
|
+
...flow.environment ? { environment: flow.environment } : {},
|
|
1264
|
+
origin: {
|
|
1265
|
+
flowId: flow.id,
|
|
1266
|
+
schemaVersion: flow.schemaVersion,
|
|
1267
|
+
revision: flow.revision,
|
|
1268
|
+
...context.commit ? { commit: context.commit } : {},
|
|
1269
|
+
featureId: flow.featureId,
|
|
1270
|
+
featureName: context.featureName,
|
|
1271
|
+
flowName: flow.name,
|
|
1272
|
+
stepIds: Object.fromEntries(remap.steps),
|
|
1273
|
+
copiedAt: (context.at ?? /* @__PURE__ */ new Date()).toISOString()
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1180
1277
|
function caseDebugPlan(testCase, baseUrl) {
|
|
1181
1278
|
const owners = {};
|
|
1182
1279
|
const steps = [];
|
|
@@ -1396,6 +1493,85 @@ function sameIdentity(a, b2) {
|
|
|
1396
1493
|
if (a.accountId && b2.accountId) return a.accountId === b2.accountId;
|
|
1397
1494
|
return true;
|
|
1398
1495
|
}
|
|
1496
|
+
var PrerequisiteProblem = class extends Error {
|
|
1497
|
+
constructor(message) {
|
|
1498
|
+
super(message);
|
|
1499
|
+
this.name = "PrerequisiteProblem";
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
function signInFirstStep(flow, id = SIGN_IN_FIRST_STEP_ID) {
|
|
1503
|
+
if (!flow.signIn) return null;
|
|
1504
|
+
return {
|
|
1505
|
+
id,
|
|
1506
|
+
type: "signIn",
|
|
1507
|
+
auth: flow.signIn,
|
|
1508
|
+
name: "Sign in first",
|
|
1509
|
+
role: "",
|
|
1510
|
+
scope: "",
|
|
1511
|
+
value: "",
|
|
1512
|
+
secret: false,
|
|
1513
|
+
legacySelector: "",
|
|
1514
|
+
proposals: []
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
function stepsWithoutSignIn(flow) {
|
|
1518
|
+
const first = flow.steps[0];
|
|
1519
|
+
return first && first.type === "signIn" && !first.disabled ? flow.steps.slice(1) : flow.steps;
|
|
1520
|
+
}
|
|
1521
|
+
var idsOf = (flow) => (flow.prerequisites ?? []).map((p) => p.flowId);
|
|
1522
|
+
function prerequisiteProblems(flow, lookup) {
|
|
1523
|
+
const problems = [];
|
|
1524
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1525
|
+
for (const id of idsOf(flow)) {
|
|
1526
|
+
if (id === flow.id) {
|
|
1527
|
+
problems.push(`"${flow.name}" cannot run before itself`);
|
|
1528
|
+
continue;
|
|
1529
|
+
}
|
|
1530
|
+
if (seen.has(id)) {
|
|
1531
|
+
problems.push(`"${lookup(id)?.name ?? id}" is listed twice before "${flow.name}"`);
|
|
1532
|
+
continue;
|
|
1533
|
+
}
|
|
1534
|
+
seen.add(id);
|
|
1535
|
+
const prerequisite = lookup(id);
|
|
1536
|
+
if (!prerequisite) {
|
|
1537
|
+
problems.push(`a flow "${flow.name}" runs after no longer exists \u2014 remove it from the list`);
|
|
1538
|
+
continue;
|
|
1539
|
+
}
|
|
1540
|
+
if (reaches(prerequisite, flow.id, lookup, /* @__PURE__ */ new Set())) {
|
|
1541
|
+
problems.push(`"${prerequisite.name}" already runs after "${flow.name}", so it cannot also run before it`);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
return problems;
|
|
1545
|
+
}
|
|
1546
|
+
function reaches(from, target, lookup, visited) {
|
|
1547
|
+
if (visited.has(from.id)) return false;
|
|
1548
|
+
visited.add(from.id);
|
|
1549
|
+
return idsOf(from).some((id) => {
|
|
1550
|
+
if (id === target) return true;
|
|
1551
|
+
const next = lookup(id);
|
|
1552
|
+
return next ? reaches(next, target, lookup, visited) : false;
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
function prerequisitesOf(flow, lookup) {
|
|
1556
|
+
const problems = prerequisiteProblems(flow, lookup);
|
|
1557
|
+
if (problems.length > 0) throw new PrerequisiteProblem(problems.join("; "));
|
|
1558
|
+
return idsOf(flow).map((id) => lookup(id));
|
|
1559
|
+
}
|
|
1560
|
+
function stepsForHost(prerequisite) {
|
|
1561
|
+
return copyFlowIntoCase({ ...prerequisite, steps: stepsWithoutSignIn(prerequisite) }, { featureName: "" }).steps;
|
|
1562
|
+
}
|
|
1563
|
+
function preparationFor(flow, lookup) {
|
|
1564
|
+
return {
|
|
1565
|
+
signIn: signInFirstStep(flow),
|
|
1566
|
+
steps: prerequisitesOf(flow, lookup).flatMap(stepsForHost)
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
function expandForRun(flow, lookup) {
|
|
1570
|
+
const { signIn: _signIn, prerequisites: _prerequisites, ...rest } = flow;
|
|
1571
|
+
if (!flow.signIn && idsOf(flow).length === 0) return rest;
|
|
1572
|
+
const { signIn, steps } = preparationFor(flow, lookup);
|
|
1573
|
+
return { ...rest, steps: [...signIn ? [signIn] : [], ...steps, ...flow.steps] };
|
|
1574
|
+
}
|
|
1399
1575
|
|
|
1400
1576
|
// ../engine-playwright/dist/index.js
|
|
1401
1577
|
import { createHmac, randomBytes } from "crypto";
|
|
@@ -4388,6 +4564,26 @@ var checkStep = (id, proposals) => ({
|
|
|
4388
4564
|
legacySelector: "",
|
|
4389
4565
|
proposals
|
|
4390
4566
|
});
|
|
4567
|
+
async function replayInto(target, steps, opts) {
|
|
4568
|
+
const session = {
|
|
4569
|
+
ownsBrowser: false,
|
|
4570
|
+
browser: target.browser,
|
|
4571
|
+
context: target.context,
|
|
4572
|
+
page: target.page,
|
|
4573
|
+
pages: new ExecutionPages(target.context, target.page),
|
|
4574
|
+
config: target.config,
|
|
4575
|
+
artifacts: resolveCapture({ policy: { screenshot: "off", video: "off", trace: "off", console: false } }),
|
|
4576
|
+
consoleLines: [],
|
|
4577
|
+
runArtifacts: []
|
|
4578
|
+
};
|
|
4579
|
+
const outcome = await runStepsIn(session, steps, {
|
|
4580
|
+
startUrl: null,
|
|
4581
|
+
...opts.resolveSecret ? { resolveSecret: opts.resolveSecret } : {},
|
|
4582
|
+
...opts.resolveAuth ? { resolveAuth: opts.resolveAuth } : {},
|
|
4583
|
+
...opts.baseUrl ? { baseUrl: opts.baseUrl } : {}
|
|
4584
|
+
});
|
|
4585
|
+
return outcome.status === "passed" ? { ok: true } : { ok: false, error: outcome.error ?? "a step before recording did not complete" };
|
|
4586
|
+
}
|
|
4391
4587
|
function opensItsOwnEntry(steps, opts) {
|
|
4392
4588
|
const first = steps.find((step) => !step.disabled);
|
|
4393
4589
|
if (!first || first.type !== "signIn" || !first.auth) return false;
|
|
@@ -5441,6 +5637,25 @@ async function startRecordingSession(opts) {
|
|
|
5441
5637
|
throw new Error(`${firstLine2(error)} \u2014 the browser was on ${landed || "/"}${title ? ` ("${title}")` : ""}`);
|
|
5442
5638
|
}
|
|
5443
5639
|
}
|
|
5640
|
+
const prepared = Boolean(opts.preparation?.steps.length);
|
|
5641
|
+
if (opts.preparation && prepared) {
|
|
5642
|
+
try {
|
|
5643
|
+
if (!opts.authentication) await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
5644
|
+
const replayed = await replayInto({ browser, context, page, config }, opts.preparation.steps, {
|
|
5645
|
+
resolveSecret: opts.preparation.resolveSecret,
|
|
5646
|
+
...opts.preparation.resolveAuth ? { resolveAuth: opts.preparation.resolveAuth } : {},
|
|
5647
|
+
baseUrl: url
|
|
5648
|
+
});
|
|
5649
|
+
if (!replayed.ok) throw new Error(replayed.error);
|
|
5650
|
+
} catch (error) {
|
|
5651
|
+
const landed = page.url().replace(/^https?:\/\/[^/]+/, "");
|
|
5652
|
+
const title = await page.title().catch(() => "");
|
|
5653
|
+
stopped = true;
|
|
5654
|
+
await browser.close().catch(() => {
|
|
5655
|
+
});
|
|
5656
|
+
throw new Error(`the flows this one starts after did not finish: ${firstLine2(error)} \u2014 the browser was on ${landed || "/"}${title ? ` ("${title}")` : ""}`);
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5444
5659
|
await context.addInitScript({ content: INIT_SCRIPT });
|
|
5445
5660
|
const ensureInstalled = async (p) => {
|
|
5446
5661
|
try {
|
|
@@ -5493,7 +5708,7 @@ async function startRecordingSession(opts) {
|
|
|
5493
5708
|
});
|
|
5494
5709
|
});
|
|
5495
5710
|
try {
|
|
5496
|
-
if (!opts.authentication) await page.goto(url, { waitUntil: "domcontentloaded", timeout: 45e3 });
|
|
5711
|
+
if (!opts.authentication && !prepared) await page.goto(url, { waitUntil: "domcontentloaded", timeout: 45e3 });
|
|
5497
5712
|
else await ensureInstalled(page);
|
|
5498
5713
|
} catch (err) {
|
|
5499
5714
|
stopped = true;
|
|
@@ -7762,8 +7977,15 @@ var LOCAL_CHROMIUM = { id: "chromium", provider: "local", engine: "chromium" };
|
|
|
7762
7977
|
async function executeFlow(opts) {
|
|
7763
7978
|
const { store, storage = null, flowId, trigger, watch = false, onEvent } = opts;
|
|
7764
7979
|
const headless = watch ? false : opts.headless ?? store.readConfig().headless;
|
|
7765
|
-
const
|
|
7766
|
-
if (!
|
|
7980
|
+
const found = store.getFlow(flowId);
|
|
7981
|
+
if (!found) throw new FlowNotRunnable(`flow not found: ${flowId}`, "not_found");
|
|
7982
|
+
let flow = found;
|
|
7983
|
+
try {
|
|
7984
|
+
flow = expandForRun(found, (id) => store.getFlow(id));
|
|
7985
|
+
} catch (problem) {
|
|
7986
|
+
if (problem instanceof PrerequisiteProblem) throw new FlowNotRunnable(problem.message, "empty");
|
|
7987
|
+
throw problem;
|
|
7988
|
+
}
|
|
7767
7989
|
if (opts.expectedRevision !== void 0 && flow.revision !== opts.expectedRevision) {
|
|
7768
7990
|
throw new FlowConflict("the flow changed before execution \u2014 reload it before running", flow.revision);
|
|
7769
7991
|
}
|
|
@@ -8313,6 +8535,11 @@ var RecordingCoordinator = class {
|
|
|
8313
8535
|
resolveAuth: authenticationResolver(opts.authentications),
|
|
8314
8536
|
resolveSecret: (ref) => opts.secrets?.[ref]
|
|
8315
8537
|
} } : {},
|
|
8538
|
+
...opts.preparation?.length ? { preparation: {
|
|
8539
|
+
steps: opts.preparation,
|
|
8540
|
+
resolveAuth: authenticationResolver(opts.authentications),
|
|
8541
|
+
resolveSecret: (ref) => opts.secrets?.[ref]
|
|
8542
|
+
} } : {},
|
|
8316
8543
|
// The project's saved defaults, unless this recording asks for
|
|
8317
8544
|
// something else. Without the fallback the settings screen would write
|
|
8318
8545
|
// a file nothing ever read.
|
|
@@ -8757,7 +8984,7 @@ function resolveCheckouts(dirs) {
|
|
|
8757
8984
|
return { projects, skipped };
|
|
8758
8985
|
}
|
|
8759
8986
|
|
|
8760
|
-
// ../agent-core/dist/chunk-
|
|
8987
|
+
// ../agent-core/dist/chunk-4MOK25KG.js
|
|
8761
8988
|
import { WebSocket, WebSocketServer } from "ws";
|
|
8762
8989
|
var HEARTBEAT_MS = 3e4;
|
|
8763
8990
|
function adapt(socket) {
|
|
@@ -9827,8 +10054,10 @@ function recordingHandlers({ recorder, onActivity }) {
|
|
|
9827
10054
|
// returned on stop for the service to commit to the repository. A
|
|
9828
10055
|
// machine that has the project checked out still records into it.
|
|
9829
10056
|
root,
|
|
9830
|
-
...command.args["authentication"] ? {
|
|
9831
|
-
|
|
10057
|
+
...command.args["authentication"] ? { authentication: AuthReferenceSchema.parse(command.args["authentication"]) } : {},
|
|
10058
|
+
// The flows this recording starts after, replayed before capturing.
|
|
10059
|
+
...Array.isArray(command.args["preparation"]) && command.args["preparation"].length > 0 ? { preparation: RecordedStepSchema.array().parse(command.args["preparation"]) } : {},
|
|
10060
|
+
...command.args["authentication"] || command.args["preparation"] ? {
|
|
9832
10061
|
authentications: command.args["authentications"],
|
|
9833
10062
|
secrets: command.args["secrets"] ?? {}
|
|
9834
10063
|
} : {},
|
package/dist/cli.js
CHANGED
package/dist/engine.js
CHANGED
package/package.json
CHANGED