@bubblegum-ai/node 0.0.6-alpha.0 → 0.0.6-alpha.10
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 +92 -1
- package/dist/cjs/client.d.ts.map +1 -0
- package/dist/cjs/client.js +118 -0
- package/dist/cjs/client.js.map +1 -0
- package/dist/cjs/errors.d.ts.map +1 -0
- package/dist/cjs/errors.js +16 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/{index.d.ts → cjs/index.d.ts} +1 -1
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +23 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/protocol.d.ts.map +1 -0
- package/dist/cjs/protocol.js +31 -0
- package/dist/cjs/protocol.js.map +1 -0
- package/dist/cjs/session.d.ts +191 -0
- package/dist/cjs/session.d.ts.map +1 -0
- package/dist/cjs/session.js +275 -0
- package/dist/cjs/session.js.map +1 -0
- package/dist/cjs/types.d.ts +76 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +10 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/client.d.ts +56 -0
- package/dist/esm/client.d.ts.map +1 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/errors.d.ts +7 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +17 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/protocol.d.ts +53 -0
- package/dist/esm/protocol.d.ts.map +1 -0
- package/dist/esm/protocol.js.map +1 -0
- package/dist/esm/session.d.ts +191 -0
- package/dist/esm/session.d.ts.map +1 -0
- package/dist/esm/session.js +271 -0
- package/dist/esm/session.js.map +1 -0
- package/dist/esm/types.d.ts +76 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +16 -6
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js.map +0 -1
- package/dist/session.d.ts +0 -85
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -141
- package/dist/session.js.map +0 -1
- package/dist/types.d.ts +0 -40
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- /package/dist/{client.d.ts → cjs/client.d.ts} +0 -0
- /package/dist/{errors.d.ts → cjs/errors.d.ts} +0 -0
- /package/dist/{protocol.d.ts → cjs/protocol.d.ts} +0 -0
- /package/dist/{client.js → esm/client.js} +0 -0
- /package/dist/{errors.js → esm/errors.js} +0 -0
- /package/dist/{index.js → esm/index.js} +0 -0
- /package/dist/{protocol.js → esm/protocol.js} +0 -0
- /package/dist/{types.js → esm/types.js} +0 -0
package/README.md
CHANGED
|
@@ -63,6 +63,50 @@ const r = await bg.recover({ failedSelector: "#login-btn", intent: "Click Login"
|
|
|
63
63
|
// r.status === "recovered" when Bubblegum healed it
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### Dynamic-value tokens (dates/times + uniqueness)
|
|
67
|
+
|
|
68
|
+
For any field that needs a value computed at run time, drop a `{{ ... }}` token
|
|
69
|
+
into the step value instead of a literal that goes stale or collides.
|
|
70
|
+
|
|
71
|
+
**Relative dates/times** — date pickers and any date field:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
await bg.act('Enter "{{today+7d|%d/%m/%Y}}" into Start date'); // -> 23/06/2026
|
|
75
|
+
await bg.act('Enter "{{now+2h|%d/%m/%Y %H:%M}}" into Appointment'); // -> 16/06/2026 04:00
|
|
76
|
+
await bg.act('Enter "{{tomorrow|%d/%m/%Y}}" into End date');
|
|
77
|
+
await bg.act('Enter "{{today+2d@07:00|%d/%m/%Y %H:%M}}" into Start'); // -> 05/07/2026 07:00
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
- **Bases:** `today`, `now`, `tomorrow`, `yesterday`.
|
|
81
|
+
- **Offsets (chainable, signed):** `+7d` `-3d` `+2w` `+1mo` `-1y` `+2h` `+30min` `+45s`
|
|
82
|
+
(`mo` = months, `min` = minutes — spelled out so a bare `m` is never ambiguous).
|
|
83
|
+
- **Absolute time (`@`, after offsets):** `@07:00` `@7am` `@9:30pm` `@23:59` `@07:00:00`
|
|
84
|
+
— pins a specific clock time (e.g. "2 days out at 7am"). With `@` and no `|`
|
|
85
|
+
format, output defaults to `%Y-%m-%d %H:%M`.
|
|
86
|
+
- **Format:** anything after `|` is a `strftime` pattern. Defaults are
|
|
87
|
+
`%Y-%m-%d` for date bases and `%Y-%m-%d %H:%M` for `now`.
|
|
88
|
+
|
|
89
|
+
**Uniqueness** — for a field whose value must differ on every run (a badge
|
|
90
|
+
name, an email, any create-form field with a unique constraint):
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
await bg.act('Enter "Badge_{{timestamp}}" into Display Name'); // -> Badge_1751558400
|
|
94
|
+
await bg.act('Enter "Badge_{{timestamp|%Y%m%d%H%M%S}}" into Display Name'); // -> Badge_20260703153012
|
|
95
|
+
await bg.act('Enter "user_{{uuid:8}}@test.com" into Email'); // -> user_3f9a1c02@test.com
|
|
96
|
+
await bg.act('Enter "SKU-{{random:6}}" into Code'); // -> SKU-402913
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- **`timestamp`** — Unix epoch **seconds**; `:ms` for milliseconds (tighter
|
|
100
|
+
uniqueness in fast loops), or a `|` `strftime` for a readable stamp such as
|
|
101
|
+
`{{timestamp|%Y%m%d%H%M%S}}`.
|
|
102
|
+
- **`uuid`** — a random UUID hex string (32 chars); `:N` keeps the first `N`
|
|
103
|
+
chars, e.g. `{{uuid:8}}`. Unique regardless of the clock.
|
|
104
|
+
- **`random`** — a run of random digits, default 6; `:N` for `N` digits.
|
|
105
|
+
|
|
106
|
+
Token-free values (and any `{{...}}` that isn't a recognised expression) are
|
|
107
|
+
passed through unchanged, so existing literal steps are unaffected. Expansion
|
|
108
|
+
happens engine-side, so it works identically for web, mobile, and CDP attach.
|
|
109
|
+
|
|
66
110
|
### Mobile
|
|
67
111
|
|
|
68
112
|
```ts
|
|
@@ -110,12 +154,44 @@ otherwise. CDP attach is Chromium-only.
|
|
|
110
154
|
| `bg.isVisible / isChecked / selectedValue(target)` | `Promise<boolean \| string>` | |
|
|
111
155
|
| `bg.explain(instruction)` | `Promise<string>` | dry-run rationale |
|
|
112
156
|
| `bg.summary()` | `Promise<SessionSummary>` | |
|
|
157
|
+
| `bg.report(opts)` | `Promise<ReportResult>` | write Allure/HTML/JSON/JUnit from the run |
|
|
113
158
|
| `bg.close()` | `Promise<void>` | closes the session + bridge |
|
|
114
159
|
|
|
115
160
|
`options` is forwarded verbatim to the engine (`timeout_ms`, `selector`,
|
|
116
161
|
`action_type`, `value`, `assertion_type`, `expected_value`, `max_cost_level`, …),
|
|
117
162
|
matching the Python how-to guides.
|
|
118
163
|
|
|
164
|
+
### Reports (Allure / HTML / JSON / JUnit)
|
|
165
|
+
|
|
166
|
+
The engine remembers every step a session runs, so you can emit the same reports
|
|
167
|
+
the Python/pytest path produces — no pytest required. Call `bg.report(...)` once
|
|
168
|
+
near the end (in a `finally`, before `close()`):
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
try {
|
|
172
|
+
await bg.act('Enter "tom" into Username');
|
|
173
|
+
await bg.act("Click Login");
|
|
174
|
+
await bg.verify("Dashboard is visible");
|
|
175
|
+
} finally {
|
|
176
|
+
await bg.report({
|
|
177
|
+
html: "reports/run.html", // single-file HTML
|
|
178
|
+
allure: "allure-results", // Allure 2 dir -> `allure serve allure-results`
|
|
179
|
+
junit: "reports/junit.xml", // CI ingestion
|
|
180
|
+
json: "reports/run.json", // machine-readable
|
|
181
|
+
title: "Smoke run",
|
|
182
|
+
suiteName: "h365-portal",
|
|
183
|
+
});
|
|
184
|
+
await bg.close();
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Each format is optional; pass `true` instead of a path to use the default name
|
|
189
|
+
(`bubblegum_report.html` / `.json` / `.xml`, `allure-results/`). Paths are
|
|
190
|
+
resolved relative to the **engine process's working directory** (where the bridge
|
|
191
|
+
was spawned — normally your project root). Returns
|
|
192
|
+
`{ written: { html: "/abs/…", … }, steps }`. Requires the engine to advertise
|
|
193
|
+
`report.write` (Bubblegum ≥ 0.0.6); older engines throw a clear error.
|
|
194
|
+
|
|
119
195
|
### Advanced: `BridgeClient`
|
|
120
196
|
|
|
121
197
|
`Bubblegum` wraps a lower-level `BridgeClient` (`bg.bridge`) that you can use
|
|
@@ -129,11 +205,26 @@ The client pins to a compatible engine. It refuses to start against a
|
|
|
129
205
|
keep serving older clients (additive-first). This package's major/minor track the
|
|
130
206
|
engine; install a matching `bubblegum-ai`.
|
|
131
207
|
|
|
208
|
+
## Module formats (ESM + CommonJS)
|
|
209
|
+
|
|
210
|
+
This package ships **both** ES modules and CommonJS, so it works whether your
|
|
211
|
+
test runner loads ESM or CJS — no `.mts` rename or loader flags needed:
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
import { Bubblegum } from "@bubblegum-ai/node"; // ESM / TypeScript
|
|
215
|
+
```
|
|
216
|
+
```js
|
|
217
|
+
const { Bubblegum } = require("@bubblegum-ai/node"); // CommonJS (e.g. Jest default)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Node picks `dist/esm` for `import` and `dist/cjs` for `require` via the package
|
|
221
|
+
`exports` map; TypeScript types resolve for both.
|
|
222
|
+
|
|
132
223
|
## Develop
|
|
133
224
|
|
|
134
225
|
```bash
|
|
135
226
|
npm install
|
|
136
|
-
npm run build # tsc -> dist/
|
|
227
|
+
npm run build # tsc -> dist/esm (ESM) + dist/cjs (CommonJS)
|
|
137
228
|
npm test # build + node:test (no Python needed; mock transport)
|
|
138
229
|
npm run typecheck
|
|
139
230
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,SAAS,EAIV,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,kDAAkD;IAClD,MAAM,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACzC,oFAAoF;IACpF,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACzC,0BAA0B;IAC1B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,YAAiB,GAAG,SAAS,CA2BvE;AAOD,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,kFAAkF;IAClF,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,MAAM,CAAS;IACvB,sDAAsD;IACtD,aAAa,CAAC,EAAE,SAAS,CAAC;gBAEd,IAAI,GAAE,mBAAwB;IAM1C,OAAO,CAAC,MAAM;IAoBd,OAAO,CAAC,OAAO;IAOf,4FAA4F;IAC5F,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAYtF,gFAAgF;IAC1E,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC;IAarC,2EAA2E;IAC3E,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BridgeClient = void 0;
|
|
4
|
+
exports.spawnBridgeTransport = spawnBridgeTransport;
|
|
5
|
+
const node_child_process_1 = require("node:child_process");
|
|
6
|
+
const node_readline_1 = require("node:readline");
|
|
7
|
+
const errors_js_1 = require("./errors.js");
|
|
8
|
+
const protocol_js_1 = require("./protocol.js");
|
|
9
|
+
/** Spawn the Python bridge as a child process and frame JSON-RPC over its stdio. */
|
|
10
|
+
function spawnBridgeTransport(opts = {}) {
|
|
11
|
+
const command = opts.command ?? "python";
|
|
12
|
+
const args = opts.args ?? ["-m", "bubblegum.bridge"];
|
|
13
|
+
const child = (0, node_child_process_1.spawn)(command, args, {
|
|
14
|
+
cwd: opts.cwd,
|
|
15
|
+
env: opts.env,
|
|
16
|
+
stdio: ["pipe", "pipe", "inherit"], // engine logs/errors pass through to our stderr
|
|
17
|
+
});
|
|
18
|
+
const rl = (0, node_readline_1.createInterface)({ input: child.stdout });
|
|
19
|
+
return {
|
|
20
|
+
send(line) {
|
|
21
|
+
child.stdin.write(line + "\n");
|
|
22
|
+
},
|
|
23
|
+
onLine(cb) {
|
|
24
|
+
rl.on("line", cb);
|
|
25
|
+
},
|
|
26
|
+
onClose(cb) {
|
|
27
|
+
child.on("error", (err) => cb(err));
|
|
28
|
+
child.on("exit", () => cb());
|
|
29
|
+
},
|
|
30
|
+
async close() {
|
|
31
|
+
rl.close();
|
|
32
|
+
child.stdin.end();
|
|
33
|
+
if (child.exitCode === null)
|
|
34
|
+
child.kill();
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Low-level JSON-RPC client over a {@link Transport}: assigns request ids,
|
|
40
|
+
* correlates responses, surfaces engine errors as {@link BridgeError}, and
|
|
41
|
+
* negotiates the protocol version via {@link BridgeClient.handshake}.
|
|
42
|
+
*/
|
|
43
|
+
class BridgeClient {
|
|
44
|
+
transport;
|
|
45
|
+
pending = new Map();
|
|
46
|
+
nextId = 1;
|
|
47
|
+
closed = false;
|
|
48
|
+
/** Populated after a successful {@link handshake}. */
|
|
49
|
+
handshakeInfo;
|
|
50
|
+
constructor(opts = {}) {
|
|
51
|
+
this.transport = opts.transport ?? spawnBridgeTransport(opts.spawn);
|
|
52
|
+
this.transport.onLine((line) => this.onLine(line));
|
|
53
|
+
this.transport.onClose((err) => this.onClose(err));
|
|
54
|
+
}
|
|
55
|
+
onLine(line) {
|
|
56
|
+
const trimmed = line.trim();
|
|
57
|
+
if (!trimmed)
|
|
58
|
+
return;
|
|
59
|
+
let msg;
|
|
60
|
+
try {
|
|
61
|
+
msg = JSON.parse(trimmed);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return; // ignore non-JSON noise on the channel
|
|
65
|
+
}
|
|
66
|
+
if (typeof msg.id !== "number")
|
|
67
|
+
return; // we only issue numeric ids
|
|
68
|
+
const pending = this.pending.get(msg.id);
|
|
69
|
+
if (!pending)
|
|
70
|
+
return;
|
|
71
|
+
this.pending.delete(msg.id);
|
|
72
|
+
if ((0, protocol_js_1.isErrorResponse)(msg)) {
|
|
73
|
+
pending.reject(new errors_js_1.BridgeError(msg.error.code, msg.error.message, msg.error.data));
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
pending.resolve(msg.result);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
onClose(err) {
|
|
80
|
+
this.closed = true;
|
|
81
|
+
const reason = err ?? new errors_js_1.BridgeError(protocol_js_1.ErrorCodes.InternalError, "bridge connection closed");
|
|
82
|
+
for (const [, pending] of this.pending)
|
|
83
|
+
pending.reject(reason);
|
|
84
|
+
this.pending.clear();
|
|
85
|
+
}
|
|
86
|
+
/** Issue a request and resolve with its `result` (or reject with a {@link BridgeError}). */
|
|
87
|
+
request(method, params = {}) {
|
|
88
|
+
if (this.closed) {
|
|
89
|
+
return Promise.reject(new errors_js_1.BridgeError(protocol_js_1.ErrorCodes.InternalError, "bridge is closed"));
|
|
90
|
+
}
|
|
91
|
+
const id = this.nextId++;
|
|
92
|
+
const payload = { jsonrpc: "2.0", id, method, params };
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
this.pending.set(id, { resolve: resolve, reject });
|
|
95
|
+
this.transport.send(JSON.stringify(payload));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** Negotiate with the engine; throws if its protocol version is unsupported. */
|
|
99
|
+
async handshake() {
|
|
100
|
+
const info = await this.request("handshake");
|
|
101
|
+
if (!protocol_js_1.SUPPORTED_PROTOCOL_VERSIONS.includes(info.protocol_version)) {
|
|
102
|
+
throw new errors_js_1.BridgeError(protocol_js_1.ErrorCodes.Unsupported, `engine protocol v${info.protocol_version} is not supported by this client ` +
|
|
103
|
+
`(supports: ${protocol_js_1.SUPPORTED_PROTOCOL_VERSIONS.join(", ")}). Upgrade @bubblegum-ai/node.`);
|
|
104
|
+
}
|
|
105
|
+
this.handshakeInfo = info;
|
|
106
|
+
return info;
|
|
107
|
+
}
|
|
108
|
+
/** True if the engine advertised the given capability in its handshake. */
|
|
109
|
+
hasCapability(name) {
|
|
110
|
+
return this.handshakeInfo?.capabilities.includes(name) ?? false;
|
|
111
|
+
}
|
|
112
|
+
async close() {
|
|
113
|
+
await this.transport.close();
|
|
114
|
+
this.onClose();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.BridgeClient = BridgeClient;
|
|
118
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;gBAEZ,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;CAM1D"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BridgeError = void 0;
|
|
4
|
+
/** An error returned by the bridge (a JSON-RPC error response) or a transport failure. */
|
|
5
|
+
class BridgeError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
data;
|
|
8
|
+
constructor(code, message, data) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "BridgeError";
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.data = data;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.BridgeError = BridgeError;
|
|
16
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":";;;AAAA,0FAA0F;AAC1F,MAAa,WAAY,SAAQ,KAAK;IAC3B,IAAI,CAAS;IACb,IAAI,CAAW;IAExB,YAAY,IAAY,EAAE,OAAe,EAAE,IAAc;QACvD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF;AAVD,kCAUC"}
|
|
@@ -13,5 +13,5 @@ export type { Transport, SpawnOptions, BridgeClientOptions } from "./client.js";
|
|
|
13
13
|
export { BridgeError } from "./errors.js";
|
|
14
14
|
export { PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, ErrorCodes, } from "./protocol.js";
|
|
15
15
|
export type { Handshake, JsonRpcResponse } from "./protocol.js";
|
|
16
|
-
export type { StepResult, StepStatus, ResolvedTarget, ErrorInfo, SessionSummary, StepOptions, } from "./types.js";
|
|
16
|
+
export type { StepResult, StepStatus, ResolvedTarget, ErrorInfo, SessionSummary, StepOptions, ReportOptions, ReportResult, } from "./types.js";
|
|
17
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEvF,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACjE,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,UAAU,GACX,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhE,YAAY,EACV,UAAU,EACV,UAAU,EACV,cAAc,EACd,SAAS,EACT,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,GACb,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @bubblegum-ai/node — Node/TypeScript client for the Bubblegum engine.
|
|
4
|
+
*
|
|
5
|
+
* Drives AI-powered, natural-language Playwright/Appium test steps from JS/TS by
|
|
6
|
+
* spawning the Python `bubblegum bridge` and speaking its JSON-RPC protocol. The
|
|
7
|
+
* Python engine stays the single source of truth for grounding; this package is
|
|
8
|
+
* a thin, typed proxy. See ../../docs/distribution-npm-and-pypi.md.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ErrorCodes = exports.SUPPORTED_PROTOCOL_VERSIONS = exports.PROTOCOL_VERSION = exports.BridgeError = exports.spawnBridgeTransport = exports.BridgeClient = exports.Bubblegum = void 0;
|
|
12
|
+
var session_js_1 = require("./session.js");
|
|
13
|
+
Object.defineProperty(exports, "Bubblegum", { enumerable: true, get: function () { return session_js_1.Bubblegum; } });
|
|
14
|
+
var client_js_1 = require("./client.js");
|
|
15
|
+
Object.defineProperty(exports, "BridgeClient", { enumerable: true, get: function () { return client_js_1.BridgeClient; } });
|
|
16
|
+
Object.defineProperty(exports, "spawnBridgeTransport", { enumerable: true, get: function () { return client_js_1.spawnBridgeTransport; } });
|
|
17
|
+
var errors_js_1 = require("./errors.js");
|
|
18
|
+
Object.defineProperty(exports, "BridgeError", { enumerable: true, get: function () { return errors_js_1.BridgeError; } });
|
|
19
|
+
var protocol_js_1 = require("./protocol.js");
|
|
20
|
+
Object.defineProperty(exports, "PROTOCOL_VERSION", { enumerable: true, get: function () { return protocol_js_1.PROTOCOL_VERSION; } });
|
|
21
|
+
Object.defineProperty(exports, "SUPPORTED_PROTOCOL_VERSIONS", { enumerable: true, get: function () { return protocol_js_1.SUPPORTED_PROTOCOL_VERSIONS; } });
|
|
22
|
+
Object.defineProperty(exports, "ErrorCodes", { enumerable: true, get: function () { return protocol_js_1.ErrorCodes; } });
|
|
23
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAEH,2CAAyC;AAAhC,uGAAA,SAAS,OAAA;AAGlB,yCAAiE;AAAxD,yGAAA,YAAY,OAAA;AAAE,iHAAA,oBAAoB,OAAA;AAG3C,yCAA0C;AAAjC,wGAAA,WAAW,OAAA;AAEpB,6CAIuB;AAHrB,+GAAA,gBAAgB,OAAA;AAChB,0HAAA,2BAA2B,OAAA;AAC3B,yGAAA,UAAU,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,yEAAyE;AACzE,eAAO,MAAM,2BAA2B,cAAe,CAAC;AAExD,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC,qEAAqE;AACrE,eAAO,MAAM,UAAU;;;;;;;;;CASb,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,SAAS,CAAC;IACd,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,oBAAoB,CAAC;AAEpE,wBAAgB,eAAe,CAAC,GAAG,EAAE,eAAe,GAAG,GAAG,IAAI,oBAAoB,CAEjF;AAED,wCAAwC;AACxC,MAAM,WAAW,SAAS;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wire protocol for the Bubblegum bridge — the TypeScript mirror of
|
|
4
|
+
* `bubblegum/bridge/protocol.py`. Keep these in lockstep with the Python side.
|
|
5
|
+
*
|
|
6
|
+
* The client negotiates against the engine via `handshake`: it feature-detects
|
|
7
|
+
* on `capabilities` and refuses to run against a `protocol_version` it does not
|
|
8
|
+
* support, so a newer engine can keep serving an older client (additive-first).
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ErrorCodes = exports.PROTOCOL_VERSION = exports.SUPPORTED_PROTOCOL_VERSIONS = void 0;
|
|
12
|
+
exports.isErrorResponse = isErrorResponse;
|
|
13
|
+
/** Protocol versions this client speaks. v1 = the 0.1.0 bridge slice. */
|
|
14
|
+
exports.SUPPORTED_PROTOCOL_VERSIONS = [1];
|
|
15
|
+
/** The latest protocol version this client was written against. */
|
|
16
|
+
exports.PROTOCOL_VERSION = 1;
|
|
17
|
+
/** JSON-RPC 2.0 + bridge error codes (mirror of the Python side). */
|
|
18
|
+
exports.ErrorCodes = {
|
|
19
|
+
ParseError: -32700,
|
|
20
|
+
InvalidRequest: -32600,
|
|
21
|
+
MethodNotFound: -32601,
|
|
22
|
+
InvalidParams: -32602,
|
|
23
|
+
InternalError: -32603,
|
|
24
|
+
SessionNotFound: -32001,
|
|
25
|
+
EngineError: -32002,
|
|
26
|
+
Unsupported: -32003,
|
|
27
|
+
};
|
|
28
|
+
function isErrorResponse(msg) {
|
|
29
|
+
return msg.error !== undefined;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/protocol.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AA2CH,0CAEC;AA3CD,yEAAyE;AAC5D,QAAA,2BAA2B,GAAG,CAAC,CAAC,CAAU,CAAC;AAExD,mEAAmE;AACtD,QAAA,gBAAgB,GAAG,CAAC,CAAC;AAElC,qEAAqE;AACxD,QAAA,UAAU,GAAG;IACxB,UAAU,EAAE,CAAC,KAAK;IAClB,cAAc,EAAE,CAAC,KAAK;IACtB,cAAc,EAAE,CAAC,KAAK;IACtB,aAAa,EAAE,CAAC,KAAK;IACrB,aAAa,EAAE,CAAC,KAAK;IACrB,eAAe,EAAE,CAAC,KAAK;IACvB,WAAW,EAAE,CAAC,KAAK;IACnB,WAAW,EAAE,CAAC,KAAK;CACX,CAAC;AAyBX,SAAgB,eAAe,CAAC,GAAoB;IAClD,OAAQ,GAA4B,CAAC,KAAK,KAAK,SAAS,CAAC;AAC3D,CAAC"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { BridgeClient, BridgeClientOptions } from "./client.js";
|
|
2
|
+
import { ReportOptions, ReportResult, SessionSummary, StepOptions, StepResult } from "./types.js";
|
|
3
|
+
export type Channel = "web" | "mobile";
|
|
4
|
+
export interface LaunchOptions extends BridgeClientOptions {
|
|
5
|
+
/** "web" (default) or "mobile". */
|
|
6
|
+
channel?: Channel;
|
|
7
|
+
/** Web: start URL to open. */
|
|
8
|
+
url?: string;
|
|
9
|
+
/** Web: run headless (default true). */
|
|
10
|
+
headless?: boolean;
|
|
11
|
+
/** Resolve-only — never execute. */
|
|
12
|
+
dryRun?: boolean;
|
|
13
|
+
/** Mobile: Appium server URL (required for the mobile channel). */
|
|
14
|
+
appiumUrl?: string;
|
|
15
|
+
/** Mobile: Appium capabilities. */
|
|
16
|
+
capabilities?: Record<string, unknown>;
|
|
17
|
+
/**
|
|
18
|
+
* Web client-owned mode: attach the engine to an existing Chromium over CDP
|
|
19
|
+
* (e.g. `http://localhost:9222`) instead of launching one, so the engine
|
|
20
|
+
* drives the same browser your test already controls. Requires the engine to
|
|
21
|
+
* advertise the `channel.web.cdp` capability.
|
|
22
|
+
*/
|
|
23
|
+
cdpEndpoint?: string;
|
|
24
|
+
/** Which existing page to attach to when using `cdpEndpoint` (default 0). */
|
|
25
|
+
pageIndex?: number;
|
|
26
|
+
}
|
|
27
|
+
/** Options for {@link Bubblegum.attach} — `cdpEndpoint` is required. */
|
|
28
|
+
export interface AttachOptions extends Omit<LaunchOptions, "channel"> {
|
|
29
|
+
cdpEndpoint: string;
|
|
30
|
+
}
|
|
31
|
+
/** One step's outcome from {@link Bubblegum.preflight}. */
|
|
32
|
+
export interface PreflightResult {
|
|
33
|
+
instruction: string;
|
|
34
|
+
/** Engine status: "dry_run" when it resolved, "failed" when it didn't. */
|
|
35
|
+
status: StepResult["status"];
|
|
36
|
+
/** True when the step resolved to a target (dry_run / passed / recovered). */
|
|
37
|
+
ok: boolean;
|
|
38
|
+
confidence: number;
|
|
39
|
+
resolver: string | null;
|
|
40
|
+
ref: string | null;
|
|
41
|
+
error: string | null;
|
|
42
|
+
}
|
|
43
|
+
/** Arguments for {@link Bubblegum.clickInTable}. */
|
|
44
|
+
export interface TableCellTarget {
|
|
45
|
+
/** Column header that identifies the cell. */
|
|
46
|
+
column: string;
|
|
47
|
+
/** Row selector: 1-based index, -1 = last, or a word like "first" / "last". */
|
|
48
|
+
row?: number | string;
|
|
49
|
+
/** Locate the row by another column's value instead of an index (e.g. a DB key). */
|
|
50
|
+
rowMatch?: Record<string, string>;
|
|
51
|
+
/** Per-call timeout. */
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
}
|
|
54
|
+
/** Arguments for {@link Bubblegum.verifyTable}. */
|
|
55
|
+
export interface TableAssertion {
|
|
56
|
+
/** Column headers that must all be present. */
|
|
57
|
+
columns?: string[];
|
|
58
|
+
/** Column -> value used to locate the row(s) (e.g. a key sourced from a DB). */
|
|
59
|
+
row?: Record<string, string>;
|
|
60
|
+
/** Column -> expected value asserted in the matched row(s). */
|
|
61
|
+
cell?: Record<string, string>;
|
|
62
|
+
/** Optional human-readable step label for the report. */
|
|
63
|
+
description?: string;
|
|
64
|
+
/** Per-call timeout; the assertion polls the table until it holds or this elapses. */
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface RecoverArgs {
|
|
68
|
+
failedSelector: string;
|
|
69
|
+
intent: string;
|
|
70
|
+
options?: StepOptions;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The ergonomic, engine-owned session. `launch()` spawns the bridge, negotiates
|
|
74
|
+
* the protocol, and opens a session whose Playwright/Appium handle lives inside
|
|
75
|
+
* the Python engine; every call here is a thin proxy to the same four primitives
|
|
76
|
+
* the Python SDK exposes, returning the identical `StepResult` shape.
|
|
77
|
+
*
|
|
78
|
+
* ```ts
|
|
79
|
+
* const bg = await Bubblegum.launch({ url: "https://example.com/login" });
|
|
80
|
+
* try {
|
|
81
|
+
* await bg.act('Enter "tom" into Username');
|
|
82
|
+
* await bg.act("Click Login");
|
|
83
|
+
* await bg.verify("Dashboard is visible");
|
|
84
|
+
* } finally {
|
|
85
|
+
* await bg.close();
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export declare class Bubblegum {
|
|
90
|
+
private readonly client;
|
|
91
|
+
private readonly sessionId;
|
|
92
|
+
private constructor();
|
|
93
|
+
/** Spawn the bridge, handshake, and open a session (engine-owned by default). */
|
|
94
|
+
static launch(opts?: LaunchOptions): Promise<Bubblegum>;
|
|
95
|
+
/**
|
|
96
|
+
* Attach the engine to a browser your test already controls, over CDP
|
|
97
|
+
* (client-owned mode). Launch your Chromium with a remote-debugging port and
|
|
98
|
+
* pass its endpoint:
|
|
99
|
+
*
|
|
100
|
+
* ```ts
|
|
101
|
+
* const browser = await chromium.launch({ args: ["--remote-debugging-port=9222"] });
|
|
102
|
+
* const bg = await Bubblegum.attach({ cdpEndpoint: "http://localhost:9222" });
|
|
103
|
+
* await bg.act("Click Login"); // drives the page your test opened
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
static attach(opts: AttachOptions): Promise<Bubblegum>;
|
|
107
|
+
/** The bridge client (for advanced use / capability checks). */
|
|
108
|
+
get bridge(): BridgeClient;
|
|
109
|
+
act(instruction: string, options?: StepOptions): Promise<StepResult>;
|
|
110
|
+
/**
|
|
111
|
+
* Dry-run a list of steps against the *current* page and report whether each
|
|
112
|
+
* one resolves — without executing anything. Lets you validate a script (or a
|
|
113
|
+
* page's worth of steps) in one batch instead of discovering failures one run
|
|
114
|
+
* at a time.
|
|
115
|
+
*
|
|
116
|
+
* Because nothing executes, steps are all checked against the page as it is
|
|
117
|
+
* now (no navigation between them) — so call it once per page (e.g. after
|
|
118
|
+
* landing on each screen) with that screen's steps.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* const report = await bg.preflight([
|
|
122
|
+
* 'Select "Active" from the Participant status dropdown',
|
|
123
|
+
* 'Select "Change of mind" from the Reason dropdown',
|
|
124
|
+
* 'Click the Submit button',
|
|
125
|
+
* ]);
|
|
126
|
+
* console.table(report); // see status / confidence / resolver per step
|
|
127
|
+
* if (report.some(r => !r.ok)) throw new Error("preflight found unresolved steps");
|
|
128
|
+
*/
|
|
129
|
+
preflight(steps: Array<string | {
|
|
130
|
+
instruction: string;
|
|
131
|
+
options?: StepOptions;
|
|
132
|
+
}>, options?: StepOptions): Promise<PreflightResult[]>;
|
|
133
|
+
verify(instruction: string, options?: StepOptions): Promise<StepResult>;
|
|
134
|
+
extract(instruction: string, options?: StepOptions): Promise<StepResult>;
|
|
135
|
+
/**
|
|
136
|
+
* Click an element inside a table cell, addressed by column + row.
|
|
137
|
+
*
|
|
138
|
+
* The cell's clickable child (a link / button) is clicked when present — ideal
|
|
139
|
+
* when the visible text is dynamic (a UUID, a DB id) and so can't be named.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* await bg.clickInTable({ column: "PPHID", row: "first" });
|
|
143
|
+
* await bg.clickInTable({ column: "PPHID", rowMatch: { Name: dbName } });
|
|
144
|
+
*/
|
|
145
|
+
clickInTable(spec: TableCellTarget): Promise<StepResult>;
|
|
146
|
+
/**
|
|
147
|
+
* Click a link by its text (exact, then case-insensitive, then substring).
|
|
148
|
+
* Handy when the link label is a dynamic value pulled from a DB.
|
|
149
|
+
*/
|
|
150
|
+
clickLink(text: string, options?: {
|
|
151
|
+
exact?: boolean;
|
|
152
|
+
timeoutMs?: number;
|
|
153
|
+
}): Promise<StepResult>;
|
|
154
|
+
/**
|
|
155
|
+
* Assert columns / cell values in a data table (Ant Design / native / ARIA).
|
|
156
|
+
*
|
|
157
|
+
* - `columns`: header names that must all be present.
|
|
158
|
+
* - `row`: column -> value used to locate the row(s) (e.g. a key from your DB).
|
|
159
|
+
* - `cell`: column -> expected value asserted in the matched row(s).
|
|
160
|
+
*
|
|
161
|
+
* At least one of `columns` / `cell` should be provided. Matching is
|
|
162
|
+
* whitespace-normalised, case-insensitive, and tolerates a value rendered
|
|
163
|
+
* inside a badge (expected is matched as a substring of the cell).
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* await bg.verifyTable({ columns: ["PPHID", "Account Status", "Profile Status"] });
|
|
167
|
+
* await bg.verifyTable({ row: { Name: dbName }, cell: { "Account Status": dbStatus } });
|
|
168
|
+
*/
|
|
169
|
+
verifyTable(spec: TableAssertion): Promise<StepResult>;
|
|
170
|
+
recover(args: RecoverArgs): Promise<StepResult>;
|
|
171
|
+
isVisible(target: string): Promise<boolean>;
|
|
172
|
+
isChecked(target: string): Promise<boolean>;
|
|
173
|
+
selectedValue(target: string): Promise<string>;
|
|
174
|
+
explain(instruction: string): Promise<string>;
|
|
175
|
+
summary(): Promise<SessionSummary>;
|
|
176
|
+
/**
|
|
177
|
+
* Write reports (Allure / HTML / JSON / JUnit) from every step this session
|
|
178
|
+
* ran, using the engine's own reporters — the same output the Python/pytest
|
|
179
|
+
* path produces. Call it once near the end of your run (e.g. in `finally`,
|
|
180
|
+
* before `close()`):
|
|
181
|
+
*
|
|
182
|
+
* ```ts
|
|
183
|
+
* await bg.report({ html: "reports/run.html", allure: "allure-results" });
|
|
184
|
+
* // -> { written: { html: "/abs/...", allure: "/abs/..." }, steps: 12 }
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
report(opts: ReportOptions): Promise<ReportResult>;
|
|
188
|
+
/** Close the engine session and tear down the bridge process. */
|
|
189
|
+
close(): Promise<void>;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGhE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAElG,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEvC,MAAM,WAAW,aAAc,SAAQ,mBAAmB;IACxD,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wEAAwE;AACxE,MAAM,WAAW,aAAc,SAAQ,IAAI,CAAC,aAAa,EAAE,SAAS,CAAC;IACnE,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC7B,8EAA8E;IAC9E,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAF5B,OAAO;IAKP,iFAAiF;WACpE,MAAM,CAAC,IAAI,GAAE,aAAkB,GAAG,OAAO,CAAC,SAAS,CAAC;IA2BjE;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC;IAItD,gEAAgE;IAChE,IAAI,MAAM,IAAI,YAAY,CAEzB;IAED,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAQpE;;;;;;;;;;;;;;;;;;OAkBG;IACG,SAAS,CACb,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,WAAW,CAAA;KAAE,CAAC,EACrE,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC;IAmB7B,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAQvE,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAQxE;;;;;;;;;OASG;IACH,YAAY,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,UAAU,CAAC;IASxD;;;OAGG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAO/F;;;;;;;;;;;;;;OAcG;IACH,WAAW,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAOtD,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IASzC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ3C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQ3C,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ9C,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQnD,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAIlC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IA2BlD,iEAAiE;IAC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|