@holostaff/sdk 0.9.8 → 0.9.9

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.
@@ -1,40 +1,35 @@
1
1
  /**
2
2
  * Observations — rrweb session capture (vision-reconciliation wave,
3
- * Phase A).
3
+ * Phase A; Browserbase cost-optimization, Phase A/B).
4
4
  *
5
5
  * Records the visitor's session with rrweb and ships event batches to
6
6
  * `POST /api/runtime/sessions/:sessionId/observations`, where the
7
7
  * server's vision bridge replays them in Browserbase and screenshots
8
8
  * feed the Gemini perceive+decide tick.
9
9
  *
10
+ * Cost gating (Browserbase is the expensive resource, rrweb is free):
11
+ * - We RECORD from page load but BUFFER client-side — nothing is sent
12
+ * (so the server never spins up a Browserbase session) until the
13
+ * first *trusted* interaction. Bots and bounces that load the page
14
+ * but never interact cost nothing. The pre-gate buffer is trimmed to
15
+ * the latest FullSnapshot so it stays small AND replayable, and the
16
+ * whole lead-up is flushed at gate-open — we never lose the first
17
+ * moments, the server just receives them a beat later once we know
18
+ * it's a human.
19
+ * - `navigator.webdriver` is reported so the server can reap automated
20
+ * clients that drive trusted input (headless browsers).
21
+ * - A visibility-gated heartbeat keeps the session marked live while
22
+ * the tab is visible; it stops the instant the tab is hidden or
23
+ * closed, so the server reaps the Browserbase session within seconds
24
+ * instead of waiting out a 30-minute timeout.
25
+ *
10
26
  * Capture policy (wave doc §Phase A — "everything the user sees,
11
- * except PII"):
12
- * - Full DOM, canvas (sampled at ~2 fps — the VLM only ticks every
13
- * 2–5s), media playback state, fonts + images inlined so replay
14
- * doesn't depend on URLs staying reachable.
15
- * - Typed PII never leaves the page: password / email / tel inputs
16
- * are masked at the keystroke level. Rendered PII is the
17
- * customer's to mark: `holostaff-mask` masks text content,
18
- * `holostaff-block` blanks a region, `holostaff-ignore` skips an
19
- * input entirely.
27
+ * except PII"): full DOM, canvas (~2 fps), media state, fonts + images
28
+ * inlined. Typed PII never leaves the page (password/email/tel masked;
29
+ * `holostaff-mask`/`-block`/`-ignore` for rendered PII).
20
30
  *
21
31
  * Version pin: rrweb 2.0.0-alpha.4 — MUST match the server's replay
22
- * bundle (server/src/bowtie/vision/rrweb.bundle.js); recorder and
23
- * replayer share the event format.
24
- *
25
- * Loading: rrweb is imported dynamically so hosts that disable
26
- * observation (or render server-side) never evaluate it; a failed
27
- * import degrades to no-capture and routes to onError, per the SDK's
28
- * fail-soft contract.
29
- *
30
- * Batching:
31
- * - flush every FLUSH_INTERVAL_MS, or at MAX_BATCH_EVENTS, or when
32
- * the approximate batch size passes MAX_BATCH_BYTES (full
33
- * snapshots with inlined images are heavy — don't let them queue).
34
- * - final flush on dispose goes over sendBeacon (survives unload);
35
- * beacons cap at ~64KB so an oversized final batch is truncated to
36
- * the most recent events — replay loses the tail of a dying
37
- * session, never the session.
32
+ * bundle (server/src/bowtie/vision/rrweb.bundle.js).
38
33
  */
39
34
  import { type TransportConfig } from './transport.js';
40
35
  import type { ObserveOptions } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../src/observations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAOhD,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,eAAe,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,kEAAkE;IAClE,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,OAAO,CAAC,EAAE,cAAc,CAAA;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,OAAO,IAAI,IAAI,CAAA;CAChB;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,GAAG,mBAAmB,CAyFpF"}
1
+ {"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../src/observations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAiBhD,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,eAAe,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,kEAAkE;IAClE,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC,OAAO,CAAC,EAAE,cAAc,CAAA;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,iDAAiD;IACjD,OAAO,IAAI,IAAI,CAAA;CAChB;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,GAAG,mBAAmB,CAoLpF"}
@@ -1,97 +1,206 @@
1
1
  /**
2
2
  * Observations — rrweb session capture (vision-reconciliation wave,
3
- * Phase A).
3
+ * Phase A; Browserbase cost-optimization, Phase A/B).
4
4
  *
5
5
  * Records the visitor's session with rrweb and ships event batches to
6
6
  * `POST /api/runtime/sessions/:sessionId/observations`, where the
7
7
  * server's vision bridge replays them in Browserbase and screenshots
8
8
  * feed the Gemini perceive+decide tick.
9
9
  *
10
+ * Cost gating (Browserbase is the expensive resource, rrweb is free):
11
+ * - We RECORD from page load but BUFFER client-side — nothing is sent
12
+ * (so the server never spins up a Browserbase session) until the
13
+ * first *trusted* interaction. Bots and bounces that load the page
14
+ * but never interact cost nothing. The pre-gate buffer is trimmed to
15
+ * the latest FullSnapshot so it stays small AND replayable, and the
16
+ * whole lead-up is flushed at gate-open — we never lose the first
17
+ * moments, the server just receives them a beat later once we know
18
+ * it's a human.
19
+ * - `navigator.webdriver` is reported so the server can reap automated
20
+ * clients that drive trusted input (headless browsers).
21
+ * - A visibility-gated heartbeat keeps the session marked live while
22
+ * the tab is visible; it stops the instant the tab is hidden or
23
+ * closed, so the server reaps the Browserbase session within seconds
24
+ * instead of waiting out a 30-minute timeout.
25
+ *
10
26
  * Capture policy (wave doc §Phase A — "everything the user sees,
11
- * except PII"):
12
- * - Full DOM, canvas (sampled at ~2 fps — the VLM only ticks every
13
- * 2–5s), media playback state, fonts + images inlined so replay
14
- * doesn't depend on URLs staying reachable.
15
- * - Typed PII never leaves the page: password / email / tel inputs
16
- * are masked at the keystroke level. Rendered PII is the
17
- * customer's to mark: `holostaff-mask` masks text content,
18
- * `holostaff-block` blanks a region, `holostaff-ignore` skips an
19
- * input entirely.
27
+ * except PII"): full DOM, canvas (~2 fps), media state, fonts + images
28
+ * inlined. Typed PII never leaves the page (password/email/tel masked;
29
+ * `holostaff-mask`/`-block`/`-ignore` for rendered PII).
20
30
  *
21
31
  * Version pin: rrweb 2.0.0-alpha.4 — MUST match the server's replay
22
- * bundle (server/src/bowtie/vision/rrweb.bundle.js); recorder and
23
- * replayer share the event format.
24
- *
25
- * Loading: rrweb is imported dynamically so hosts that disable
26
- * observation (or render server-side) never evaluate it; a failed
27
- * import degrades to no-capture and routes to onError, per the SDK's
28
- * fail-soft contract.
29
- *
30
- * Batching:
31
- * - flush every FLUSH_INTERVAL_MS, or at MAX_BATCH_EVENTS, or when
32
- * the approximate batch size passes MAX_BATCH_BYTES (full
33
- * snapshots with inlined images are heavy — don't let them queue).
34
- * - final flush on dispose goes over sendBeacon (survives unload);
35
- * beacons cap at ~64KB so an oversized final batch is truncated to
36
- * the most recent events — replay loses the tail of a dying
37
- * session, never the session.
32
+ * bundle (server/src/bowtie/vision/rrweb.bundle.js).
38
33
  */
39
34
  import { postJson, postBeacon } from './transport.js';
40
35
  const FLUSH_INTERVAL_MS = 5000;
41
36
  const MAX_BATCH_EVENTS = 200;
42
37
  const MAX_BATCH_BYTES = 800000;
43
38
  const BEACON_SAFE_BYTES = 55000;
39
+ /** Force a periodic FullSnapshot so the pre-gate buffer can be trimmed to
40
+ * a replayable checkpoint and the server replay self-heals. */
41
+ const CHECKOUT_EVERY_MS = 30000;
42
+ /** Pre-gate buffer caps — trimmed to the latest FullSnapshot when hit. */
43
+ const PREGATE_MAX_EVENTS = 800;
44
+ const PREGATE_MAX_BYTES = 3000000;
45
+ /** Liveness ping cadence while visible (server reap grace must exceed it). */
46
+ const HEARTBEAT_INTERVAL_MS = 15000;
47
+ /** rrweb EventType.FullSnapshot. */
48
+ const RRWEB_FULL_SNAPSHOT = 2;
44
49
  export function startObservations(deps) {
45
50
  if (typeof window === 'undefined')
46
51
  return { dispose: () => { } };
47
52
  if (deps.observe?.enabled === false)
48
53
  return { dispose: () => { } };
49
54
  let disposed = false;
55
+ let gateOpen = false;
50
56
  let stopRecording = null;
57
+ // Post-gate send buffer.
51
58
  let buffer = [];
52
59
  let bufferBytes = 0;
60
+ // Pre-gate buffer: recorded but withheld until a human interacts.
61
+ let pregate = [];
62
+ let pregateBytes = 0;
53
63
  let flushTimer = null;
64
+ let heartbeatTimer = null;
54
65
  const path = `/api/runtime/sessions/${deps.sessionId}/observations`;
66
+ const heartbeatPath = `/api/runtime/sessions/${deps.sessionId}/heartbeat`;
67
+ // Trusted interaction can still come from a headless browser driving
68
+ // real input — flag automation so the server can reap it.
69
+ const automated = typeof navigator !== 'undefined'
70
+ && navigator.webdriver === true;
71
+ const bodyExtra = automated ? { automated: true } : {};
55
72
  const flush = () => {
56
73
  if (!buffer.length)
57
74
  return;
58
75
  const events = buffer;
59
76
  buffer = [];
60
77
  bufferBytes = 0;
61
- void postJson(deps.cfg, path, { ...deps.buildBody(), events });
78
+ void postJson(deps.cfg, path, { ...deps.buildBody(), ...bodyExtra, events });
62
79
  };
63
- /** Unload-safe flush. Beacon payloads cap at ~64KB; keep the most
64
- * recent events if the tail batch is oversized — replay loses the
65
- * tail of a dying session, never the session. */
80
+ /** Unload-safe flush over sendBeacon (≤64KB; keep the most recent
81
+ * events if the tail is oversized — lose the tail, never the session). */
66
82
  const flushBeacon = () => {
67
83
  if (!buffer.length)
68
84
  return;
69
85
  let events = buffer;
70
86
  buffer = [];
71
87
  bufferBytes = 0;
72
- // Size by the events alone (body adds ~200 constant bytes); halving
73
- // converges in ≤4 rounds from the 800KB batch cap.
74
88
  while (events.length > 1 && JSON.stringify(events).length > BEACON_SAFE_BYTES) {
75
89
  events = events.slice(Math.ceil(events.length / 2));
76
90
  }
77
- postBeacon(deps.cfg, path, { ...deps.buildBody(), events });
91
+ postBeacon(deps.cfg, path, { ...deps.buildBody(), ...bodyExtra, events });
92
+ };
93
+ const sizeof = (e) => {
94
+ try {
95
+ return JSON.stringify(e).length;
96
+ }
97
+ catch {
98
+ return 1000;
99
+ }
100
+ };
101
+ /** Drop everything before the latest FullSnapshot — bounds memory while
102
+ * keeping the buffer independently replayable. */
103
+ const trimPregate = () => {
104
+ let lastSnap = -1;
105
+ for (let i = pregate.length - 1; i >= 0; i--) {
106
+ if (pregate[i].type === RRWEB_FULL_SNAPSHOT) {
107
+ lastSnap = i;
108
+ break;
109
+ }
110
+ }
111
+ if (lastSnap > 0)
112
+ pregate = pregate.slice(lastSnap);
113
+ pregateBytes = pregate.reduce((n, e) => n + sizeof(e), 0);
78
114
  };
79
115
  const push = (event) => {
80
116
  if (disposed)
81
117
  return;
118
+ if (!gateOpen) {
119
+ pregate.push(event);
120
+ pregateBytes += sizeof(event);
121
+ if (pregate.length > PREGATE_MAX_EVENTS || pregateBytes > PREGATE_MAX_BYTES)
122
+ trimPregate();
123
+ return;
124
+ }
82
125
  buffer.push(event);
83
- // Approximate sizing — exact enough to keep batches under the cap.
84
- try {
85
- bufferBytes += JSON.stringify(event).length;
126
+ bufferBytes += sizeof(event);
127
+ if (buffer.length >= MAX_BATCH_EVENTS || bufferBytes >= MAX_BATCH_BYTES)
128
+ flush();
129
+ };
130
+ const startSending = () => {
131
+ if (flushTimer == null)
132
+ flushTimer = setInterval(flush, FLUSH_INTERVAL_MS);
133
+ };
134
+ const stopSending = () => {
135
+ if (flushTimer != null) {
136
+ clearInterval(flushTimer);
137
+ flushTimer = null;
86
138
  }
87
- catch {
88
- bufferBytes += 1000;
139
+ };
140
+ const startHeartbeat = () => {
141
+ if (heartbeatTimer != null)
142
+ return;
143
+ heartbeatTimer = setInterval(() => {
144
+ if (typeof document !== 'undefined' && document.hidden)
145
+ return;
146
+ void postJson(deps.cfg, heartbeatPath, { ...deps.buildBody(), ...bodyExtra });
147
+ }, HEARTBEAT_INTERVAL_MS);
148
+ };
149
+ const stopHeartbeat = () => {
150
+ if (heartbeatTimer != null) {
151
+ clearInterval(heartbeatTimer);
152
+ heartbeatTimer = null;
89
153
  }
90
- if (buffer.length >= MAX_BATCH_EVENTS || bufferBytes >= MAX_BATCH_BYTES)
154
+ };
155
+ // -- The human gate -------------------------------------------------
156
+ const GATE_EVENTS = ['pointerdown', 'pointermove', 'keydown', 'wheel', 'scroll', 'touchstart'];
157
+ const gateOpts = { passive: true, capture: true };
158
+ const openGate = () => {
159
+ if (gateOpen || disposed)
160
+ return;
161
+ gateOpen = true;
162
+ removeGateListeners();
163
+ // Hand the buffered lead-up to the send queue (already trimmed to a
164
+ // valid FullSnapshot) and flush it now — this is what creates the BB
165
+ // session, only now that we've seen a human.
166
+ buffer = pregate;
167
+ bufferBytes = pregateBytes;
168
+ pregate = [];
169
+ pregateBytes = 0;
170
+ flush();
171
+ startSending();
172
+ startHeartbeat();
173
+ };
174
+ const onGateEvent = (e) => { if (e.isTrusted)
175
+ openGate(); };
176
+ const addGateListeners = () => {
177
+ for (const t of GATE_EVENTS)
178
+ window.addEventListener(t, onGateEvent, gateOpts);
179
+ };
180
+ const removeGateListeners = () => {
181
+ for (const t of GATE_EVENTS)
182
+ window.removeEventListener(t, onGateEvent, gateOpts);
183
+ };
184
+ // -- Visibility: pause sending + heartbeat when hidden --------------
185
+ const onVisibility = () => {
186
+ if (!gateOpen)
187
+ return;
188
+ if (document.hidden) {
91
189
  flush();
190
+ stopSending();
191
+ stopHeartbeat();
192
+ }
193
+ else {
194
+ startSending();
195
+ startHeartbeat();
196
+ }
92
197
  };
93
- // Dynamic import keeps rrweb out of hosts that never observe and
94
- // makes a missing/incompatible module a soft failure.
198
+ if (typeof document !== 'undefined') {
199
+ document.addEventListener('visibilitychange', onVisibility);
200
+ }
201
+ addGateListeners();
202
+ // Dynamic import keeps rrweb out of hosts that never observe and makes
203
+ // a missing/incompatible module a soft failure.
95
204
  void import('rrweb')
96
205
  .then((rrweb) => {
97
206
  if (disposed)
@@ -103,6 +212,8 @@ export function startObservations(deps) {
103
212
  }
104
213
  stopRecording = record({
105
214
  emit: (event) => push(event),
215
+ // Periodic FullSnapshot → trimmable pre-gate buffer + self-healing replay.
216
+ checkoutEveryNms: CHECKOUT_EVERY_MS,
106
217
  // -- everything the user sees --
107
218
  recordCanvas: true,
108
219
  sampling: { canvas: 2 },
@@ -117,7 +228,7 @@ export function startObservations(deps) {
117
228
  ...(deps.observe?.blockSelector ? { blockSelector: deps.observe.blockSelector } : {}),
118
229
  ...(deps.observe?.rrweb ?? {}),
119
230
  }) ?? null;
120
- flushTimer = setInterval(flush, FLUSH_INTERVAL_MS);
231
+ // NB: sending does NOT start here — it starts at the human gate.
121
232
  })
122
233
  .catch((err) => {
123
234
  deps.cfg.onError?.(err instanceof Error ? err : new Error(String(err)), { method: 'OBSERVE', path });
@@ -127,16 +238,20 @@ export function startObservations(deps) {
127
238
  if (disposed)
128
239
  return;
129
240
  disposed = true;
130
- if (flushTimer != null) {
131
- clearInterval(flushTimer);
132
- flushTimer = null;
241
+ stopSending();
242
+ stopHeartbeat();
243
+ removeGateListeners();
244
+ if (typeof document !== 'undefined') {
245
+ document.removeEventListener('visibilitychange', onVisibility);
133
246
  }
134
247
  try {
135
248
  stopRecording?.();
136
249
  }
137
250
  catch { /* recorder already gone */ }
138
251
  stopRecording = null;
139
- flushBeacon();
252
+ // Only beacon a tail if we'd opened the gate (a real human session).
253
+ if (gateOpen)
254
+ flushBeacon();
140
255
  },
141
256
  };
142
257
  }
@@ -1 +1 @@
1
- {"version":3,"file":"observations.js","sourceRoot":"","sources":["../src/observations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observations.js","sourceRoot":"","sources":["../src/observations.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holostaff/sdk",
3
- "version": "0.9.8",
3
+ "version": "0.9.9",
4
4
  "description": "Holostaff SDK — lifetime identity, stage detection, custom signal probes, and the living-portrait presence layer (chip, note, Theater, voice Stage) for the Holostaff runtime.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://docs.holostaff.ai",