@swmansion/argent 0.24.0 → 0.24.1-next.0
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/bin/argent-android-devtools-0.1.0.apk +0 -0
- package/bin/darwin/ax-service +0 -0
- package/bin/darwin/tvos-ax-service +0 -0
- package/bin/darwin/tvos-hid-daemon +0 -0
- package/bin/tcp/ax-service +0 -0
- package/dist/cli-cmds.mjs +1 -1
- package/dist/installer.mjs +1 -1
- package/dist/tool-server.cjs +314 -262
- package/dylibs/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/libKeyboardPatch.dylib +0 -0
- package/dylibs/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tcp/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tcp/libKeyboardPatch.dylib +0 -0
- package/dylibs/tcp/libNativeDevtoolsIos.dylib +0 -0
- package/dylibs/tvos/libArgentInjectionBootstrap.dylib +0 -0
- package/dylibs/tvos/libKeyboardPatch.dylib +0 -0
- package/dylibs/tvos/libNativeDevtoolsIos.dylib +0 -0
- package/package.json +1 -1
|
Binary file
|
package/bin/darwin/ax-service
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/bin/tcp/ax-service
CHANGED
|
Binary file
|
package/dist/cli-cmds.mjs
CHANGED
package/dist/installer.mjs
CHANGED
|
@@ -16625,7 +16625,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
16625
16625
|
var SESSION_ID = randomUUID4();
|
|
16626
16626
|
function readCliVersion() {
|
|
16627
16627
|
if (true) {
|
|
16628
|
-
return "0.24.0";
|
|
16628
|
+
return "0.24.1-next.0";
|
|
16629
16629
|
}
|
|
16630
16630
|
return "0.0.0";
|
|
16631
16631
|
}
|
package/dist/tool-server.cjs
CHANGED
|
@@ -93916,7 +93916,7 @@ var _CI_VENDOR_COUNT_FOR_TEST = vendors_default.length;
|
|
|
93916
93916
|
var SESSION_ID = (0, import_node_crypto3.randomUUID)();
|
|
93917
93917
|
function readCliVersion() {
|
|
93918
93918
|
if (true) {
|
|
93919
|
-
return "0.24.0";
|
|
93919
|
+
return "0.24.1-next.0";
|
|
93920
93920
|
}
|
|
93921
93921
|
return "0.0.0";
|
|
93922
93922
|
}
|
|
@@ -143956,11 +143956,25 @@ function selectorToYaml(sel) {
|
|
|
143956
143956
|
}
|
|
143957
143957
|
return out;
|
|
143958
143958
|
}
|
|
143959
|
+
var INLINE_UNSAFE = /[\u0000-\u001f\u007f-\u009f]/g;
|
|
143960
|
+
var INLINE_SHORT = {
|
|
143961
|
+
"\b": "\\b",
|
|
143962
|
+
" ": "\\t",
|
|
143963
|
+
"\n": "\\n",
|
|
143964
|
+
"\f": "\\f",
|
|
143965
|
+
"\r": "\\r"
|
|
143966
|
+
};
|
|
143967
|
+
function escapeInline(value) {
|
|
143968
|
+
return value.replace(
|
|
143969
|
+
INLINE_UNSAFE,
|
|
143970
|
+
(c) => INLINE_SHORT[c] ?? `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`
|
|
143971
|
+
);
|
|
143972
|
+
}
|
|
143959
143973
|
function describeSelector(s) {
|
|
143960
143974
|
const { loose: _loose, any: any2, within, after, next, ...rest } = s;
|
|
143961
143975
|
const scopes = { within, after, next };
|
|
143962
143976
|
const fields = Object.entries(rest).map(
|
|
143963
|
-
([k, v]) => k === "textMatches" ? `text=/${v}/` : `${k === "identifier" ? "id" : k}
|
|
143977
|
+
([k, v]) => k === "textMatches" ? `text=/${escapeInline(String(v))}/` : `${k === "identifier" ? "id" : k}=${JSON.stringify(String(v))}`
|
|
143964
143978
|
).join(" ");
|
|
143965
143979
|
const parts2 = [any2 ? "*" : void 0, fields || void 0].filter((p) => p !== void 0);
|
|
143966
143980
|
for (const relation of SELECTOR_RELATIONS) {
|
|
@@ -145612,7 +145626,7 @@ costs the finish the cross-tree verdicts anchored to them.`,
|
|
|
145612
145626
|
|
|
145613
145627
|
// ../tool-server/src/tools/flows/flow-add-step.ts
|
|
145614
145628
|
init_zod();
|
|
145615
|
-
var
|
|
145629
|
+
var fs53 = __toESM(require("node:fs/promises"));
|
|
145616
145630
|
var path38 = __toESM(require("node:path"));
|
|
145617
145631
|
init_src();
|
|
145618
145632
|
|
|
@@ -147407,10 +147421,8 @@ function assertReason(condition, selector, expectedText, textMatch, matches2) {
|
|
|
147407
147421
|
}
|
|
147408
147422
|
}
|
|
147409
147423
|
|
|
147410
|
-
// ../tool-server/src/tools/flows/flow-
|
|
147411
|
-
|
|
147412
|
-
var fs53 = __toESM(require("node:fs/promises"));
|
|
147413
|
-
function selectorLabel(sel) {
|
|
147424
|
+
// ../tool-server/src/tools/flows/flow-step-definitions.ts
|
|
147425
|
+
function yamlSelectorLabel(sel) {
|
|
147414
147426
|
const yaml = selectorToYaml(sel);
|
|
147415
147427
|
if (typeof yaml !== "object" || yaml === null) return JSON.stringify(yaml);
|
|
147416
147428
|
const sorted = Object.fromEntries(
|
|
@@ -147418,116 +147430,54 @@ function selectorLabel(sel) {
|
|
|
147418
147430
|
);
|
|
147419
147431
|
return JSON.stringify(sorted);
|
|
147420
147432
|
}
|
|
147421
|
-
function
|
|
147422
|
-
const selector =
|
|
147433
|
+
function yamlTextConditionLabel(sel, expectedText, textMatch) {
|
|
147434
|
+
const selector = yamlSelectorLabel(sel);
|
|
147423
147435
|
const expected = expectedText ?? "";
|
|
147424
147436
|
return textMatch === "matches" ? `text ${selector} matches /${expected}/` : textMatch === "equals" ? `text ${selector} == ${JSON.stringify(expected)}` : `text ${selector} contains ${JSON.stringify(expected)}`;
|
|
147425
147437
|
}
|
|
147426
|
-
function
|
|
147427
|
-
return "
|
|
147428
|
-
}
|
|
147429
|
-
var zodSchema62 = external_exports.object({
|
|
147430
|
-
name: external_exports.string().describe("Name of the flow being recorded \u2014 the one passed to flow-start-recording."),
|
|
147431
|
-
project_root: external_exports.string().describe(
|
|
147432
|
-
"Absolute path to the project root of the flow being recorded \u2014 the same value passed to flow-start-recording. Together with `name` it identifies which recording to finish."
|
|
147433
|
-
)
|
|
147434
|
-
});
|
|
147435
|
-
function attachStepWarnings(summary, warnings) {
|
|
147436
|
-
if (warnings.size === 0) return summary;
|
|
147437
|
-
return summary.flatMap((line, i) => {
|
|
147438
|
-
const recorded = warnings.get(i + 1);
|
|
147439
|
-
return recorded ? [line, ` warning: ${recorded.warning}`] : [line];
|
|
147440
|
-
});
|
|
147438
|
+
function yamlConditionLabel(cond) {
|
|
147439
|
+
return cond.condition === "text" ? yamlTextConditionLabel(cond.selector, cond.expectedText, cond.textMatch) : `${cond.condition} ${yamlSelectorLabel(cond.selector)}`;
|
|
147441
147440
|
}
|
|
147442
|
-
function
|
|
147443
|
-
const
|
|
147444
|
-
|
|
147445
|
-
|
|
147446
|
-
if (
|
|
147447
|
-
|
|
147448
|
-
|
|
147449
|
-
|
|
147450
|
-
|
|
147451
|
-
|
|
147452
|
-
clauses.push(
|
|
147453
|
-
`${counts.wait} ${counts.wait === 1 ? "step" : "steps"} recorded a wait that did not pass`
|
|
147454
|
-
);
|
|
147441
|
+
function selectorLabel(sel) {
|
|
147442
|
+
const parts2 = [];
|
|
147443
|
+
if (sel.any) parts2.push("*");
|
|
147444
|
+
if (sel.text !== void 0) parts2.push(JSON.stringify(sel.text));
|
|
147445
|
+
if (sel.textMatches !== void 0) parts2.push(`/${escapeInline(sel.textMatches)}/`);
|
|
147446
|
+
if (sel.identifier) parts2.push(`id=${escapeInline(sel.identifier)}`);
|
|
147447
|
+
if (sel.role) parts2.push(`role=${escapeInline(sel.role)}`);
|
|
147448
|
+
for (const relation of SELECTOR_RELATIONS) {
|
|
147449
|
+
const scope = sel[relation];
|
|
147450
|
+
if (scope !== void 0) parts2.push(`${relation} (${selectorLabel(scope)})`);
|
|
147455
147451
|
}
|
|
147456
|
-
|
|
147457
|
-
if (discarded === 0) return carried;
|
|
147458
|
-
const one = discarded === 1;
|
|
147459
|
-
const drop = `${discarded} ${one ? "warning" : "warnings"} raised during this recording ${one ? "is" : "are"} NOT in \`summary\`: a hand edit to the .yaml moved the ${one ? "step it judged" : "steps they judged"}, so which step ${one ? "it belongs" : "they belong"} to is no longer knowable \u2014 re-record ${one ? "that wait" : "those waits"} to see ${one ? "it" : "them"} again`;
|
|
147460
|
-
return carried === "" ? ` \u2014 ${drop}` : `${carried}. ${drop}`;
|
|
147452
|
+
return parts2.join(" ");
|
|
147461
147453
|
}
|
|
147462
|
-
function
|
|
147463
|
-
const
|
|
147464
|
-
|
|
147465
|
-
|
|
147466
|
-
if (!steps.every((step, i) => stepAnchor(step) === stepAnchor(recorded[i]))) return kept;
|
|
147467
|
-
for (const [n, verdict] of session.stepWarnings ?? []) {
|
|
147468
|
-
const step = steps[n - 1];
|
|
147469
|
-
if (step !== void 0 && stepAnchor(step) === verdict.step) kept.set(n, verdict);
|
|
147454
|
+
function conditionLabel(cond, renderSelector) {
|
|
147455
|
+
const sel = renderSelector(cond.selector);
|
|
147456
|
+
if (cond.condition === "text") {
|
|
147457
|
+
return `${sel} ${describeTextExpectation(cond.expectedText, cond.textMatch)}`;
|
|
147470
147458
|
}
|
|
147471
|
-
return
|
|
147459
|
+
return `${cond.condition} ${sel}`;
|
|
147460
|
+
}
|
|
147461
|
+
function gestureTargetLabel(target, renderSelector) {
|
|
147462
|
+
return "selector" in target ? renderSelector(target.selector) : `(${target.x}, ${target.y})`;
|
|
147463
|
+
}
|
|
147464
|
+
function swipeLabel(step, renderSelector) {
|
|
147465
|
+
let travel;
|
|
147466
|
+
if (step.direction !== void 0) travel = step.direction;
|
|
147467
|
+
else if (step.by !== void 0) travel = `by ${swipeByLabel(step.by)}`;
|
|
147468
|
+
else if (step.to !== void 0) travel = `to ${gestureTargetLabel(step.to, renderSelector)}`;
|
|
147469
|
+
else return void 0;
|
|
147470
|
+
return `${travel}${step.from ? ` from ${gestureTargetLabel(step.from, renderSelector)}` : ""}`;
|
|
147471
|
+
}
|
|
147472
|
+
function whenLabel(cond, renderUi) {
|
|
147473
|
+
return cond.kind === "platform" ? `platform ${cond.platform}` : renderUi(cond);
|
|
147474
|
+
}
|
|
147475
|
+
function describeWhenCondition(cond) {
|
|
147476
|
+
return whenLabel(cond, (ui) => conditionLabel(ui, describeSelector));
|
|
147472
147477
|
}
|
|
147473
|
-
var flowFinishRecordingTool = {
|
|
147474
|
-
id: "flow-finish-recording",
|
|
147475
|
-
interaction: {
|
|
147476
|
-
// Name the flow: other recordings stay live, so an unqualified message would
|
|
147477
|
-
// not identify which one.
|
|
147478
|
-
startedMsg: ({ params }) => `Finishing recording of flow ${params.name}`,
|
|
147479
|
-
// `params.name` equals the basename of `result.path` on every branch
|
|
147480
|
-
// (`assertSafeFlowName` admits no dots or separators), and matches the two
|
|
147481
|
-
// formatters either side.
|
|
147482
|
-
completedMsg: ({ params }) => `Saved recorded flow ${params.name}`,
|
|
147483
|
-
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to finish recording of flow ${params.name}: ${failureSignal2.error_code}`
|
|
147484
|
-
},
|
|
147485
|
-
description: `Finish recording the flow named by \`name\` + \`project_root\`, leaving recordings under any other key untouched. Returns { message, path, executionPrerequisite, steps, summary, flowFile, savedTo } - a summary of all recorded steps plus the final YAML. Use when you have added all desired steps and want to finalize the flow file. Fails if that flow has no recording in progress.
|
|
147486
|
-
A warning flow-add-step raised on a recorded \`await-ui-element\` is repeated in \`summary\` as a \`warning:\` line of its own, right below the step it judges, and \`message\` counts them by kind. A warning is repeated only while the step it judges is still identifiable by its number: hand-editing the .yaml during the recording moves the steps, so those warnings are DROPPED rather than pinned on whichever step inherited the number, and \`message\` says how many were dropped. A step that carries a cross-tree warning was re-probed against the runner's tree: read it before converting that wait to \`await:\`/\`assert:\`, which is what the verdict is about and what this moment is for. A step that recorded a wait which did not pass was never probed at all, and its own warning names the CAUSE, because only one of them judges the condition: an unmet wait was read and found false, and it stops the run at replay; a wait whose tree source could not be read, or one that was cancelled, observed nothing and leaves the condition UNKNOWN rather than known-bad. Read those before replaying.
|
|
147487
|
-
You can still edit the .yaml file directly afterwards to remove or reorder steps.`,
|
|
147488
|
-
zodSchema: zodSchema62,
|
|
147489
|
-
services: () => ({}),
|
|
147490
|
-
async execute(_services, params) {
|
|
147491
|
-
const { filePath, flowFile, savedTo, flow, summary, headline } = await withFlowFileLock(
|
|
147492
|
-
params.project_root,
|
|
147493
|
-
params.name,
|
|
147494
|
-
async () => {
|
|
147495
|
-
const session = await requireRecordingSession(params.project_root, params.name);
|
|
147496
|
-
const filePath2 = session.filePath;
|
|
147497
|
-
let flowFile2;
|
|
147498
|
-
let savedTo2;
|
|
147499
|
-
if (session.persist === "client") {
|
|
147500
|
-
flowFile2 = serializeFlow(session.flow);
|
|
147501
|
-
savedTo2 = clientFileDirective(filePath2, flowFile2);
|
|
147502
|
-
} else {
|
|
147503
|
-
flowFile2 = await fs53.readFile(filePath2, "utf8");
|
|
147504
|
-
savedTo2 = filePath2;
|
|
147505
|
-
}
|
|
147506
|
-
const flow2 = parseFlow(flowFile2);
|
|
147507
|
-
const anchored = anchoredWarnings(session, flow2.steps);
|
|
147508
|
-
const summary2 = attachStepWarnings(summarizeSteps(flow2), anchored);
|
|
147509
|
-
const discarded = (session.discardedWarnings ?? 0) + (session.stepWarnings?.size ?? 0) - anchored.size;
|
|
147510
|
-
const headline2 = warningHeadline(anchored, discarded);
|
|
147511
|
-
clearRecordingSession(session);
|
|
147512
|
-
return { filePath: filePath2, flowFile: flowFile2, savedTo: savedTo2, flow: flow2, summary: summary2, headline: headline2 };
|
|
147513
|
-
}
|
|
147514
|
-
);
|
|
147515
|
-
return {
|
|
147516
|
-
// Name the counts in `message` as well. A caller that reads only
|
|
147517
|
-
// `message` would otherwise polish blind.
|
|
147518
|
-
message: `Finished recording "${params.name}" flow (${flow.steps.length} steps)` + headline,
|
|
147519
|
-
path: filePath,
|
|
147520
|
-
executionPrerequisite: flow.executionPrerequisite,
|
|
147521
|
-
steps: flow.steps.length,
|
|
147522
|
-
summary,
|
|
147523
|
-
flowFile,
|
|
147524
|
-
savedTo
|
|
147525
|
-
};
|
|
147526
|
-
}
|
|
147527
|
-
};
|
|
147528
147478
|
function renderToolArgs(args) {
|
|
147529
147479
|
try {
|
|
147530
|
-
return
|
|
147480
|
+
return JSON.stringify(args);
|
|
147531
147481
|
} catch {
|
|
147532
147482
|
return "[cyclic args]";
|
|
147533
147483
|
}
|
|
@@ -147535,77 +147485,162 @@ function renderToolArgs(args) {
|
|
|
147535
147485
|
function delayLabel(step) {
|
|
147536
147486
|
if (!step.delayMs) return "";
|
|
147537
147487
|
const ms = Number(step.delayMs);
|
|
147538
|
-
return
|
|
147539
|
-
}
|
|
147540
|
-
|
|
147541
|
-
|
|
147542
|
-
|
|
147543
|
-
|
|
147544
|
-
|
|
147545
|
-
}
|
|
147546
|
-
|
|
147547
|
-
|
|
147548
|
-
|
|
147549
|
-
|
|
147550
|
-
|
|
147551
|
-
|
|
147552
|
-
|
|
147553
|
-
|
|
147554
|
-
|
|
147555
|
-
|
|
147556
|
-
|
|
147557
|
-
|
|
147558
|
-
|
|
147559
|
-
|
|
147560
|
-
|
|
147561
|
-
|
|
147562
|
-
}
|
|
147563
|
-
|
|
147564
|
-
|
|
147565
|
-
|
|
147488
|
+
return ms >= 1 && ms <= 2 ** 31 - 1 ? ` (after ${ms}ms)` : "";
|
|
147489
|
+
}
|
|
147490
|
+
var MAX_TARGET_TEXT_CHARS = 200;
|
|
147491
|
+
function typedTextLabel(text) {
|
|
147492
|
+
const chars = Array.from(text);
|
|
147493
|
+
if (chars.length <= MAX_TARGET_TEXT_CHARS) return JSON.stringify(text);
|
|
147494
|
+
const elided = chars.length - MAX_TARGET_TEXT_CHARS;
|
|
147495
|
+
return `${JSON.stringify(chars.slice(0, MAX_TARGET_TEXT_CHARS).join(""))}\u2026(+${elided} chars)`;
|
|
147496
|
+
}
|
|
147497
|
+
var POINT_GESTURE_STEP = {
|
|
147498
|
+
// `times` (tap) and `duration` (long-press) change what replays, so a summary
|
|
147499
|
+
// line that drops them misdescribes the file. `times` has a second reason:
|
|
147500
|
+
// `tap` is one of the kinds the recorder builds, and the recorder echoes this
|
|
147501
|
+
// line alone rather than the growing YAML, so it is the author's only per-step
|
|
147502
|
+
// view of what was appended. `long-press` has no recorder path, so it reaches
|
|
147503
|
+
// an author only through flow-finish-recording's `summary`, which returns
|
|
147504
|
+
// `flowFile` beside it. Neither kind carries a `delayMs` (only `tool` steps
|
|
147505
|
+
// do), so no delayLabel here.
|
|
147506
|
+
//
|
|
147507
|
+
// Four replay-affecting fields render on neither surface — `type.submit`,
|
|
147508
|
+
// `await.timeout`, `idle.timeout`, `idle.stableFor` — so a summary line alone
|
|
147509
|
+
// does not distinguish two steps differing only in those.
|
|
147510
|
+
summary: (step) => {
|
|
147511
|
+
const target = step.selector ? yamlSelectorLabel(step.selector) : `(${step.x}, ${step.y})`;
|
|
147512
|
+
const times = step.kind === "tap" && step.times !== void 0 && step.times > 1 ? ` \xD7${step.times}` : "";
|
|
147513
|
+
const held = step.kind === "long-press" && step.duration !== void 0 ? ` for ${step.duration}ms` : "";
|
|
147514
|
+
return `${target}${times}${held}`;
|
|
147515
|
+
},
|
|
147516
|
+
target: (step) => {
|
|
147517
|
+
if (step.selector) return selectorLabel(step.selector);
|
|
147518
|
+
if (step.x !== void 0 && step.y !== void 0) return `(${step.x}, ${step.y})`;
|
|
147519
|
+
return void 0;
|
|
147520
|
+
}
|
|
147521
|
+
};
|
|
147522
|
+
var UI_CONDITION_STEP = {
|
|
147523
|
+
summary: (step) => yamlConditionLabel(step),
|
|
147524
|
+
target: (step) => conditionLabel(step, selectorLabel)
|
|
147525
|
+
};
|
|
147526
|
+
var FLOW_STEP_DEFINITIONS = {
|
|
147527
|
+
"tool": {
|
|
147528
|
+
summary: (step) => `${step.name} ${renderToolArgs(step.args)}${delayLabel(step)}`,
|
|
147529
|
+
// Carries its subject in a report field of its own (`tool`) that renderers
|
|
147530
|
+
// print in the target's place.
|
|
147531
|
+
target: () => void 0
|
|
147532
|
+
},
|
|
147533
|
+
"echo": {
|
|
147534
|
+
summary: (step) => step.message,
|
|
147535
|
+
// As for `tool`, but the field is `message`.
|
|
147536
|
+
target: () => void 0
|
|
147537
|
+
},
|
|
147538
|
+
"launch": {
|
|
147539
|
+
summary: (step) => typeof step.app === "string" ? step.app : JSON.stringify(step.app),
|
|
147540
|
+
// A launch's app id may be per-platform (`appIdForPlatform`), and a step
|
|
147541
|
+
// alone does not know the run device.
|
|
147542
|
+
target: () => void 0
|
|
147543
|
+
},
|
|
147544
|
+
"run": {
|
|
147545
|
+
summary: (step) => step.flow,
|
|
147546
|
+
// The as-written path, so a report line shows exactly what the flow
|
|
147547
|
+
// references (`run ../shared/login.yaml`), not just the attribution stem.
|
|
147548
|
+
target: (step) => step.flow
|
|
147549
|
+
},
|
|
147550
|
+
"when": {
|
|
147551
|
+
summary: (step) => {
|
|
147552
|
+
const count2 = step.steps.length;
|
|
147553
|
+
const cond = whenLabel(step.condition, yamlConditionLabel);
|
|
147554
|
+
return `${cond} (${count2} step${count2 === 1 ? "" : "s"})`;
|
|
147555
|
+
},
|
|
147556
|
+
target: (step) => whenLabel(step.condition, (ui) => conditionLabel(ui, selectorLabel))
|
|
147557
|
+
},
|
|
147558
|
+
"tap": POINT_GESTURE_STEP,
|
|
147559
|
+
"long-press": POINT_GESTURE_STEP,
|
|
147560
|
+
"swipe": {
|
|
147561
|
+
// `momentum` and `duration` change what replays, so the summary spells them
|
|
147562
|
+
// as it spells tap's `times`. A report target names what the step acts on,
|
|
147563
|
+
// so they ride the summary alone.
|
|
147564
|
+
summary: (step) => {
|
|
147566
147565
|
const options = [
|
|
147567
147566
|
...step.momentum === false ? ["momentum-free"] : [],
|
|
147568
147567
|
...step.duration !== void 0 ? [`${step.duration}ms`] : []
|
|
147569
147568
|
];
|
|
147570
147569
|
const tail = options.length > 0 ? ` (${options.join(", ")})` : "";
|
|
147571
|
-
return `${
|
|
147570
|
+
return `${swipeLabel(step, yamlSelectorLabel)}${tail}`;
|
|
147571
|
+
},
|
|
147572
|
+
target: (step) => swipeLabel(step, selectorLabel)
|
|
147573
|
+
},
|
|
147574
|
+
"type": {
|
|
147575
|
+
summary: (step) => `${yamlSelectorLabel(step.into)} \u2190 ${JSON.stringify(step.text)}`,
|
|
147576
|
+
// The typed text rides along, the way an await/assert target carries its
|
|
147577
|
+
// expectation: two steps into the same field with different text would
|
|
147578
|
+
// otherwise render identical targets.
|
|
147579
|
+
target: (step) => `into ${selectorLabel(step.into)} \u2190 ${typedTextLabel(step.text)}`
|
|
147580
|
+
},
|
|
147581
|
+
"await": UI_CONDITION_STEP,
|
|
147582
|
+
"assert": UI_CONDITION_STEP,
|
|
147583
|
+
"idle": {
|
|
147584
|
+
summaryKind: "await",
|
|
147585
|
+
summary: () => "screen idle",
|
|
147586
|
+
// The report already prints the kind, and this step addresses nothing
|
|
147587
|
+
// beyond the screen itself: a target would render as "idle screen idle".
|
|
147588
|
+
target: () => void 0
|
|
147589
|
+
},
|
|
147590
|
+
"wait": {
|
|
147591
|
+
summary: (step) => `${step.ms}ms`,
|
|
147592
|
+
target: () => void 0
|
|
147593
|
+
},
|
|
147594
|
+
"scroll-to": {
|
|
147595
|
+
summary: (step) => `${yamlSelectorLabel(step.target)} (${step.direction})` + (step.within ? ` within ${yamlSelectorLabel(step.within)}` : ""),
|
|
147596
|
+
target: (step) => {
|
|
147597
|
+
const dir = step.direction !== "down" ? ` (${step.direction})` : "";
|
|
147598
|
+
const container = step.within ? ` in scroll container (${selectorLabel(step.within)})` : "";
|
|
147599
|
+
return `${selectorLabel(step.target)}${dir}${container}`;
|
|
147572
147600
|
}
|
|
147573
|
-
|
|
147574
|
-
|
|
147575
|
-
|
|
147576
|
-
|
|
147577
|
-
const
|
|
147578
|
-
return
|
|
147601
|
+
},
|
|
147602
|
+
"pinch": {
|
|
147603
|
+
summary: (step) => `scale ${step.scale}${step.selector ? ` on ${yamlSelectorLabel(step.selector)}` : ""}`,
|
|
147604
|
+
target: (step) => {
|
|
147605
|
+
const scale = `scale ${step.scale}`;
|
|
147606
|
+
return step.selector ? `${selectorLabel(step.selector)} (${scale})` : scale;
|
|
147579
147607
|
}
|
|
147580
|
-
|
|
147581
|
-
|
|
147582
|
-
|
|
147583
|
-
|
|
147584
|
-
|
|
147585
|
-
|
|
147586
|
-
step.condition.textMatch
|
|
147587
|
-
) : `${step.condition.condition} ${selectorLabel(step.condition.selector)}`;
|
|
147588
|
-
const count2 = step.steps.length;
|
|
147589
|
-
return `${n}. when: ${cond} (${count2} step${count2 === 1 ? "" : "s"})`;
|
|
147608
|
+
},
|
|
147609
|
+
"rotate": {
|
|
147610
|
+
summary: (step) => `by ${step.by}\xB0${step.selector ? ` on ${yamlSelectorLabel(step.selector)}` : ""}`,
|
|
147611
|
+
target: (step) => {
|
|
147612
|
+
const by = `by ${step.by}\xB0`;
|
|
147613
|
+
return step.selector ? `${selectorLabel(step.selector)} (${by})` : by;
|
|
147590
147614
|
}
|
|
147591
|
-
|
|
147592
|
-
|
|
147593
|
-
|
|
147594
|
-
|
|
147595
|
-
|
|
147596
|
-
|
|
147597
|
-
|
|
147598
|
-
|
|
147599
|
-
case "idle":
|
|
147600
|
-
return `${n}. await: screen idle`;
|
|
147601
|
-
case "tool":
|
|
147602
|
-
default:
|
|
147603
|
-
return `${n}. tool: ${step.name} ${renderToolArgs(step.args)}${delayLabel(step)}`;
|
|
147615
|
+
},
|
|
147616
|
+
"snapshot": {
|
|
147617
|
+
// `name` interpolates raw on both surfaces. It becomes a baseline filename,
|
|
147618
|
+
// so `parseFlow` gates it on FLOW_NAME_PATTERN (letters, digits, `_`, `-`)
|
|
147619
|
+
// — and that parse is the only thing that builds a snapshot step, so no
|
|
147620
|
+
// quote, backslash or newline reaches here to escape.
|
|
147621
|
+
summary: (step) => step.name + (step.cropOn ? ` cropOn ${yamlSelectorLabel(step.cropOn)}` : "") + (step.maxMismatch !== void 0 ? ` maxMismatch ${step.maxMismatch}` : ""),
|
|
147622
|
+
target: (step) => step.cropOn ? `"${step.name}" cropOn ${selectorLabel(step.cropOn)}` : `"${step.name}"`
|
|
147604
147623
|
}
|
|
147624
|
+
};
|
|
147625
|
+
function definitionOf(step) {
|
|
147626
|
+
return FLOW_STEP_DEFINITIONS[step.kind];
|
|
147627
|
+
}
|
|
147628
|
+
function stepTarget(step) {
|
|
147629
|
+
return definitionOf(step).target(step);
|
|
147630
|
+
}
|
|
147631
|
+
function summarizeStep(step, n) {
|
|
147632
|
+
const def = definitionOf(step);
|
|
147633
|
+
return `${n}. ${def.summaryKind ?? step.kind}: ${def.summary(step)}`;
|
|
147634
|
+
}
|
|
147635
|
+
function summarizeSteps(flow) {
|
|
147636
|
+
return flow.steps.map((step, i) => summarizeStep(step, i + 1));
|
|
147637
|
+
}
|
|
147638
|
+
function stepAnchor(step) {
|
|
147639
|
+
return summarizeStep(step, 0);
|
|
147605
147640
|
}
|
|
147606
147641
|
|
|
147607
147642
|
// ../tool-server/src/tools/flows/flow-add-step.ts
|
|
147608
|
-
var
|
|
147643
|
+
var zodSchema62 = external_exports.object({
|
|
147609
147644
|
name: external_exports.string().describe("Name of the flow being recorded \u2014 the one passed to flow-start-recording."),
|
|
147610
147645
|
project_root: external_exports.string().describe(
|
|
147611
147646
|
"Absolute path to the project root of the flow being recorded \u2014 the same value passed to flow-start-recording. Together with `name` it identifies which recording this step belongs to."
|
|
@@ -147819,7 +147854,7 @@ async function captureTapSelector(registry2, session, udid, point) {
|
|
|
147819
147854
|
async function activeFlowState(session) {
|
|
147820
147855
|
if (session.persist === "host") {
|
|
147821
147856
|
try {
|
|
147822
|
-
session.flow = parseFlow(await
|
|
147857
|
+
session.flow = parseFlow(await fs53.readFile(session.filePath, "utf8"));
|
|
147823
147858
|
} catch (err) {
|
|
147824
147859
|
return {
|
|
147825
147860
|
stepCount: session.flow.steps.length,
|
|
@@ -147960,7 +147995,7 @@ async function captureRunTarget(session, args) {
|
|
|
147960
147995
|
}
|
|
147961
147996
|
try {
|
|
147962
147997
|
assertSafeFlowName(name);
|
|
147963
|
-
const realFlowPath = await
|
|
147998
|
+
const realFlowPath = await fs53.realpath(session.filePath);
|
|
147964
147999
|
const flowsDir = path38.dirname(realFlowPath);
|
|
147965
148000
|
const fragPath = path38.join(flowsDir, `${name}.yaml`);
|
|
147966
148001
|
const projectRoot = args.project_root;
|
|
@@ -147976,10 +148011,10 @@ async function captureRunTarget(session, args) {
|
|
|
147976
148011
|
warning: `kept the raw flow-execute step \u2014 no sibling is named "${name}.yaml" (this filesystem matched it case-insensitively to "${spelling.actual}"), so a run: ${name} step would name a flow no case-sensitive checkout can find \u2014 ${recovery}`
|
|
147977
148012
|
};
|
|
147978
148013
|
}
|
|
147979
|
-
parseFlow(await
|
|
148014
|
+
parseFlow(await fs53.readFile(fragPath, "utf8"));
|
|
147980
148015
|
let executedPath;
|
|
147981
148016
|
try {
|
|
147982
|
-
executedPath = await
|
|
148017
|
+
executedPath = await fs53.realpath(path38.join(flowsDirFor(projectRoot), `${name}.yaml`));
|
|
147983
148018
|
} catch {
|
|
147984
148019
|
executedPath = void 0;
|
|
147985
148020
|
}
|
|
@@ -147988,7 +148023,7 @@ async function captureRunTarget(session, args) {
|
|
|
147988
148023
|
warning: `kept the raw flow-execute step \u2014 could not verify which file the live flow-execute ran ("${name}" has no canonical file in project_root's flows dir to compare the sibling against)`
|
|
147989
148024
|
};
|
|
147990
148025
|
}
|
|
147991
|
-
if (executedPath !== await
|
|
148026
|
+
if (executedPath !== await fs53.realpath(fragPath)) {
|
|
147992
148027
|
return {
|
|
147993
148028
|
warning: `kept the raw flow-execute step \u2014 project_root "${projectRoot}" resolves "${name}" to "${executedPath}", not the recording's sibling "${fragPath}", so "${name}.yaml" beside the recording's real file is not the file the live flow-execute ran and a run: ${name} step would replay a different flow than the one that just ran`
|
|
147994
148029
|
};
|
|
@@ -148020,7 +148055,7 @@ If a step was recorded by mistake, remove it from the .yaml after \`flow-finish-
|
|
|
148020
148055
|
// more times — and every retry re-runs the action and appends another step,
|
|
148021
148056
|
// because an aborted request still appends its first.
|
|
148022
148057
|
longRunning: true,
|
|
148023
|
-
zodSchema:
|
|
148058
|
+
zodSchema: zodSchema62,
|
|
148024
148059
|
services: () => ({}),
|
|
148025
148060
|
async execute(_services, params, ctx) {
|
|
148026
148061
|
const session = await requireRecordingSession(params.project_root, params.name);
|
|
@@ -148125,7 +148160,7 @@ If a step was recorded by mistake, remove it from the .yaml after \`flow-finish-
|
|
|
148125
148160
|
|
|
148126
148161
|
// ../tool-server/src/tools/flows/flow-insert-echo.ts
|
|
148127
148162
|
init_zod();
|
|
148128
|
-
var
|
|
148163
|
+
var zodSchema63 = external_exports.object({
|
|
148129
148164
|
name: external_exports.string().describe("Name of the flow being recorded \u2014 the one passed to flow-start-recording."),
|
|
148130
148165
|
project_root: external_exports.string().describe(
|
|
148131
148166
|
"Absolute path to the project root of the flow being recorded \u2014 the same value passed to flow-start-recording. Together with `name` it identifies which recording this echo belongs to."
|
|
@@ -148143,7 +148178,7 @@ var flowInsertEchoTool = {
|
|
|
148143
148178
|
description: `Record an echo step in the flow named by \`name\` + \`project_root\`. Echo steps print a message when the flow is replayed \u2014 useful as labels between tool calls.
|
|
148144
148179
|
Use when you want to annotate a recorded flow with a human-readable label or checkpoint message.
|
|
148145
148180
|
Returns { message, stepCount, savedTo }. Fails if that flow has no recording in progress.`,
|
|
148146
|
-
zodSchema:
|
|
148181
|
+
zodSchema: zodSchema63,
|
|
148147
148182
|
services: () => ({}),
|
|
148148
148183
|
async execute(_services, params) {
|
|
148149
148184
|
const session = await requireRecordingSession(params.project_root, params.name);
|
|
@@ -148159,6 +148194,109 @@ Returns { message, stepCount, savedTo }. Fails if that flow has no recording in
|
|
|
148159
148194
|
}
|
|
148160
148195
|
};
|
|
148161
148196
|
|
|
148197
|
+
// ../tool-server/src/tools/flows/flow-finish-recording.ts
|
|
148198
|
+
init_zod();
|
|
148199
|
+
var fs54 = __toESM(require("node:fs/promises"));
|
|
148200
|
+
var zodSchema64 = external_exports.object({
|
|
148201
|
+
name: external_exports.string().describe("Name of the flow being recorded \u2014 the one passed to flow-start-recording."),
|
|
148202
|
+
project_root: external_exports.string().describe(
|
|
148203
|
+
"Absolute path to the project root of the flow being recorded \u2014 the same value passed to flow-start-recording. Together with `name` it identifies which recording to finish."
|
|
148204
|
+
)
|
|
148205
|
+
});
|
|
148206
|
+
function attachStepWarnings(summary, warnings) {
|
|
148207
|
+
if (warnings.size === 0) return summary;
|
|
148208
|
+
return summary.flatMap((line, i) => {
|
|
148209
|
+
const recorded = warnings.get(i + 1);
|
|
148210
|
+
return recorded ? [line, ` warning: ${recorded.warning}`] : [line];
|
|
148211
|
+
});
|
|
148212
|
+
}
|
|
148213
|
+
function warningHeadline(warnings, discarded) {
|
|
148214
|
+
const counts = { conversion: 0, wait: 0 };
|
|
148215
|
+
for (const { kind } of warnings.values()) counts[kind] += 1;
|
|
148216
|
+
const clauses = [];
|
|
148217
|
+
if (counts.conversion > 0) {
|
|
148218
|
+
clauses.push(
|
|
148219
|
+
`${counts.conversion} ${counts.conversion === 1 ? "step carries" : "steps carry"} a cross-tree warning about converting a recorded wait`
|
|
148220
|
+
);
|
|
148221
|
+
}
|
|
148222
|
+
if (counts.wait > 0) {
|
|
148223
|
+
clauses.push(
|
|
148224
|
+
`${counts.wait} ${counts.wait === 1 ? "step" : "steps"} recorded a wait that did not pass`
|
|
148225
|
+
);
|
|
148226
|
+
}
|
|
148227
|
+
const carried = clauses.length === 0 ? "" : ` \u2014 ${clauses.join(", and ")}; read \`summary\` before converting or replaying`;
|
|
148228
|
+
if (discarded === 0) return carried;
|
|
148229
|
+
const one = discarded === 1;
|
|
148230
|
+
const drop = `${discarded} ${one ? "warning" : "warnings"} raised during this recording ${one ? "is" : "are"} NOT in \`summary\`: a hand edit to the .yaml moved the ${one ? "step it judged" : "steps they judged"}, so which step ${one ? "it belongs" : "they belong"} to is no longer knowable \u2014 re-record ${one ? "that wait" : "those waits"} to see ${one ? "it" : "them"} again`;
|
|
148231
|
+
return carried === "" ? ` \u2014 ${drop}` : `${carried}. ${drop}`;
|
|
148232
|
+
}
|
|
148233
|
+
function anchoredWarnings(session, steps) {
|
|
148234
|
+
const kept = /* @__PURE__ */ new Map();
|
|
148235
|
+
const recorded = session.flow.steps;
|
|
148236
|
+
if (recorded.length !== steps.length) return kept;
|
|
148237
|
+
if (!steps.every((step, i) => stepAnchor(step) === stepAnchor(recorded[i]))) return kept;
|
|
148238
|
+
for (const [n, verdict] of session.stepWarnings ?? []) {
|
|
148239
|
+
const step = steps[n - 1];
|
|
148240
|
+
if (step !== void 0 && stepAnchor(step) === verdict.step) kept.set(n, verdict);
|
|
148241
|
+
}
|
|
148242
|
+
return kept;
|
|
148243
|
+
}
|
|
148244
|
+
var flowFinishRecordingTool = {
|
|
148245
|
+
id: "flow-finish-recording",
|
|
148246
|
+
interaction: {
|
|
148247
|
+
// Name the flow: other recordings stay live, so an unqualified message would
|
|
148248
|
+
// not identify which one.
|
|
148249
|
+
startedMsg: ({ params }) => `Finishing recording of flow ${params.name}`,
|
|
148250
|
+
// `params.name` equals the basename of `result.path` on every branch
|
|
148251
|
+
// (`assertSafeFlowName` admits no dots or separators), and matches the two
|
|
148252
|
+
// formatters either side.
|
|
148253
|
+
completedMsg: ({ params }) => `Saved recorded flow ${params.name}`,
|
|
148254
|
+
failedMsg: ({ params, failureSignal: failureSignal2 }) => `Failed to finish recording of flow ${params.name}: ${failureSignal2.error_code}`
|
|
148255
|
+
},
|
|
148256
|
+
description: `Finish recording the flow named by \`name\` + \`project_root\`, leaving recordings under any other key untouched. Returns { message, path, executionPrerequisite, steps, summary, flowFile, savedTo } - a summary of all recorded steps plus the final YAML. Use when you have added all desired steps and want to finalize the flow file. Fails if that flow has no recording in progress.
|
|
148257
|
+
A warning flow-add-step raised on a recorded \`await-ui-element\` is repeated in \`summary\` as a \`warning:\` line of its own, right below the step it judges, and \`message\` counts them by kind. A warning is repeated only while the step it judges is still identifiable by its number: hand-editing the .yaml during the recording moves the steps, so those warnings are DROPPED rather than pinned on whichever step inherited the number, and \`message\` says how many were dropped. A step that carries a cross-tree warning was re-probed against the runner's tree: read it before converting that wait to \`await:\`/\`assert:\`, which is what the verdict is about and what this moment is for. A step that recorded a wait which did not pass was never probed at all, and its own warning names the CAUSE, because only one of them judges the condition: an unmet wait was read and found false, and it stops the run at replay; a wait whose tree source could not be read, or one that was cancelled, observed nothing and leaves the condition UNKNOWN rather than known-bad. Read those before replaying.
|
|
148258
|
+
You can still edit the .yaml file directly afterwards to remove or reorder steps.`,
|
|
148259
|
+
zodSchema: zodSchema64,
|
|
148260
|
+
services: () => ({}),
|
|
148261
|
+
async execute(_services, params) {
|
|
148262
|
+
const { filePath, flowFile, savedTo, flow, summary, headline } = await withFlowFileLock(
|
|
148263
|
+
params.project_root,
|
|
148264
|
+
params.name,
|
|
148265
|
+
async () => {
|
|
148266
|
+
const session = await requireRecordingSession(params.project_root, params.name);
|
|
148267
|
+
const filePath2 = session.filePath;
|
|
148268
|
+
let flowFile2;
|
|
148269
|
+
let savedTo2;
|
|
148270
|
+
if (session.persist === "client") {
|
|
148271
|
+
flowFile2 = serializeFlow(session.flow);
|
|
148272
|
+
savedTo2 = clientFileDirective(filePath2, flowFile2);
|
|
148273
|
+
} else {
|
|
148274
|
+
flowFile2 = await fs54.readFile(filePath2, "utf8");
|
|
148275
|
+
savedTo2 = filePath2;
|
|
148276
|
+
}
|
|
148277
|
+
const flow2 = parseFlow(flowFile2);
|
|
148278
|
+
const anchored = anchoredWarnings(session, flow2.steps);
|
|
148279
|
+
const summary2 = attachStepWarnings(summarizeSteps(flow2), anchored);
|
|
148280
|
+
const discarded = (session.discardedWarnings ?? 0) + (session.stepWarnings?.size ?? 0) - anchored.size;
|
|
148281
|
+
const headline2 = warningHeadline(anchored, discarded);
|
|
148282
|
+
clearRecordingSession(session);
|
|
148283
|
+
return { filePath: filePath2, flowFile: flowFile2, savedTo: savedTo2, flow: flow2, summary: summary2, headline: headline2 };
|
|
148284
|
+
}
|
|
148285
|
+
);
|
|
148286
|
+
return {
|
|
148287
|
+
// Name the counts in `message` as well. A caller that reads only
|
|
148288
|
+
// `message` would otherwise polish blind.
|
|
148289
|
+
message: `Finished recording "${params.name}" flow (${flow.steps.length} steps)` + headline,
|
|
148290
|
+
path: filePath,
|
|
148291
|
+
executionPrerequisite: flow.executionPrerequisite,
|
|
148292
|
+
steps: flow.steps.length,
|
|
148293
|
+
summary,
|
|
148294
|
+
flowFile,
|
|
148295
|
+
savedTo
|
|
148296
|
+
};
|
|
148297
|
+
}
|
|
148298
|
+
};
|
|
148299
|
+
|
|
148162
148300
|
// ../tool-server/src/tools/flows/flow-run.ts
|
|
148163
148301
|
init_zod();
|
|
148164
148302
|
var fs57 = __toESM(require("node:fs/promises"));
|
|
@@ -151345,88 +151483,6 @@ function pushReport(state3, report) {
|
|
|
151345
151483
|
state3.reports.push(report);
|
|
151346
151484
|
state3.onStepReport?.(report);
|
|
151347
151485
|
}
|
|
151348
|
-
function selectorLabel2(sel) {
|
|
151349
|
-
const parts2 = [];
|
|
151350
|
-
if (sel.any) parts2.push("*");
|
|
151351
|
-
if (sel.text !== void 0) parts2.push(`"${sel.text}"`);
|
|
151352
|
-
if (sel.textMatches !== void 0) parts2.push(`/${sel.textMatches}/`);
|
|
151353
|
-
if (sel.identifier) parts2.push(`id=${sel.identifier}`);
|
|
151354
|
-
if (sel.role) parts2.push(`role=${sel.role}`);
|
|
151355
|
-
for (const relation of SELECTOR_RELATIONS) {
|
|
151356
|
-
const scope = sel[relation];
|
|
151357
|
-
if (scope !== void 0) parts2.push(`${relation} (${selectorLabel2(scope)})`);
|
|
151358
|
-
}
|
|
151359
|
-
return parts2.join(" ");
|
|
151360
|
-
}
|
|
151361
|
-
function conditionLabel(cond, renderSelector) {
|
|
151362
|
-
const sel = renderSelector(cond.selector);
|
|
151363
|
-
if (cond.condition === "text") {
|
|
151364
|
-
return `${sel} ${describeTextExpectation(cond.expectedText, cond.textMatch)}`;
|
|
151365
|
-
}
|
|
151366
|
-
return `${cond.condition} ${sel}`;
|
|
151367
|
-
}
|
|
151368
|
-
function gestureTargetLabel(target) {
|
|
151369
|
-
return "selector" in target ? selectorLabel2(target.selector) : `(${target.x}, ${target.y})`;
|
|
151370
|
-
}
|
|
151371
|
-
function stepTarget(step) {
|
|
151372
|
-
switch (step.kind) {
|
|
151373
|
-
case "tap":
|
|
151374
|
-
case "long-press":
|
|
151375
|
-
if (step.selector) return selectorLabel2(step.selector);
|
|
151376
|
-
if (step.x !== void 0 && step.y !== void 0) return `(${step.x}, ${step.y})`;
|
|
151377
|
-
return void 0;
|
|
151378
|
-
case "swipe": {
|
|
151379
|
-
let travel;
|
|
151380
|
-
if (step.direction !== void 0) {
|
|
151381
|
-
travel = step.direction;
|
|
151382
|
-
} else if (step.by !== void 0) {
|
|
151383
|
-
travel = `by ${swipeByLabel(step.by)}`;
|
|
151384
|
-
} else if (step.to !== void 0) {
|
|
151385
|
-
travel = `to ${gestureTargetLabel(step.to)}`;
|
|
151386
|
-
} else {
|
|
151387
|
-
return void 0;
|
|
151388
|
-
}
|
|
151389
|
-
return `${travel}${step.from ? ` from ${gestureTargetLabel(step.from)}` : ""}`;
|
|
151390
|
-
}
|
|
151391
|
-
case "type":
|
|
151392
|
-
return `into ${selectorLabel2(step.into)}`;
|
|
151393
|
-
case "await":
|
|
151394
|
-
case "assert":
|
|
151395
|
-
return conditionLabel(step, selectorLabel2);
|
|
151396
|
-
case "idle":
|
|
151397
|
-
return void 0;
|
|
151398
|
-
case "when":
|
|
151399
|
-
return step.condition.kind === "platform" ? `platform ${step.condition.platform}` : conditionLabel(step.condition, selectorLabel2);
|
|
151400
|
-
case "scroll-to": {
|
|
151401
|
-
const dir = step.direction !== "down" ? ` (${step.direction})` : "";
|
|
151402
|
-
return `${selectorLabel2(step.target)}${dir}`;
|
|
151403
|
-
}
|
|
151404
|
-
case "pinch": {
|
|
151405
|
-
const scale = `scale ${step.scale}`;
|
|
151406
|
-
return step.selector ? `${selectorLabel2(step.selector)} (${scale})` : scale;
|
|
151407
|
-
}
|
|
151408
|
-
case "rotate": {
|
|
151409
|
-
const by = `by ${step.by}\xB0`;
|
|
151410
|
-
return step.selector ? `${selectorLabel2(step.selector)} (${by})` : by;
|
|
151411
|
-
}
|
|
151412
|
-
case "snapshot":
|
|
151413
|
-
return step.cropOn ? `"${step.name}" cropOn ${selectorLabel2(step.cropOn)}` : `"${step.name}"`;
|
|
151414
|
-
case "run":
|
|
151415
|
-
return step.flow;
|
|
151416
|
-
case "echo":
|
|
151417
|
-
case "tool":
|
|
151418
|
-
return void 0;
|
|
151419
|
-
case "launch":
|
|
151420
|
-
return void 0;
|
|
151421
|
-
case "wait":
|
|
151422
|
-
return void 0;
|
|
151423
|
-
default: {
|
|
151424
|
-
const unclassified = step;
|
|
151425
|
-
void unclassified;
|
|
151426
|
-
return void 0;
|
|
151427
|
-
}
|
|
151428
|
-
}
|
|
151429
|
-
}
|
|
151430
151486
|
function scopeFlow(scope) {
|
|
151431
151487
|
return scope.runStack[scope.runStack.length - 1].display;
|
|
151432
151488
|
}
|
|
@@ -151514,10 +151570,6 @@ async function execSteps(state3, steps, scope) {
|
|
|
151514
151570
|
if (report.status === "fail" || report.status === "error") state3.stopped = true;
|
|
151515
151571
|
}
|
|
151516
151572
|
}
|
|
151517
|
-
function describeWhenCondition(cond) {
|
|
151518
|
-
if (cond.kind === "platform") return `platform ${cond.platform}`;
|
|
151519
|
-
return conditionLabel(cond, describeSelector);
|
|
151520
|
-
}
|
|
151521
151573
|
function reportBlockSkipped(state3, steps, scope, reason) {
|
|
151522
151574
|
for (const step of steps) {
|
|
151523
151575
|
pushReport(state3, {
|
|
@@ -152509,7 +152561,7 @@ var updateArgentTool = {
|
|
|
152509
152561
|
});
|
|
152510
152562
|
child.unref();
|
|
152511
152563
|
}, 2e3);
|
|
152512
|
-
const
|
|
152564
|
+
const targetLabel = effectiveTarget === "both" ? "global and project-local installs" : `${effectiveTarget} install`;
|
|
152513
152565
|
const otherHint = requested === "auto" && resolved !== "both" ? resolved === "local" ? ` If you also have a global install, call this tool again with target "global" to update it too.` : ` If you also have a project-local install, run \`argent update --local\` in that project to update it too.` : "";
|
|
152514
152566
|
const bothDegradedNote = resolved === "both" && effectiveTarget === "global" ? ` The project-local install was skipped: no project declaring ${PACKAGE_NAME2} could be located from this server \u2014 run \`argent update --local\` in the project directory for it.` : "";
|
|
152515
152567
|
const versionInfo = targetsOnlyRunningInstall ? `(v${currentVersion} -> v${installableVersion}) ` : "";
|
|
@@ -152517,7 +152569,7 @@ var updateArgentTool = {
|
|
|
152517
152569
|
const coversRunningInstall = targetsOnlyRunningInstall || effectiveTarget === "both";
|
|
152518
152570
|
const restartNote = coversRunningInstall ? ` The tool server will stop and restart automatically once the update is installed. Subsequent tool calls will reconnect to the updated server.` : ` This session's tool server is not affected and keeps running; the update applies only to the targeted install.`;
|
|
152519
152571
|
return {
|
|
152520
|
-
message: `Argent update initiated ${versionInfo}for the ${
|
|
152572
|
+
message: `Argent update initiated ${versionInfo}for the ${targetLabel}.` + crossTargetNote + restartNote + `${otherHint}${bothDegradedNote}`
|
|
152521
152573
|
};
|
|
152522
152574
|
}
|
|
152523
152575
|
};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED