@beryl-so/cli 0.22.0 → 0.24.1
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/README.md +7 -5
- package/dist/adapters/mcp.js +111 -15
- package/dist/beryl-test-skill.js +241 -264
- package/dist/commands/accounts.js +8 -5
- package/dist/commands/auth.js +80 -24
- package/dist/commands/config-vars.js +5 -0
- package/dist/commands/init.js +27 -10
- package/dist/commands/mailboxes.js +5 -1
- package/dist/commands/runs.js +19 -6
- package/dist/commands/tests.js +36 -6
- package/dist/device-login.js +132 -0
- package/dist/skill-tables.js +74 -0
- package/package.json +2 -2
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Table rows derive from the schema snapshot at module load, so the skill can never
|
|
2
|
+
// drift from the plan language; only the one-liners are hand-written, and parity
|
|
3
|
+
// tests fail when a schema enum gains or loses a member the docs don't cover.
|
|
4
|
+
import { ACTION_PLAN_SCHEMA } from "./schema.generated.js";
|
|
5
|
+
const defs = ACTION_PLAN_SCHEMA.$defs;
|
|
6
|
+
export const ACTION_TYPES = defs.ActionType.enum;
|
|
7
|
+
export const EXPECT_KINDS = defs.ExpectKind.enum;
|
|
8
|
+
export const EMAIL_EXTRACTS = defs.EmailExtract.enum;
|
|
9
|
+
function actionRequires(action) {
|
|
10
|
+
const rule = defs.PlanStep.allOf.find((r) => r.if.properties.action?.const === action && !r.if.properties.extract);
|
|
11
|
+
return rule?.then.required ?? [];
|
|
12
|
+
}
|
|
13
|
+
function expectRequires(kind) {
|
|
14
|
+
const rule = defs.PlanStep.allOf.find((r) => r.if.properties.expect_kind?.const === kind);
|
|
15
|
+
return rule?.then.required ?? [];
|
|
16
|
+
}
|
|
17
|
+
export const ACTION_DOCS = {
|
|
18
|
+
goto: "Navigate to `url` — a path on your app, absolute only for another origin",
|
|
19
|
+
fill: "Type `value` into the `selector` element",
|
|
20
|
+
click: "Click the `selector` element",
|
|
21
|
+
press: "Press keyboard `key` (e.g. `Enter`) on the `selector` element",
|
|
22
|
+
check: "Check the `selector` checkbox",
|
|
23
|
+
uncheck: "Uncheck the `selector` checkbox",
|
|
24
|
+
select: "Choose `option` in the `selector` dropdown",
|
|
25
|
+
hover: "Hover the `selector` element",
|
|
26
|
+
scroll: "Scroll the page (no selector) or bring `selector` into view — see below",
|
|
27
|
+
wait_for: "Wait for the `selector` element to appear",
|
|
28
|
+
expect: "Assert — kinds in the expect table below",
|
|
29
|
+
capture_count: "Bank the live count of `selector` matches under `capture_as` for a later `count_delta`",
|
|
30
|
+
await_email: "Await mail in the run inbox, bank the extracted value under `capture_as` (§5)",
|
|
31
|
+
upload: "Set a file input: `value` names a project config file — see below",
|
|
32
|
+
dialog: "Arm a one-shot accept/dismiss handler for the NEXT step's dialog — see below",
|
|
33
|
+
switch_tab: "Make another open tab the active page; `value` picks it — see below",
|
|
34
|
+
close_tab: "Close the active tab (optional `value` picks one) and fall back to the previous",
|
|
35
|
+
drag: "Drag the `selector` element onto the `value` TARGET selector",
|
|
36
|
+
};
|
|
37
|
+
export const EXPECT_DOCS = {
|
|
38
|
+
visible: "The element is visible",
|
|
39
|
+
attached: "In the DOM, maybe not shown — for carousel/slider content where `visible` is timing-flaky",
|
|
40
|
+
hidden: "The element is not visible",
|
|
41
|
+
checked: "The checkbox/radio is checked",
|
|
42
|
+
enabled: "The element is enabled",
|
|
43
|
+
disabled: "The element is disabled",
|
|
44
|
+
have_text: "The element's text EXACTLY equals `expect_text`",
|
|
45
|
+
have_value: "The input's value equals `expect_text`",
|
|
46
|
+
have_url: "The page URL contains `expect_text` (page-level, no selector)",
|
|
47
|
+
have_title: "The page title contains `expect_text` (page-level, no selector)",
|
|
48
|
+
have_count: "Exactly `expect_count` elements match `selector`",
|
|
49
|
+
persisted: "The record just created is present — a visible match for the `{{unique}}`-named row",
|
|
50
|
+
gone: "Zero matches — absent from the DOM, stronger than `hidden`",
|
|
51
|
+
count_delta: "The match count moved by signed `expect_delta` vs the `capture_ref` baseline",
|
|
52
|
+
};
|
|
53
|
+
export const EXTRACT_DOCS = {
|
|
54
|
+
code: "the one-time code",
|
|
55
|
+
link: "the sign-in/verify URL",
|
|
56
|
+
pattern: "your own regex in `extract_pattern`, exactly one capture group",
|
|
57
|
+
};
|
|
58
|
+
function table(header, rows) {
|
|
59
|
+
return [
|
|
60
|
+
`| ${header} | required fields | meaning |`,
|
|
61
|
+
"|---|---|---|",
|
|
62
|
+
...rows.map(([name, req, doc]) => `| \`${name}\` | ${req} | ${doc} |`),
|
|
63
|
+
].join("\n");
|
|
64
|
+
}
|
|
65
|
+
const fields = (names) => names.map((f) => `\`${f}\``).join(", ") || "—";
|
|
66
|
+
export function actionTable() {
|
|
67
|
+
return table("action", ACTION_TYPES.map((a) => [a, fields(actionRequires(a)), ACTION_DOCS[a] ?? ""]));
|
|
68
|
+
}
|
|
69
|
+
export function expectTable() {
|
|
70
|
+
return table("expect_kind", EXPECT_KINDS.map((k) => [k, fields(expectRequires(k)), EXPECT_DOCS[k] ?? ""]));
|
|
71
|
+
}
|
|
72
|
+
export function extractLine() {
|
|
73
|
+
return EMAIL_EXTRACTS.map((e) => `\`${e}\` (${EXTRACT_DOCS[e] ?? ""})`).join(", ");
|
|
74
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@beryl-so/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Beryl on the command line
|
|
3
|
+
"version": "0.24.1",
|
|
4
|
+
"description": "Beryl on the command line — projects, runs, the exploring agent, and an MCP server over the same commands.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://beryl.so/docs/cli",
|