@eventmodelers/cli 1.0.5 → 1.0.7

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/cli.js CHANGED
@@ -1430,7 +1430,9 @@ async function runModeling(kitDir, projectDir, verbose = false) {
1430
1430
  log(`channel "${channelName}": ${status}`);
1431
1431
  if (status === 'SUBSCRIBED') drain().catch((err) => log(`initial drain error: ${err.message}`));
1432
1432
  },
1433
- );
1433
+ ).catch((err) => {
1434
+ log(`realtime subscribe failed, prompts won't be pushed live: ${err.message}`);
1435
+ });
1434
1436
 
1435
1437
  setInterval(async () => {
1436
1438
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eventmodelers/cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Eventmodelers CLI — real-time Claude agent + skills for Claude Code, for any stack (Node, Supabase, Axon, Cratis, or modeling-only)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -7,6 +7,15 @@
7
7
 
8
8
  const REALTIME_EVENTS_COLLECTION = 'realtime_events';
9
9
 
10
+ // Same backoff steps the PocketBase SDK uses for its own reconnects (see
11
+ // predefinedReconnectIntervals in the SDK) — reused here because the SDK only
12
+ // applies that backoff to a connection that drops *after* it was established.
13
+ // A failed first handshake (e.g. "Invalid realtime client" from the initial
14
+ // GET /api/realtime and the follow-up subscribe POST landing on different
15
+ // backend instances) rejects immediately with no retry at all, so we retry it
16
+ // ourselves.
17
+ const RECONNECT_INTERVALS_MS = [200, 300, 500, 1000, 1200, 1500, 2000];
18
+
10
19
  export async function createPocketBaseRealtimeAdapter(cfg, initialToken) {
11
20
  const { EventSource } = await import('eventsource');
12
21
  if (!globalThis.EventSource) globalThis.EventSource = EventSource; // PocketBase's SDK assumes a browser-style global
@@ -16,11 +25,20 @@ export async function createPocketBaseRealtimeAdapter(cfg, initialToken) {
16
25
 
17
26
  return {
18
27
  async subscribe(topic, handlers, onStatus) {
19
- await pb.collection(REALTIME_EVENTS_COLLECTION).subscribe('*', (e) => {
20
- if (e.action !== 'create' || e.record.topic !== topic) return;
21
- handlers[e.record.event]?.(e.record.payload);
22
- });
23
- onStatus?.('SUBSCRIBED');
28
+ for (let attempt = 0; ; attempt++) {
29
+ try {
30
+ await pb.collection(REALTIME_EVENTS_COLLECTION).subscribe('*', (e) => {
31
+ if (e.action !== 'create' || e.record.topic !== topic) return;
32
+ handlers[e.record.event]?.(e.record.payload);
33
+ });
34
+ onStatus?.('SUBSCRIBED');
35
+ return;
36
+ } catch (err) {
37
+ if (attempt >= RECONNECT_INTERVALS_MS.length) throw err;
38
+ onStatus?.(`RECONNECTING (attempt ${attempt + 1}/${RECONNECT_INTERVALS_MS.length}): ${err.message}`);
39
+ await new Promise((resolve) => setTimeout(resolve, RECONNECT_INTERVALS_MS[attempt]));
40
+ }
41
+ }
24
42
  },
25
43
  setAuth(token) {
26
44
  pb.authStore.save(token, null);
@@ -66,6 +66,17 @@ Guidelines:
66
66
  - Don't add `<html>`/`<head>`/`<body>` tags to a page — every page is a body-only fragment. The canvas wraps each page in its own `<html><head>` (stylesheet + resize script) `<body>...</body></html>` at render time, so anything sent is placed inside that generated `<body>`.
67
67
  - Bulma CSS (0.9.4) is loaded by default in that `<head>` — classes like `title`, `button`, `is-primary`, `field`/`control`/`input` etc. all work out of the box, no need to write custom CSS for standard form/layout components. Note headings need a size modifier too, e.g. `class="title is-1"` — a bare `title` class alone is always 2rem regardless of the tag (`h1` vs `h2` etc.).
68
68
 
69
+ ### Marks — only when the user explicitly asks for one
70
+
71
+ The canvas has a native "Marks" feature (outline highlight, optional blur-outside spotlight) for calling out part of a screen. **Do not add marks by default.** Only apply one of the two effects below when the request explicitly asks to highlight/mark/call out/circle/spotlight or blur/obscure part of the screen (e.g. "highlight the submit button", "blur everything except the email field"). An ordinary "design a screen" request gets no marks.
72
+
73
+ Since this skill only has a `pages`/`backgroundColor` field to send (no separate marks API), reproduce the same visual language directly as inline CSS on the target element(s) — self-contained in the page HTML, same as any other styling in Step 3:
74
+
75
+ - **Mark / highlight an area** — add to the target element's `style`: `outline:4px solid <color> !important;outline-offset:1px;`. Default color `#e74c3c` (red) unless the user names one; other options mirror the app's mark picker: `#1e293b` (dark slate), `#2ecc71` (green), `#3b82f6` (blue), `#f1c40f` (yellow), `#ffffff` (white).
76
+ - **Blur outside / spotlight an area** — add `style="filter:blur(6px) !important;"` to every other top-level sibling/section on the page so only the called-out element stays sharp. Combine with the outline above if the user asked to both mark and blur.
77
+
78
+ Apply these only to the specific element(s) the request describes — don't guess at additional areas to call out.
79
+
69
80
  ## Step 4 — Render the pages
70
81
 
71
82
  **Updating an existing node** (`nodeId` was given) — always sends the **complete** pages array, not just the changed/new entry: