haltija 1.12.1 → 1.12.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,91 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.12.2
4
+
5
+ Two fixes, both from an agent driving real apps. Each is a case where haltija reported success — or
6
+ green health — while quietly producing something you couldn't trust, which is the same thread the
7
+ 1.12.x line has been pulling on throughout.
8
+
9
+ **[#26](https://github.com/tonioloewald/haltija/issues/26) remains open and is NOT a 1.12.0
10
+ regression.** The reporter's own control run settled it: the known-bad version survived the original
11
+ failing surface through seven hard navigations plus an HMR rebuild. A tab becoming permanently
12
+ undrivable was really observed, so the issue stays open as a standing record — but neither of us can
13
+ currently reproduce it on any version, and nothing here claims to fix it.
14
+
15
+
16
+ ### `--private` instances get their own Electron profile — [#31](https://github.com/tonioloewald/haltija/issues/31)
17
+
18
+ Private mode isolated ports, the registry, retirement and teardown — but **not the Electron
19
+ profile**, so every instance ran with the same `--user-data-dir`. Chromium's single-instance locking
20
+ means the second one to launch can't take the profile lock and falls back to caches it cannot
21
+ persist, losing the HTTP cache and the V8 code cache. A large app bundle is then fully re-parsed on
22
+ every navigation: **roughly 10x slower page boots**.
23
+
24
+ The damage isn't the slowness, it's that it **lies in the one workflow private mode exists for**.
25
+ Comparing two versions side by side, the failure followed **launch order, not version** — 22.1s vs
26
+ 2.04s, the same version passing or failing depending only on which started first, and each fine
27
+ alone. The reporter nearly wrote up a version regression that did not exist. Every health signal
28
+ read green throughout, including `hj doctor` and a measured 120fps rAF cadence, because nothing was
29
+ broken — it was just slow.
30
+
31
+ Each private instance now gets `<tmpdir>/haltija-private-<pid>` as its `userData` and `sessionData`,
32
+ set before `app.whenReady()` and before anything reads `preferences.json`.
33
+
34
+ Two related leaks closed at the same time, both cases of "private" having meant *private ports*
35
+ rather than *touches nothing of yours*:
36
+
37
+ - **A private run no longer writes `~/.haltija/last-quit`.** That marker tells `hj`'s auto-launch the
38
+ user deliberately quit, so an automated run ending was suppressing auto-launch for the interactive
39
+ app a developer was using.
40
+ - **Stale private scratch is swept** at the start of the next private run — profiles and the
41
+ port-files the launcher writes (175 had accumulated on one machine). Swept at startup rather than
42
+ on exit because Chromium flushes its caches *after* `will-quit`, so deleting the profile there
43
+ just gets it recreated. The sweep keys on whether the owning pid is still alive and **never
44
+ touches a live peer** — `EPERM` from `kill(pid, 0)` counts as alive, since the process exists and
45
+ merely belongs to someone else. That decision is a tested function (`src/private-state.ts`), not a
46
+ loop in the launcher, because deleting a running instance's profile would be far worse than the
47
+ litter it tidies.
48
+
49
+ ### The test-suite runner gains `drag`, and a `wait` can no longer pass without waiting — [#30](https://github.com/tonioloewald/haltija/issues/30)
50
+
51
+ **`drag` is now a step action.** `hj drag` and `POST /drag` had shipped for releases; the runner's
52
+ dispatcher simply had no case, so a perfectly reasonable suite failed with `Unsupported step action:
53
+ drag`. Sliders, resize handles and drag-reorder lists are exactly the interactions you cannot cover
54
+ another way — a synthetic keydown on a slider thumb is not a faithful substitute.
55
+
56
+ The routine now lives in `src/drag.ts` and both `/drag` and the runner call it. Dragging is not one
57
+ message to the widget (scroll into view → measure → mouseenter/over/move → mousedown → N
58
+ interpolated mousemoves → mouseup), and a second copy in the runner's switch would have been the
59
+ fifth instance this cycle of one idea with two implementations.
60
+
61
+ **A `wait` step with nothing to wait for was reported as PASSING.** `{"action": "wait",
62
+ "forElement": "tbody tr", "timeout": 10000}` fell out of the runner's chain to `break`, and since a
63
+ step passes by default it looked green — so a guard that had never waited for anything let every
64
+ assertion after it race the page. Two fixes: `forElement` is now accepted as an alias of `selector`
65
+ (the name `/wait` uses, and the name **our own SKILL.md example used**, which means the documented
66
+ example never waited), and a `wait` carrying none of `duration`/`ms`/`selector`/`forElement`/
67
+ `forWindow`/`url` is now an **error**.
68
+
69
+ This is the same defect as the CLI's `hj wait --hidden`, fixed in 1.12.0 — that fix landed in the
70
+ CLI and never reached the runner.
71
+
72
+ **`hj test validate` now rejects illegal steps before the suite runs**, with a "did you mean":
73
+
74
+ ```
75
+ step 0: unknown step action "drg" — did you mean "drag"?. Legal actions: navigate, click, …
76
+ step 1: wait step has nothing to wait for — give it `duration` (ms), `selector` (or `forElement`) …
77
+ ```
78
+
79
+ Validation previously checked only that selectors resolved, so `{"action": "drag"}` validated clean
80
+ and then died in CI.
81
+
82
+ **And the list is published and enforced.** There was nowhere to look up the legal actions: `hj api`
83
+ documents the HTTP endpoints, which reads as though the same verbs work as steps. The canonical list
84
+ is now `TEST_STEP_ACTIONS` in `src/test-actions.ts`, printed in `SKILL.md`, `CLAUDE.md` and
85
+ `docs/CI-INTEGRATION.md` — and a test asserts it matches the runner's `switch (step.action)` in
86
+ **both** directions. Writing that guard immediately found `screenshot` documented in `SKILL.md` as a
87
+ step action when the runner has never had one.
88
+
3
89
  ## 1.12.1
4
90
 
5
91
  A patch of fixes reported by an agent driving a real React + web-components admin app against
@@ -44,6 +44,44 @@ const IS_PRIVATE = process.env.HALTIJA_PRIVATE === '1'
44
44
  // consumer (e.g. a dev-server test lane) can drive this instance.
45
45
  const CALLER_PORT_FILE = IS_PRIVATE ? (process.env.HALTIJA_PORT_FILE || null) : null
46
46
 
47
+ // A PRIVATE INSTANCE GETS ITS OWN ELECTRON PROFILE.
48
+ //
49
+ // Private mode isolated the ports, the registry, retirement and teardown — but not the profile, so
50
+ // every instance ran with the same `--user-data-dir`. Chromium single-instance locking means the
51
+ // second one to launch cannot take the profile lock and falls back to caches it cannot persist,
52
+ // losing the HTTP cache and the V8 code cache. A large app bundle is then fully re-parsed on every
53
+ // navigation: measured at roughly 10x slower page boots (issue #31).
54
+ //
55
+ // The damage is not just slowness, it is a LIE in the one workflow private mode exists for. Running
56
+ // two versions side by side, the failure followed LAUNCH ORDER rather than version — 22.1s vs 2.04s,
57
+ // and the same version passed or failed depending only on which started first. The reporter nearly
58
+ // wrote up a version regression that did not exist. Every health signal read green throughout,
59
+ // including `hj doctor` and a 120fps rAF cadence, because nothing was broken; it was just slow.
60
+ //
61
+ // Keyed on pid, not port: the private ports are ephemeral and not known yet at this point, and pid
62
+ // is unique across concurrent runs by construction. Set BEFORE `app.whenReady()` and before
63
+ // anything reads `app.getPath('userData')` (preferences.json does), or the isolation is partial —
64
+ // which is how this bug existed at all.
65
+ let PRIVATE_USER_DATA = null
66
+ if (IS_PRIVATE) {
67
+ PRIVATE_USER_DATA = path.join(os.tmpdir(), `haltija-private-${process.pid}`)
68
+ try {
69
+ fs.mkdirSync(PRIVATE_USER_DATA, { recursive: true })
70
+ app.setPath('userData', PRIVATE_USER_DATA)
71
+ // Also keep the disk cache with it, so nothing is left in the shared profile.
72
+ app.setPath('sessionData', PRIVATE_USER_DATA)
73
+ } catch (err) {
74
+ // Falling back to the shared profile is slow and pollutes it, but it still WORKS — so say so
75
+ // loudly rather than refusing to start a run over a temp-directory failure.
76
+ console.error(
77
+ `[Haltija Desktop] Could not create a private profile at ${PRIVATE_USER_DATA}: ${err.message}. ` +
78
+ `Falling back to the shared profile — concurrent private instances will be slow and are ` +
79
+ `NOT safe to compare against each other (see issue #31).`,
80
+ )
81
+ PRIVATE_USER_DATA = null
82
+ }
83
+ }
84
+
47
85
  // Haltija server config
48
86
  let HALTIJA_PORT = IS_PRIVATE ? 0 : parseInt(process.env.HALTIJA_PORT || '8700')
49
87
  let HALTIJA_SERVER = `http://localhost:${HALTIJA_PORT}`
@@ -1694,11 +1732,24 @@ if (!gotTheLock) {
1694
1732
  }
1695
1733
  // Drop a marker so hj's auto-launch knows the user explicitly quit.
1696
1734
  // Cleared next time the user manually starts Haltija.
1697
- try {
1698
- const dir = path.join(os.homedir(), '.haltija')
1699
- fs.mkdirSync(dir, { recursive: true })
1700
- fs.writeFileSync(path.join(dir, 'last-quit'), String(Date.now()))
1701
- } catch {}
1735
+ //
1736
+ // NOT in private mode: `~/.haltija/last-quit` is SHARED state, and an automated run ending is
1737
+ // not the user quitting anything. Writing it suppressed auto-launch for the interactive app the
1738
+ // developer is actually using — the same class as the profile sharing above (#31), where
1739
+ // "private" turned out to mean "private ports" rather than "touches nothing of yours".
1740
+ if (!IS_PRIVATE) {
1741
+ try {
1742
+ const dir = path.join(os.homedir(), '.haltija')
1743
+ fs.mkdirSync(dir, { recursive: true })
1744
+ fs.writeFileSync(path.join(dir, 'last-quit'), String(Date.now()))
1745
+ } catch {}
1746
+ }
1747
+
1748
+ // NOTE: the private profile is deliberately NOT deleted here. Chromium flushes its caches
1749
+ // AFTER 'will-quit', so removing the directory at this point just gets it recreated — measured:
1750
+ // both dirs survived a clean shutdown. Stale profiles are swept at the START of the next
1751
+ // private run instead (see sweepStalePrivateState in bin/tosijs-dev.mjs), keyed on whether the
1752
+ // owning pid is still alive, which is immune to shutdown ordering.
1702
1753
  })
1703
1754
 
1704
1755
  // Handle certificate errors (for self-signed certs in dev)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haltija-desktop",
3
- "version": "1.12.1",
3
+ "version": "1.12.2",
4
4
  "private": true,
5
5
  "description": "Haltija Desktop - God Mode Browser for AI Agents",
6
6
  "homepage": "https://github.com/tonioloewald/haltija",
@@ -46,7 +46,7 @@
46
46
  });
47
47
 
48
48
  // src/version.ts
49
- var VERSION = "1.12.1";
49
+ var VERSION = "1.12.2";
50
50
 
51
51
  // src/text-selector.ts
52
52
  var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\(/;
@@ -0,0 +1,29 @@
1
+ /** ⚠️ AUTO-GENERATED FROM src/private-state.ts — DO NOT EDIT. Run: bun run build */
2
+ // src/private-state.ts
3
+ function stalePrivateEntries(names, deps) {
4
+ const out = [];
5
+ for (const name of names) {
6
+ const m = /^haltija-private-(\d+)(\.json)?$/.exec(name);
7
+ if (!m)
8
+ continue;
9
+ const pid = parseInt(m[1], 10);
10
+ if (!pid || pid === deps.selfPid)
11
+ continue;
12
+ if (deps.isAlive(pid))
13
+ continue;
14
+ out.push(name);
15
+ }
16
+ return out;
17
+ }
18
+ function pidIsAlive(pid) {
19
+ try {
20
+ process.kill(pid, 0);
21
+ return true;
22
+ } catch (err) {
23
+ return err?.code === "EPERM";
24
+ }
25
+ }
26
+ export {
27
+ stalePrivateEntries,
28
+ pidIsAlive
29
+ };
@@ -13,10 +13,11 @@
13
13
  */
14
14
 
15
15
  import { spawn, execSync as execSyncImported } from 'child_process'
16
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'
16
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync } from 'fs'
17
17
  import { homedir, platform, tmpdir } from 'os'
18
18
  import { fileURLToPath } from 'url'
19
19
  import { dirname, join } from 'path'
20
+ import { stalePrivateEntries, pidIsAlive } from './private-state.mjs'
20
21
 
21
22
  const __dirname = dirname(fileURLToPath(import.meta.url))
22
23
  const serverPath = join(__dirname, '../dist/server.js')
@@ -452,8 +453,45 @@ if (privateMode) {
452
453
  ? args[portFileIdx + 1]
453
454
  : join(tmpdir(), `haltija-private-${process.pid}.json`)
454
455
  env.HALTIJA_PORT_FILE = privatePortFile
456
+ sweepStalePrivateState()
455
457
  }
456
458
 
459
+ /**
460
+ * Remove the scratch left by private runs that are no longer alive.
461
+ *
462
+ * Two kinds accumulate in tmpdir, both named `haltija-private-<pid>`:
463
+ * - the port-file (`<pid>.json`) this launcher writes
464
+ * - the Electron profile directory (issue #31), several MB of cache per run
465
+ *
466
+ * Swept at STARTUP rather than on exit because Chromium flushes its caches AFTER Electron's
467
+ * 'will-quit' fires — deleting the profile there simply gets it recreated, which is what happened
468
+ * when this was first written that way. Liveness of the owning pid is the test, so a sweep can
469
+ * never touch a concurrent run: the whole point of private mode is that instances don't interfere,
470
+ * and a cleanup that deletes a live peer's profile would be a far worse bug than the litter.
471
+ *
472
+ * Runs for `--private --headless` too, since the launcher is common to both.
473
+ */
474
+ function sweepStalePrivateState() {
475
+ const dir = tmpdir()
476
+ let entries
477
+ try {
478
+ entries = readdirSync(dir)
479
+ } catch {
480
+ return
481
+ }
482
+ // The decision lives in src/private-state.ts and is unit-tested: never sweep a live peer, never
483
+ // sweep ourselves, and treat EPERM from kill(pid,0) as ALIVE (the process exists, it is just not
484
+ // ours to signal). Getting that backwards would delete another user's running instance.
485
+ for (const name of stalePrivateEntries(entries, { selfPid: process.pid, isAlive: pidIsAlive })) {
486
+ try {
487
+ rmSync(join(dir, name), { recursive: true, force: true })
488
+ } catch {
489
+ // Best effort — the OS reaps tmpdir eventually, and failing to tidy must never stop a run.
490
+ }
491
+ }
492
+ }
493
+
494
+
457
495
  /** Poll the private instance's port-file until it reports its ephemeral port. */
458
496
  /**
459
497
  * Wait for a private instance to report its ephemeral port. 30s because this may be waiting on a
package/bin/version.mjs CHANGED
@@ -3,4 +3,4 @@
3
3
  * ⚠️ To change the version, update package.json and run: bun run build
4
4
  */
5
5
 
6
- export const HJ_VERSION = '1.12.1'
6
+ export const HJ_VERSION = '1.12.2'
@@ -68,30 +68,30 @@ export declare const tree: EndpointDef<{
68
68
  window?: string | undefined;
69
69
  }>;
70
70
  export declare const query: EndpointDef<{
71
- selector?: string | undefined;
72
71
  ref?: string | undefined;
72
+ selector?: string | undefined;
73
73
  all?: boolean | undefined;
74
74
  }>;
75
75
  export declare const inspect: EndpointDef<{
76
+ ref?: string | undefined;
76
77
  selector?: string | undefined;
77
78
  window?: string | undefined;
78
- ref?: string | undefined;
79
79
  fullStyles?: boolean | undefined;
80
80
  matchedRules?: boolean | undefined;
81
81
  }>;
82
82
  export declare const inspectAll: EndpointDef<{
83
+ ref?: string | undefined;
83
84
  selector?: string | undefined;
84
85
  window?: string | undefined;
85
- ref?: string | undefined;
86
86
  fullStyles?: boolean | undefined;
87
87
  matchedRules?: boolean | undefined;
88
88
  limit?: number | undefined;
89
89
  }>;
90
90
  export declare const click: EndpointDef<{
91
91
  text?: string | undefined;
92
+ ref?: string | undefined;
92
93
  selector?: string | undefined;
93
94
  window?: string | undefined;
94
- ref?: string | undefined;
95
95
  tag?: string | undefined;
96
96
  autoWait?: boolean | undefined;
97
97
  timeout?: number | undefined;
@@ -99,9 +99,9 @@ export declare const click: EndpointDef<{
99
99
  diffDelay?: number | undefined;
100
100
  }>;
101
101
  export declare const type: EndpointDef<{
102
+ ref?: string | undefined;
102
103
  selector?: string | undefined;
103
104
  window?: string | undefined;
104
- ref?: string | undefined;
105
105
  autoWait?: boolean | undefined;
106
106
  timeout?: number | undefined;
107
107
  diff?: boolean | undefined;
@@ -117,9 +117,9 @@ export declare const type: EndpointDef<{
117
117
  }>;
118
118
  export declare const key: EndpointDef<{
119
119
  repeat?: number | undefined;
120
+ ref?: string | undefined;
120
121
  selector?: string | undefined;
121
122
  window?: string | undefined;
122
- ref?: string | undefined;
123
123
  ctrlKey?: boolean | undefined;
124
124
  shiftKey?: boolean | undefined;
125
125
  altKey?: boolean | undefined;
@@ -128,30 +128,30 @@ export declare const key: EndpointDef<{
128
128
  }>;
129
129
  export declare const drag: EndpointDef<{
130
130
  duration?: number | undefined;
131
+ ref?: string | undefined;
131
132
  selector?: string | undefined;
132
133
  window?: string | undefined;
133
- ref?: string | undefined;
134
134
  deltaX?: number | undefined;
135
135
  deltaY?: number | undefined;
136
136
  }>;
137
137
  export declare const highlight: EndpointDef<{
138
138
  duration?: number | undefined;
139
+ ref?: string | undefined;
139
140
  selector?: string | undefined;
140
141
  window?: string | undefined;
141
- ref?: string | undefined;
142
142
  label?: string | undefined;
143
143
  color?: string | undefined;
144
144
  }>;
145
145
  export declare const unhighlight: EndpointDef<{}>;
146
146
  export declare const scroll: EndpointDef<{
147
147
  duration?: number | undefined;
148
+ ref?: string | undefined;
148
149
  selector?: string | undefined;
150
+ x?: number | undefined;
151
+ y?: number | undefined;
149
152
  window?: string | undefined;
150
- ref?: string | undefined;
151
153
  deltaX?: number | undefined;
152
154
  deltaY?: number | undefined;
153
- x?: number | undefined;
154
- y?: number | undefined;
155
155
  easing?: string | undefined;
156
156
  block?: string | undefined;
157
157
  }>;
@@ -226,16 +226,16 @@ export declare const fetchUrl: EndpointDef<{
226
226
  url: string;
227
227
  }>;
228
228
  export declare const call: EndpointDef<{
229
+ ref?: string | undefined;
229
230
  selector?: string | undefined;
230
231
  window?: string | undefined;
231
- ref?: string | undefined;
232
232
  args?: any[] | undefined;
233
233
  method: string;
234
234
  }>;
235
235
  export declare const screenshot: EndpointDef<{
236
+ ref?: string | undefined;
236
237
  selector?: string | undefined;
237
238
  window?: string | undefined;
238
- ref?: string | undefined;
239
239
  delay?: number | undefined;
240
240
  canvas?: string | undefined;
241
241
  format?: string | undefined;
@@ -293,8 +293,8 @@ export declare const recordingStart: EndpointDef<{
293
293
  export declare const recordingStop: EndpointDef<{}>;
294
294
  export declare const recordingGenerate: EndpointDef<{
295
295
  url?: string | undefined;
296
- minDelay?: number | undefined;
297
296
  events?: any[] | undefined;
297
+ minDelay?: number | undefined;
298
298
  name?: string | undefined;
299
299
  since?: number | undefined;
300
300
  description?: string | undefined;
@@ -388,21 +388,21 @@ export declare const endpoints: {
388
388
  window?: string | undefined;
389
389
  }>;
390
390
  readonly query: EndpointDef<{
391
- selector?: string | undefined;
392
391
  ref?: string | undefined;
392
+ selector?: string | undefined;
393
393
  all?: boolean | undefined;
394
394
  }>;
395
395
  readonly inspect: EndpointDef<{
396
+ ref?: string | undefined;
396
397
  selector?: string | undefined;
397
398
  window?: string | undefined;
398
- ref?: string | undefined;
399
399
  fullStyles?: boolean | undefined;
400
400
  matchedRules?: boolean | undefined;
401
401
  }>;
402
402
  readonly inspectAll: EndpointDef<{
403
+ ref?: string | undefined;
403
404
  selector?: string | undefined;
404
405
  window?: string | undefined;
405
- ref?: string | undefined;
406
406
  fullStyles?: boolean | undefined;
407
407
  matchedRules?: boolean | undefined;
408
408
  limit?: number | undefined;
@@ -423,9 +423,9 @@ export declare const endpoints: {
423
423
  }>;
424
424
  readonly click: EndpointDef<{
425
425
  text?: string | undefined;
426
+ ref?: string | undefined;
426
427
  selector?: string | undefined;
427
428
  window?: string | undefined;
428
- ref?: string | undefined;
429
429
  tag?: string | undefined;
430
430
  autoWait?: boolean | undefined;
431
431
  timeout?: number | undefined;
@@ -433,9 +433,9 @@ export declare const endpoints: {
433
433
  diffDelay?: number | undefined;
434
434
  }>;
435
435
  readonly type: EndpointDef<{
436
+ ref?: string | undefined;
436
437
  selector?: string | undefined;
437
438
  window?: string | undefined;
438
- ref?: string | undefined;
439
439
  autoWait?: boolean | undefined;
440
440
  timeout?: number | undefined;
441
441
  diff?: boolean | undefined;
@@ -451,9 +451,9 @@ export declare const endpoints: {
451
451
  }>;
452
452
  readonly key: EndpointDef<{
453
453
  repeat?: number | undefined;
454
+ ref?: string | undefined;
454
455
  selector?: string | undefined;
455
456
  window?: string | undefined;
456
- ref?: string | undefined;
457
457
  ctrlKey?: boolean | undefined;
458
458
  shiftKey?: boolean | undefined;
459
459
  altKey?: boolean | undefined;
@@ -462,30 +462,30 @@ export declare const endpoints: {
462
462
  }>;
463
463
  readonly drag: EndpointDef<{
464
464
  duration?: number | undefined;
465
+ ref?: string | undefined;
465
466
  selector?: string | undefined;
466
467
  window?: string | undefined;
467
- ref?: string | undefined;
468
468
  deltaX?: number | undefined;
469
469
  deltaY?: number | undefined;
470
470
  }>;
471
471
  readonly highlight: EndpointDef<{
472
472
  duration?: number | undefined;
473
+ ref?: string | undefined;
473
474
  selector?: string | undefined;
474
475
  window?: string | undefined;
475
- ref?: string | undefined;
476
476
  label?: string | undefined;
477
477
  color?: string | undefined;
478
478
  }>;
479
479
  readonly unhighlight: EndpointDef<{}>;
480
480
  readonly scroll: EndpointDef<{
481
481
  duration?: number | undefined;
482
+ ref?: string | undefined;
482
483
  selector?: string | undefined;
484
+ x?: number | undefined;
485
+ y?: number | undefined;
483
486
  window?: string | undefined;
484
- ref?: string | undefined;
485
487
  deltaX?: number | undefined;
486
488
  deltaY?: number | undefined;
487
- x?: number | undefined;
488
- y?: number | undefined;
489
489
  easing?: string | undefined;
490
490
  block?: string | undefined;
491
491
  }>;
@@ -546,16 +546,16 @@ export declare const endpoints: {
546
546
  url: string;
547
547
  }>;
548
548
  readonly call: EndpointDef<{
549
+ ref?: string | undefined;
549
550
  selector?: string | undefined;
550
551
  window?: string | undefined;
551
- ref?: string | undefined;
552
552
  args?: any[] | undefined;
553
553
  method: string;
554
554
  }>;
555
555
  readonly screenshot: EndpointDef<{
556
+ ref?: string | undefined;
556
557
  selector?: string | undefined;
557
558
  window?: string | undefined;
558
- ref?: string | undefined;
559
559
  delay?: number | undefined;
560
560
  canvas?: string | undefined;
561
561
  format?: string | undefined;
@@ -613,8 +613,8 @@ export declare const endpoints: {
613
613
  readonly recordingStop: EndpointDef<{}>;
614
614
  readonly recordingGenerate: EndpointDef<{
615
615
  url?: string | undefined;
616
- minDelay?: number | undefined;
617
616
  events?: any[] | undefined;
617
+ minDelay?: number | undefined;
618
618
  name?: string | undefined;
619
619
  since?: number | undefined;
620
620
  description?: string | undefined;
@@ -707,36 +707,36 @@ export declare const ALL_ENDPOINTS: (EndpointDef<{
707
707
  mode?: string | undefined;
708
708
  window?: string | undefined;
709
709
  }> | EndpointDef<{
710
- selector?: string | undefined;
711
710
  ref?: string | undefined;
711
+ selector?: string | undefined;
712
712
  all?: boolean | undefined;
713
713
  }> | EndpointDef<{
714
+ ref?: string | undefined;
714
715
  selector?: string | undefined;
715
716
  window?: string | undefined;
716
- ref?: string | undefined;
717
717
  fullStyles?: boolean | undefined;
718
718
  matchedRules?: boolean | undefined;
719
719
  }> | EndpointDef<{
720
+ ref?: string | undefined;
720
721
  selector?: string | undefined;
721
722
  window?: string | undefined;
722
- ref?: string | undefined;
723
723
  fullStyles?: boolean | undefined;
724
724
  matchedRules?: boolean | undefined;
725
725
  limit?: number | undefined;
726
726
  }> | EndpointDef<{
727
727
  text?: string | undefined;
728
+ ref?: string | undefined;
728
729
  selector?: string | undefined;
729
730
  window?: string | undefined;
730
- ref?: string | undefined;
731
731
  tag?: string | undefined;
732
732
  autoWait?: boolean | undefined;
733
733
  timeout?: number | undefined;
734
734
  diff?: boolean | undefined;
735
735
  diffDelay?: number | undefined;
736
736
  }> | EndpointDef<{
737
+ ref?: string | undefined;
737
738
  selector?: string | undefined;
738
739
  window?: string | undefined;
739
- ref?: string | undefined;
740
740
  autoWait?: boolean | undefined;
741
741
  timeout?: number | undefined;
742
742
  diff?: boolean | undefined;
@@ -751,9 +751,9 @@ export declare const ALL_ENDPOINTS: (EndpointDef<{
751
751
  text: string;
752
752
  }> | EndpointDef<{
753
753
  repeat?: number | undefined;
754
+ ref?: string | undefined;
754
755
  selector?: string | undefined;
755
756
  window?: string | undefined;
756
- ref?: string | undefined;
757
757
  ctrlKey?: boolean | undefined;
758
758
  shiftKey?: boolean | undefined;
759
759
  altKey?: boolean | undefined;
@@ -761,27 +761,27 @@ export declare const ALL_ENDPOINTS: (EndpointDef<{
761
761
  key: string;
762
762
  }> | EndpointDef<{
763
763
  duration?: number | undefined;
764
+ ref?: string | undefined;
764
765
  selector?: string | undefined;
765
766
  window?: string | undefined;
766
- ref?: string | undefined;
767
767
  deltaX?: number | undefined;
768
768
  deltaY?: number | undefined;
769
769
  }> | EndpointDef<{
770
770
  duration?: number | undefined;
771
+ ref?: string | undefined;
771
772
  selector?: string | undefined;
772
773
  window?: string | undefined;
773
- ref?: string | undefined;
774
774
  label?: string | undefined;
775
775
  color?: string | undefined;
776
776
  }> | EndpointDef<{}> | EndpointDef<{
777
777
  duration?: number | undefined;
778
+ ref?: string | undefined;
778
779
  selector?: string | undefined;
780
+ x?: number | undefined;
781
+ y?: number | undefined;
779
782
  window?: string | undefined;
780
- ref?: string | undefined;
781
783
  deltaX?: number | undefined;
782
784
  deltaY?: number | undefined;
783
- x?: number | undefined;
784
- y?: number | undefined;
785
785
  easing?: string | undefined;
786
786
  block?: string | undefined;
787
787
  }> | EndpointDef<{
@@ -835,15 +835,15 @@ export declare const ALL_ENDPOINTS: (EndpointDef<{
835
835
  window?: string | undefined;
836
836
  url: string;
837
837
  }> | EndpointDef<{
838
+ ref?: string | undefined;
838
839
  selector?: string | undefined;
839
840
  window?: string | undefined;
840
- ref?: string | undefined;
841
841
  args?: any[] | undefined;
842
842
  method: string;
843
843
  }> | EndpointDef<{
844
+ ref?: string | undefined;
844
845
  selector?: string | undefined;
845
846
  window?: string | undefined;
846
- ref?: string | undefined;
847
847
  delay?: number | undefined;
848
848
  canvas?: string | undefined;
849
849
  format?: string | undefined;
@@ -886,8 +886,8 @@ export declare const ALL_ENDPOINTS: (EndpointDef<{
886
886
  name?: string | undefined;
887
887
  }> | EndpointDef<{}> | EndpointDef<{
888
888
  url?: string | undefined;
889
- minDelay?: number | undefined;
890
889
  events?: any[] | undefined;
890
+ minDelay?: number | undefined;
891
891
  name?: string | undefined;
892
892
  since?: number | undefined;
893
893
  description?: string | undefined;
@@ -20,7 +20,7 @@
20
20
  * - Option+Tab toggles visibility (but active state always shows briefly)
21
21
  * - Localhost only by default
22
22
  */
23
- export declare const VERSION = "1.12.1";
23
+ export declare const VERSION = "1.12.2";
24
24
  export declare class DevChannel extends HTMLElement {
25
25
  static get tagName(): string;
26
26
  static elementCreator(): () => DevChannel;
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "1.12.1";
2
+ var VERSION = "1.12.2";
3
3
 
4
4
  // src/text-selector.ts
5
5
  var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\(/;
package/dist/component.js CHANGED
@@ -46,7 +46,7 @@
46
46
  });
47
47
 
48
48
  // src/version.ts
49
- var VERSION = "1.12.1";
49
+ var VERSION = "1.12.2";
50
50
 
51
51
  // src/text-selector.ts
52
52
  var TEXT_PSEUDO_RE = /:(?:text-is|has-text|text)\(/;