@bubblegum-ai/node 0.0.6-alpha.0 → 0.0.6-alpha.2

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.
Files changed (64) hide show
  1. package/README.md +70 -1
  2. package/dist/cjs/client.d.ts.map +1 -0
  3. package/dist/cjs/client.js +118 -0
  4. package/dist/cjs/client.js.map +1 -0
  5. package/dist/cjs/errors.d.ts.map +1 -0
  6. package/dist/cjs/errors.js +16 -0
  7. package/dist/cjs/errors.js.map +1 -0
  8. package/dist/{index.d.ts → cjs/index.d.ts} +1 -1
  9. package/dist/cjs/index.d.ts.map +1 -0
  10. package/dist/cjs/index.js +23 -0
  11. package/dist/cjs/index.js.map +1 -0
  12. package/dist/cjs/package.json +3 -0
  13. package/dist/cjs/protocol.d.ts.map +1 -0
  14. package/dist/cjs/protocol.js +31 -0
  15. package/dist/cjs/protocol.js.map +1 -0
  16. package/dist/{session.d.ts → cjs/session.d.ts} +13 -1
  17. package/dist/cjs/session.d.ts.map +1 -0
  18. package/dist/cjs/session.js +180 -0
  19. package/dist/cjs/session.js.map +1 -0
  20. package/dist/{types.d.ts → cjs/types.d.ts} +29 -0
  21. package/dist/cjs/types.d.ts.map +1 -0
  22. package/dist/cjs/types.js +10 -0
  23. package/dist/cjs/types.js.map +1 -0
  24. package/dist/esm/client.d.ts +56 -0
  25. package/dist/esm/client.d.ts.map +1 -0
  26. package/dist/esm/client.js.map +1 -0
  27. package/dist/esm/errors.d.ts +7 -0
  28. package/dist/esm/errors.d.ts.map +1 -0
  29. package/dist/esm/errors.js.map +1 -0
  30. package/dist/esm/index.d.ts +17 -0
  31. package/dist/esm/index.d.ts.map +1 -0
  32. package/dist/esm/index.js.map +1 -0
  33. package/dist/esm/package.json +3 -0
  34. package/dist/esm/protocol.d.ts +53 -0
  35. package/dist/esm/protocol.d.ts.map +1 -0
  36. package/dist/esm/protocol.js.map +1 -0
  37. package/dist/esm/session.d.ts +97 -0
  38. package/dist/esm/session.d.ts.map +1 -0
  39. package/dist/{session.js → esm/session.js} +35 -0
  40. package/dist/esm/session.js.map +1 -0
  41. package/dist/esm/types.d.ts +69 -0
  42. package/dist/esm/types.d.ts.map +1 -0
  43. package/dist/esm/types.js.map +1 -0
  44. package/package.json +16 -6
  45. package/dist/client.d.ts.map +0 -1
  46. package/dist/client.js.map +0 -1
  47. package/dist/errors.d.ts.map +0 -1
  48. package/dist/errors.js.map +0 -1
  49. package/dist/index.d.ts.map +0 -1
  50. package/dist/index.js.map +0 -1
  51. package/dist/protocol.d.ts.map +0 -1
  52. package/dist/protocol.js.map +0 -1
  53. package/dist/session.d.ts.map +0 -1
  54. package/dist/session.js.map +0 -1
  55. package/dist/types.d.ts.map +0 -1
  56. package/dist/types.js.map +0 -1
  57. /package/dist/{client.d.ts → cjs/client.d.ts} +0 -0
  58. /package/dist/{errors.d.ts → cjs/errors.d.ts} +0 -0
  59. /package/dist/{protocol.d.ts → cjs/protocol.d.ts} +0 -0
  60. /package/dist/{client.js → esm/client.js} +0 -0
  61. /package/dist/{errors.js → esm/errors.js} +0 -0
  62. /package/dist/{index.js → esm/index.js} +0 -0
  63. /package/dist/{protocol.js → esm/protocol.js} +0 -0
  64. /package/dist/{types.js → esm/types.js} +0 -0
package/README.md CHANGED
@@ -63,6 +63,28 @@ 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
+ ### Parameterised dates/times (dynamic-value tokens)
67
+
68
+ For date pickers (or any field) that need a value computed at run time, drop a
69
+ `{{ ... }}` token into the step value instead of a literal that goes stale:
70
+
71
+ ```ts
72
+ // Relative date in the app's display format:
73
+ await bg.act('Enter "{{today+7d|%d/%m/%Y}}" into Start date'); // -> 23/06/2026
74
+ await bg.act('Enter "{{now+2h|%d/%m/%Y %H:%M}}" into Appointment'); // -> 16/06/2026 04:00
75
+ await bg.act('Enter "{{tomorrow|%d/%m/%Y}}" into End date');
76
+ ```
77
+
78
+ - **Bases:** `today`, `now`, `tomorrow`, `yesterday`.
79
+ - **Offsets (chainable, signed):** `+7d` `-3d` `+2w` `+1mo` `-1y` `+2h` `+30min` `+45s`
80
+ (`mo` = months, `min` = minutes — spelled out so a bare `m` is never ambiguous).
81
+ - **Format:** anything after `|` is a `strftime` pattern. Defaults are
82
+ `%Y-%m-%d` for date bases and `%Y-%m-%d %H:%M` for `now`.
83
+
84
+ Token-free values (and any `{{...}}` that isn't a recognised expression) are
85
+ passed through unchanged, so existing literal steps are unaffected. Expansion
86
+ happens engine-side, so it works identically for web, mobile, and CDP attach.
87
+
66
88
  ### Mobile
67
89
 
68
90
  ```ts
@@ -110,12 +132,44 @@ otherwise. CDP attach is Chromium-only.
110
132
  | `bg.isVisible / isChecked / selectedValue(target)` | `Promise<boolean \| string>` | |
111
133
  | `bg.explain(instruction)` | `Promise<string>` | dry-run rationale |
112
134
  | `bg.summary()` | `Promise<SessionSummary>` | |
135
+ | `bg.report(opts)` | `Promise<ReportResult>` | write Allure/HTML/JSON/JUnit from the run |
113
136
  | `bg.close()` | `Promise<void>` | closes the session + bridge |
114
137
 
115
138
  `options` is forwarded verbatim to the engine (`timeout_ms`, `selector`,
116
139
  `action_type`, `value`, `assertion_type`, `expected_value`, `max_cost_level`, …),
117
140
  matching the Python how-to guides.
118
141
 
142
+ ### Reports (Allure / HTML / JSON / JUnit)
143
+
144
+ The engine remembers every step a session runs, so you can emit the same reports
145
+ the Python/pytest path produces — no pytest required. Call `bg.report(...)` once
146
+ near the end (in a `finally`, before `close()`):
147
+
148
+ ```ts
149
+ try {
150
+ await bg.act('Enter "tom" into Username');
151
+ await bg.act("Click Login");
152
+ await bg.verify("Dashboard is visible");
153
+ } finally {
154
+ await bg.report({
155
+ html: "reports/run.html", // single-file HTML
156
+ allure: "allure-results", // Allure 2 dir -> `allure serve allure-results`
157
+ junit: "reports/junit.xml", // CI ingestion
158
+ json: "reports/run.json", // machine-readable
159
+ title: "Smoke run",
160
+ suiteName: "h365-portal",
161
+ });
162
+ await bg.close();
163
+ }
164
+ ```
165
+
166
+ Each format is optional; pass `true` instead of a path to use the default name
167
+ (`bubblegum_report.html` / `.json` / `.xml`, `allure-results/`). Paths are
168
+ resolved relative to the **engine process's working directory** (where the bridge
169
+ was spawned — normally your project root). Returns
170
+ `{ written: { html: "/abs/…", … }, steps }`. Requires the engine to advertise
171
+ `report.write` (Bubblegum ≥ 0.0.6); older engines throw a clear error.
172
+
119
173
  ### Advanced: `BridgeClient`
120
174
 
121
175
  `Bubblegum` wraps a lower-level `BridgeClient` (`bg.bridge`) that you can use
@@ -129,11 +183,26 @@ The client pins to a compatible engine. It refuses to start against a
129
183
  keep serving older clients (additive-first). This package's major/minor track the
130
184
  engine; install a matching `bubblegum-ai`.
131
185
 
186
+ ## Module formats (ESM + CommonJS)
187
+
188
+ This package ships **both** ES modules and CommonJS, so it works whether your
189
+ test runner loads ESM or CJS — no `.mts` rename or loader flags needed:
190
+
191
+ ```ts
192
+ import { Bubblegum } from "@bubblegum-ai/node"; // ESM / TypeScript
193
+ ```
194
+ ```js
195
+ const { Bubblegum } = require("@bubblegum-ai/node"); // CommonJS (e.g. Jest default)
196
+ ```
197
+
198
+ Node picks `dist/esm` for `import` and `dist/cjs` for `require` via the package
199
+ `exports` map; TypeScript types resolve for both.
200
+
132
201
  ## Develop
133
202
 
134
203
  ```bash
135
204
  npm install
136
- npm run build # tsc -> dist/
205
+ npm run build # tsc -> dist/esm (ESM) + dist/cjs (CommonJS)
137
206
  npm test # build + node:test (no Python needed; mock transport)
138
207
  npm run typecheck
139
208
  ```
@@ -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,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -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"}
@@ -1,5 +1,5 @@
1
1
  import { BridgeClient, BridgeClientOptions } from "./client.js";
2
- import { SessionSummary, StepOptions, StepResult } from "./types.js";
2
+ import { ReportOptions, ReportResult, SessionSummary, StepOptions, StepResult } from "./types.js";
3
3
  export type Channel = "web" | "mobile";
4
4
  export interface LaunchOptions extends BridgeClientOptions {
5
5
  /** "web" (default) or "mobile". */
@@ -79,6 +79,18 @@ export declare class Bubblegum {
79
79
  selectedValue(target: string): Promise<string>;
80
80
  explain(instruction: string): Promise<string>;
81
81
  summary(): Promise<SessionSummary>;
82
+ /**
83
+ * Write reports (Allure / HTML / JSON / JUnit) from every step this session
84
+ * ran, using the engine's own reporters — the same output the Python/pytest
85
+ * path produces. Call it once near the end of your run (e.g. in `finally`,
86
+ * before `close()`):
87
+ *
88
+ * ```ts
89
+ * await bg.report({ html: "reports/run.html", allure: "allure-results" });
90
+ * // -> { written: { html: "/abs/...", allure: "/abs/..." }, steps: 12 }
91
+ * ```
92
+ */
93
+ report(opts: ReportOptions): Promise<ReportResult>;
82
94
  /** Close the engine session and tear down the bridge process. */
83
95
  close(): Promise<void>;
84
96
  }
@@ -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,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,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,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;IAyBlD,iEAAiE;IAC3D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Bubblegum = void 0;
4
+ const client_js_1 = require("./client.js");
5
+ const errors_js_1 = require("./errors.js");
6
+ const protocol_js_1 = require("./protocol.js");
7
+ /**
8
+ * The ergonomic, engine-owned session. `launch()` spawns the bridge, negotiates
9
+ * the protocol, and opens a session whose Playwright/Appium handle lives inside
10
+ * the Python engine; every call here is a thin proxy to the same four primitives
11
+ * the Python SDK exposes, returning the identical `StepResult` shape.
12
+ *
13
+ * ```ts
14
+ * const bg = await Bubblegum.launch({ url: "https://example.com/login" });
15
+ * try {
16
+ * await bg.act('Enter "tom" into Username');
17
+ * await bg.act("Click Login");
18
+ * await bg.verify("Dashboard is visible");
19
+ * } finally {
20
+ * await bg.close();
21
+ * }
22
+ * ```
23
+ */
24
+ class Bubblegum {
25
+ client;
26
+ sessionId;
27
+ constructor(client, sessionId) {
28
+ this.client = client;
29
+ this.sessionId = sessionId;
30
+ }
31
+ /** Spawn the bridge, handshake, and open a session (engine-owned by default). */
32
+ static async launch(opts = {}) {
33
+ const client = new client_js_1.BridgeClient(opts);
34
+ try {
35
+ await client.handshake();
36
+ if (opts.cdpEndpoint && !client.hasCapability("channel.web.cdp")) {
37
+ throw new errors_js_1.BridgeError(protocol_js_1.ErrorCodes.Unsupported, "this engine does not support CDP attach (channel.web.cdp); upgrade bubblegum-ai");
38
+ }
39
+ const { session_id } = await client.request("session.open", {
40
+ channel: opts.channel ?? "web",
41
+ url: opts.url,
42
+ headless: opts.headless ?? true,
43
+ dry_run: opts.dryRun ?? false,
44
+ appium_url: opts.appiumUrl,
45
+ capabilities: opts.capabilities,
46
+ cdp_endpoint: opts.cdpEndpoint,
47
+ page_index: opts.pageIndex,
48
+ });
49
+ return new Bubblegum(client, session_id);
50
+ }
51
+ catch (err) {
52
+ await client.close();
53
+ throw err;
54
+ }
55
+ }
56
+ /**
57
+ * Attach the engine to a browser your test already controls, over CDP
58
+ * (client-owned mode). Launch your Chromium with a remote-debugging port and
59
+ * pass its endpoint:
60
+ *
61
+ * ```ts
62
+ * const browser = await chromium.launch({ args: ["--remote-debugging-port=9222"] });
63
+ * const bg = await Bubblegum.attach({ cdpEndpoint: "http://localhost:9222" });
64
+ * await bg.act("Click Login"); // drives the page your test opened
65
+ * ```
66
+ */
67
+ static attach(opts) {
68
+ return Bubblegum.launch({ ...opts, channel: "web" });
69
+ }
70
+ /** The bridge client (for advanced use / capability checks). */
71
+ get bridge() {
72
+ return this.client;
73
+ }
74
+ act(instruction, options) {
75
+ return this.client.request("act", {
76
+ session_id: this.sessionId,
77
+ instruction,
78
+ options,
79
+ });
80
+ }
81
+ verify(instruction, options) {
82
+ return this.client.request("verify", {
83
+ session_id: this.sessionId,
84
+ instruction,
85
+ options,
86
+ });
87
+ }
88
+ extract(instruction, options) {
89
+ return this.client.request("extract", {
90
+ session_id: this.sessionId,
91
+ instruction,
92
+ options,
93
+ });
94
+ }
95
+ recover(args) {
96
+ return this.client.request("recover", {
97
+ session_id: this.sessionId,
98
+ failed_selector: args.failedSelector,
99
+ intent: args.intent,
100
+ options: args.options,
101
+ });
102
+ }
103
+ async isVisible(target) {
104
+ const r = await this.client.request("is_visible", {
105
+ session_id: this.sessionId,
106
+ target,
107
+ });
108
+ return r.value;
109
+ }
110
+ async isChecked(target) {
111
+ const r = await this.client.request("is_checked", {
112
+ session_id: this.sessionId,
113
+ target,
114
+ });
115
+ return r.value;
116
+ }
117
+ async selectedValue(target) {
118
+ const r = await this.client.request("selected_value", {
119
+ session_id: this.sessionId,
120
+ target,
121
+ });
122
+ return r.value;
123
+ }
124
+ async explain(instruction) {
125
+ const r = await this.client.request("explain", {
126
+ session_id: this.sessionId,
127
+ instruction,
128
+ });
129
+ return r.explanation;
130
+ }
131
+ summary() {
132
+ return this.client.request("summary", { session_id: this.sessionId });
133
+ }
134
+ /**
135
+ * Write reports (Allure / HTML / JSON / JUnit) from every step this session
136
+ * ran, using the engine's own reporters — the same output the Python/pytest
137
+ * path produces. Call it once near the end of your run (e.g. in `finally`,
138
+ * before `close()`):
139
+ *
140
+ * ```ts
141
+ * await bg.report({ html: "reports/run.html", allure: "allure-results" });
142
+ * // -> { written: { html: "/abs/...", allure: "/abs/..." }, steps: 12 }
143
+ * ```
144
+ */
145
+ report(opts) {
146
+ if (!this.client.hasCapability("report.write")) {
147
+ throw new errors_js_1.BridgeError(protocol_js_1.ErrorCodes.Unsupported, "this engine does not support report generation (report.write); upgrade bubblegum-ai");
148
+ }
149
+ const resolve = (v, fallback) => v === true ? fallback : v || undefined;
150
+ const params = { session_id: this.sessionId };
151
+ const html = resolve(opts.html, "bubblegum_report.html");
152
+ const json = resolve(opts.json, "bubblegum_report.json");
153
+ const junit = resolve(opts.junit, "bubblegum_report.xml");
154
+ const allure = resolve(opts.allure, "allure-results");
155
+ if (html)
156
+ params.html = html;
157
+ if (json)
158
+ params.json = json;
159
+ if (junit)
160
+ params.junit = junit;
161
+ if (allure)
162
+ params.allure = allure;
163
+ if (opts.title)
164
+ params.title = opts.title;
165
+ if (opts.suiteName)
166
+ params.suite_name = opts.suiteName;
167
+ return this.client.request("report.write", params);
168
+ }
169
+ /** Close the engine session and tear down the bridge process. */
170
+ async close() {
171
+ try {
172
+ await this.client.request("session.close", { session_id: this.sessionId });
173
+ }
174
+ finally {
175
+ await this.client.close();
176
+ }
177
+ }
178
+ }
179
+ exports.Bubblegum = Bubblegum;
180
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/session.ts"],"names":[],"mappings":"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"}
@@ -37,4 +37,33 @@ export interface SessionSummary {
37
37
  }
38
38
  /** Per-call options forwarded verbatim to the engine SDK (timeout_ms, selector, …). */
39
39
  export type StepOptions = Record<string, unknown>;
40
+ /**
41
+ * Which reports to write from the session's accumulated step results.
42
+ *
43
+ * Each field is either an output path, or `true` to use the default name
44
+ * (`bubblegum_report.html` / `.json` / `.xml`, and `allure-results/` for
45
+ * Allure). Omit a field to skip that format. Paths are resolved relative to the
46
+ * engine process's working directory.
47
+ */
48
+ export interface ReportOptions {
49
+ /** Single-file HTML report. */
50
+ html?: string | boolean;
51
+ /** Machine-readable JSON report. */
52
+ json?: string | boolean;
53
+ /** JUnit XML (for CI test-report ingestion). */
54
+ junit?: string | boolean;
55
+ /** Allure 2 results *directory* (view with `allure serve <dir>`). */
56
+ allure?: string | boolean;
57
+ /** Report title (HTML/JSON). */
58
+ title?: string;
59
+ /** Suite name (Allure/JUnit). */
60
+ suiteName?: string;
61
+ }
62
+ /** Result of {@link Bubblegum.report}: resolved paths written, and step count. */
63
+ export interface ReportResult {
64
+ /** Format → resolved absolute path (or directory, for Allure). */
65
+ written: Record<string, string>;
66
+ /** Number of steps included in the report. */
67
+ steps: number;
68
+ }
40
69
  //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnF,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,uFAAuF;AACvF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,oCAAoC;IACpC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,kFAAkF;AAClF,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ /**
3
+ * TypeScript mirror of the engine's result schemas (`bubblegum/core/schemas.py`).
4
+ *
5
+ * Kept intentionally close to the Pydantic models. `[key: string]: unknown`
6
+ * index signatures let newer engine fields flow through without breaking the
7
+ * client (additive-first), while the named fields stay strongly typed.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG"}