@lightcone-ai/daemon 0.18.1 → 0.19.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightcone-ai/daemon",
3
- "version": "0.18.1",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -1,4 +1,5 @@
1
1
  import { resolveDurationMs } from './phase-duration.js';
2
+ import { humanizedScroll } from '../humanized-scroll.js';
2
3
 
3
4
  function normalizeText(value) {
4
5
  if (typeof value !== 'string') return '';
@@ -228,13 +229,26 @@ function resolveFromY(phase, fallback = null) {
228
229
  return Math.round(parsed);
229
230
  }
230
231
 
232
+ // Delegates to humanizedScroll, which dispatches real CDP touch events so
233
+ // the browser's gesture engine produces native scroll physics (rubber-band,
234
+ // fling inertia, compositor-paced repaints). The old implementation drove
235
+ // `root.scrollTo(...)` in a setTimeout loop inside page.evaluate — visually
236
+ // smooth in isolation, but bypassed the gesture pipeline entirely, which is
237
+ // what made scrolls feel "robotic" on recordings (see the
238
+ // `not natural` thread in docs/scenario-content-creation discussion).
239
+ //
240
+ // `minSteps` is no longer needed (humanizedScroll computes segments from
241
+ // distance + duration). `jitterPx` is forwarded as `pixel_jitter_px`, which
242
+ // humanizedScroll converts into per-touchMove vertical offset.
231
243
  async function animateScroll(page, {
232
244
  startY = null,
233
245
  targetY,
234
246
  durationMs,
235
247
  easing = 'easeInOutQuad',
236
248
  jitterPx = 0,
237
- minSteps = 10,
249
+ // minSteps is accepted but unused — kept in the signature so callers don't
250
+ // need updating in this refactor.
251
+ minSteps: _minSteps, // eslint-disable-line no-unused-vars
238
252
  } = {}) {
239
253
  if (!Number.isFinite(Number(targetY))) {
240
254
  const error = new Error('phase_target_y_required');
@@ -242,53 +256,19 @@ async function animateScroll(page, {
242
256
  throw error;
243
257
  }
244
258
 
245
- const normalizedDurationMs = Math.max(0, Number(durationMs) || 0);
246
- const normalizedMinSteps = Math.max(1, Number(minSteps) || 1);
247
-
248
- await page.evaluate(async ({
249
- startY: evaluateStartY,
250
- targetY: evaluateTargetY,
251
- durationMs: evaluateDurationMs,
252
- easing: evaluateEasing,
253
- jitterPx: evaluateJitterPx,
254
- minSteps: evaluateMinSteps,
255
- }) => {
256
- const root = document.scrollingElement || document.documentElement;
257
- const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
258
-
259
- const fromY = Number.isFinite(evaluateStartY) ? evaluateStartY : root.scrollTop;
260
- const toY = evaluateTargetY;
261
- const delta = toY - fromY;
262
-
263
- const steps = Math.max(evaluateMinSteps, Math.round(Math.max(1, evaluateDurationMs) / 16));
264
- const stepDurationMs = evaluateDurationMs <= 0 ? 0 : evaluateDurationMs / steps;
265
-
266
- const applyEasing = (t) => {
267
- if (evaluateEasing === 'linear') return t;
268
- if (evaluateEasing === 'easeOutQuad') return 1 - ((1 - t) * (1 - t));
269
- return t < 0.5
270
- ? 2 * t * t
271
- : 1 - (Math.pow(-2 * t + 2, 2) / 2);
272
- };
273
-
274
- root.scrollTo(0, fromY);
275
- for (let index = 1; index <= steps; index += 1) {
276
- const t = index / steps;
277
- const eased = applyEasing(t);
278
- const jitter = evaluateJitterPx > 0 ? ((Math.random() * 2 - 1) * evaluateJitterPx) : 0;
279
- root.scrollTo(0, fromY + (delta * eased) + jitter);
280
- if (stepDurationMs > 0) {
281
- await wait(stepDurationMs);
282
- }
283
- }
284
- root.scrollTo(0, toY);
285
- }, {
286
- startY,
287
- targetY,
288
- durationMs: normalizedDurationMs,
289
- easing,
290
- jitterPx: Math.max(0, Number(jitterPx) || 0),
291
- minSteps: normalizedMinSteps,
259
+ const resolvedFromY = Number.isFinite(Number(startY))
260
+ ? Number(startY)
261
+ : await page.evaluate(() => {
262
+ const root = document.scrollingElement || document.documentElement;
263
+ return Math.round(root.scrollTop);
264
+ });
265
+
266
+ await humanizedScroll(page, {
267
+ from_y: resolvedFromY,
268
+ to_y: Number(targetY),
269
+ duration_ms: Math.max(0, Number(durationMs) || 0),
270
+ motion_curve: easing,
271
+ pixel_jitter_px: Math.max(0, Number(jitterPx) || 0),
292
272
  });
293
273
  }
294
274