@runalabs/rill-cli 0.1.17 → 0.1.18

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 (2) hide show
  1. package/dist/cli.js +167 -24
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -15799,7 +15799,8 @@ var interactionReportFields = {
15799
15799
  sideEffects: external_exports.array(sideEffectSchema).max(30).optional(),
15800
15800
  cleanup: external_exports.literal("not_attempted").optional()
15801
15801
  };
15802
- var cloudSubmission = external_exports.object({ ...interactionFields, id: external_exports.string().uuid(), url: cloudRunTarget, prompt: external_exports.string().trim().min(1).max(2e3), expectation: external_exports.string().trim().min(1).max(1e3).optional(), account: external_exports.string().regex(/^[a-z0-9-]{1,60}$/).optional() }).strict();
15802
+ var cloudRunPrompt = external_exports.string().min(1).max(2e3).refine((value) => Boolean(value.trim()), "Describe what you want Rill to do.");
15803
+ var cloudSubmission = external_exports.object({ ...interactionFields, id: external_exports.string().uuid(), url: cloudRunTarget, prompt: cloudRunPrompt, expectation: external_exports.string().trim().min(1).max(1e3).optional(), account: external_exports.string().regex(/^[a-z0-9-]{1,60}$/).optional() }).strict();
15803
15804
  var siteAccountSchema = external_exports.object({
15804
15805
  name: external_exports.string().regex(/^[a-z0-9-]{1,60}$/),
15805
15806
  origin: publicTarget.refine((v) => new URL(v).protocol === "https:" && new URL(v).origin === v, "Use an exact HTTPS origin."),
@@ -15853,15 +15854,70 @@ var agentOutcomeSchema = external_exports.object({
15853
15854
  evidence: external_exports.string().max(1e3)
15854
15855
  }).strict();
15855
15856
 
15857
+ // ../recorder/src/collaborator-pointer.ts
15858
+ var collaboratorPointerSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="17.3" height="17.3" viewBox="-0.75 -0.75 17.3 17.3">
15859
+ <!-- Hotspot is (0, 0) in user units: 0.75px right and 0.75px down from the SVG's top-left corner. -->
15860
+ <defs>
15861
+ <linearGradient id="rill-pointer-fill" x1="0" y1="0" x2=".6" y2="1">
15862
+ <stop offset="0" style="stop-color: var(--rill-cursor-accent-light, #8f91f5)"/>
15863
+ <stop offset=".55" style="stop-color: var(--rill-cursor-accent, #6366f1)"/>
15864
+ </linearGradient>
15865
+ </defs>
15866
+ <path d="M0 0L4.1 14.9Q4.5 16.5 5.5 15.2L8.8 8.8L15.2 5.5Q16.5 4.5 14.9 4.1Z" fill="url(#rill-pointer-fill)" stroke="#fff" stroke-width="1.5" stroke-linejoin="round"/>
15867
+ </svg>`;
15868
+ var collaboratorPointerMarkup = `<span class="rill-cursor-shape">${collaboratorPointerSvg}</span><span class="rill-cursor-label">Rill</span>`;
15869
+ var collaboratorPointerStyles = `
15870
+ .rill-cursor-visual { position:absolute; left:0; top:0; width:0; height:0; --rill-cursor-accent-light:color-mix(in srgb,var(--rill-cursor-accent) 72%,#fff); }
15871
+ .rill-cursor-shape { position:absolute; left:-.75px; top:-.75px; width:17.3px; height:17.3px; }
15872
+ .rill-cursor-shape svg { display:block; width:17.3px; height:17.3px; transform-origin:.75px .75px; transition:transform 110ms ease-out; filter:drop-shadow(0 .5px 1px rgba(12,12,18,.25)) drop-shadow(0 1.5px 3px rgba(12,12,18,.14)); }
15873
+ .rill-cursor-visual.is-pressed .rill-cursor-shape svg { transform:scale(.86); transition-duration:50ms; }
15874
+ .rill-cursor-label { position:absolute; left:10px; top:15px; height:15px; padding:0 6px; display:flex; align-items:center; border-radius:8px; font:600 9px/1 system-ui,sans-serif; letter-spacing:.02em; color:#fff; white-space:nowrap; opacity:.92; background:linear-gradient(180deg,color-mix(in srgb,var(--rill-cursor-accent) 78%,#fff),var(--rill-cursor-accent)); box-shadow:0 0 0 1.25px #fff,0 1px 3px rgba(12,12,18,.18),0 0 1px 1.25px rgba(12,12,18,.1); }
15875
+ .rill-cursor-visual.label-left .rill-cursor-label { left:auto; right:4px; }
15876
+ .rill-cursor-visual.label-above .rill-cursor-label { top:auto; bottom:6px; }
15877
+ @media (prefers-reduced-motion:reduce) { .rill-cursor-shape svg { transition:none; } }
15878
+ `;
15879
+
15880
+ // ../recorder/src/scroll-capsule.ts
15881
+ var scrollCapsuleSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="20.5" height="42.5" viewBox="0 0 20.5 42.5">
15882
+ <!-- Capsule body is 18 x 40 at (1.25, 1.25); the white edge sits 1.25px outside it. Shown pointing down. -->
15883
+ <defs>
15884
+ <linearGradient id="rill-capsule-fill" x1="0" y1="0" x2="0" y2="1">
15885
+ <stop offset="0" style="stop-color: var(--rill-cursor-accent-light, #8588f4)"/>
15886
+ <stop offset="1" style="stop-color: var(--rill-cursor-accent, #6366f1)"/>
15887
+ </linearGradient>
15888
+ </defs>
15889
+ <rect x="1.25" y="1.25" width="18" height="40" rx="9" fill="url(#rill-capsule-fill)" stroke="#fff" stroke-width="2.5" paint-order="stroke"/>
15890
+ <!-- For scrolling up, rotate this group 180deg around the capsule center (10.25, 21.25). -->
15891
+ <g id="chevrons" fill="none" stroke="#fff" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round">
15892
+ <path d="M5.85 11.05Q8.85 13.85 10.25 15.25Q11.65 13.85 14.65 11.05" opacity=".32"/>
15893
+ <path d="M5.85 19.05Q8.85 21.85 10.25 23.25Q11.65 21.85 14.65 19.05" opacity=".6"/>
15894
+ <path d="M5.85 27.05Q8.85 29.85 10.25 31.25Q11.65 29.85 14.65 27.05" opacity=".95"/>
15895
+ </g>
15896
+ </svg>`;
15897
+ var scrollCapsuleStyles = `
15898
+ .scroll-indicator { position:absolute; right:12.75px; bottom:10.75px; width:20.5px; height:42.5px; opacity:0; transform:translateY(4px) scale(.92); transform-origin:center; transition:opacity 180ms ease-out,transform 180ms ease-out; filter:drop-shadow(0 1px 1.5px rgba(12,12,18,.18)) drop-shadow(0 4px 5px rgba(12,12,18,.12)); --rill-cursor-accent-light:color-mix(in srgb,var(--rill-cursor-accent) 78%,#fff); }
15899
+ .scroll-indicator.is-visible { opacity:1; transform:none; transition:opacity 160ms ease-out,transform 260ms cubic-bezier(.2,.9,.3,1.25); }
15900
+ .scroll-indicator svg { position:absolute; left:50%; top:50%; width:20.5px; height:42.5px; translate:-50% -50%; transform-origin:center; }
15901
+ .scroll-indicator[data-direction="right"],.scroll-indicator[data-direction="left"] { width:42.5px; height:20.5px; }
15902
+ .scroll-indicator[data-direction="right"] svg { rotate:-90deg; }
15903
+ .scroll-indicator[data-direction="left"] svg { rotate:90deg; }
15904
+ .scroll-indicator[data-direction="unknown"] #chevrons { visibility:hidden; }
15905
+ @media (prefers-reduced-motion:reduce) { .scroll-indicator,.scroll-indicator.is-visible { transform:none; transition:none; } }
15906
+ `;
15907
+
15856
15908
  // ../recorder/src/cursor-overlay.ts
15857
15909
  function installCursorOverlay(options) {
15858
15910
  const scope = window;
15859
15911
  if (scope[options.key]) return;
15860
15912
  let host;
15913
+ let scrollTimer;
15914
+ let scrollExitTimer;
15861
15915
  const controller = new AbortController();
15862
15916
  const animations = /* @__PURE__ */ new Set();
15863
15917
  const cleanup = () => {
15864
15918
  controller.abort();
15919
+ window.clearTimeout(scrollTimer);
15920
+ window.clearTimeout(scrollExitTimer);
15865
15921
  for (const animation of animations) animation.cancel();
15866
15922
  host?.remove();
15867
15923
  delete scope[options.key];
@@ -15877,48 +15933,135 @@ function installCursorOverlay(options) {
15877
15933
  const style = document.createElement("style");
15878
15934
  style.textContent = `
15879
15935
  :host, * { pointer-events: none !important; }
15880
- .pointer { position:absolute; left:0; top:0; display:none; width:24px; height:28px; }
15881
- .halo { position:absolute; left:-12px; top:-12px; width:26px; height:26px; border-radius:50%; background:${options.color}; opacity:.22; }
15882
- svg { position:absolute; left:-2px; top:-2px; width:24px; height:28px; filter:drop-shadow(0 1px 2px #0008); }
15883
- .pulse { position:absolute; width:32px; height:32px; box-sizing:border-box; border:2px solid ${options.color}; border-radius:50%; }
15936
+ ${options.pointerStyles}
15937
+ .pointer { display:none; --rill-cursor-accent:${options.color}; }
15938
+ ${options.scrollStyles}
15939
+ .scroll-indicator { --rill-cursor-accent:${options.color}; }
15940
+ .click-dot, .click-ring { position:absolute; border-radius:50%; transform:translate(-50%,-50%); }
15941
+ .click-dot { width:5px; height:5px; background:${options.color}; box-shadow:0 0 0 1px #fff,0 0 2px rgba(0,0,0,.3); }
15942
+ .click-ring { box-sizing:border-box; border:1px solid ${options.color}; box-shadow:0 0 0 .5px #fffc,inset 0 0 0 .5px #fffc,0 0 2px rgba(0,0,0,.25); }
15884
15943
  `;
15885
15944
  const pointer = document.createElement("div");
15886
- pointer.className = "pointer";
15887
- pointer.innerHTML = '<div class="halo"></div><svg viewBox="0 0 24 28" xmlns="http://www.w3.org/2000/svg"><path d="M3 2 L3 22 L8 17 L12 25 L16 23 L12 15 L20 15 Z" fill="white" stroke="#171717" stroke-width="1.5" stroke-linejoin="round"/></svg>';
15888
- root.append(style, pointer);
15945
+ pointer.className = "pointer rill-cursor-visual";
15946
+ pointer.innerHTML = options.pointerMarkup;
15947
+ const scrollIndicator = document.createElement("div");
15948
+ scrollIndicator.className = "scroll-indicator";
15949
+ scrollIndicator.innerHTML = options.scrollMarkup;
15950
+ const chevrons = scrollIndicator.querySelector("#chevrons");
15951
+ root.append(style, pointer, scrollIndicator);
15889
15952
  document.documentElement.appendChild(host);
15890
15953
  const listenerOptions = { capture: true, passive: true, signal: controller.signal };
15954
+ const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
15955
+ let scrollDirection;
15956
+ let drift;
15957
+ const stopDrift = () => {
15958
+ if (!drift) return;
15959
+ animations.delete(drift);
15960
+ drift.cancel();
15961
+ drift = void 0;
15962
+ };
15963
+ const showScroll = (direction) => {
15964
+ window.clearTimeout(scrollTimer);
15965
+ window.clearTimeout(scrollExitTimer);
15966
+ scrollIndicator.dataset.direction = direction;
15967
+ chevrons.setAttribute("transform", direction === "up" ? "rotate(180 10.25 21.25)" : "");
15968
+ scrollIndicator.classList.add("is-visible");
15969
+ if (reducedMotion.matches || direction === "unknown") stopDrift();
15970
+ else if (direction !== scrollDirection || !drift) {
15971
+ stopDrift();
15972
+ const distance = direction === "up" || direction === "left" ? -3 : 3;
15973
+ const translate = direction === "left" || direction === "right" ? `${distance}px 0` : `0 ${distance}px`;
15974
+ drift = scrollIndicator.animate([
15975
+ { translate: "0 0", easing: "cubic-bezier(.4,0,.6,1)" },
15976
+ { translate, offset: 0.65, easing: "cubic-bezier(.4,0,.2,1)" },
15977
+ { translate: "0 0" }
15978
+ ], { duration: 820, iterations: Infinity });
15979
+ animations.add(drift);
15980
+ void drift.finished.catch(() => void 0);
15981
+ }
15982
+ scrollDirection = direction;
15983
+ scrollTimer = window.setTimeout(() => {
15984
+ scrollIndicator.classList.remove("is-visible");
15985
+ if (reducedMotion.matches) stopDrift();
15986
+ else scrollExitTimer = window.setTimeout(stopDrift, 180);
15987
+ }, 550);
15988
+ };
15989
+ reducedMotion.addEventListener("change", () => {
15990
+ if (reducedMotion.matches) stopDrift();
15991
+ }, { signal: controller.signal });
15992
+ const positions = /* @__PURE__ */ new WeakMap();
15993
+ positions.set(document, { x: window.scrollX, y: window.scrollY });
15994
+ document.addEventListener("scroll", (event) => {
15995
+ if (!event.isTrusted || document.hidden) return;
15996
+ const target = event.target;
15997
+ if (target !== document && !(target instanceof Element)) return;
15998
+ const position = target === document ? { x: window.scrollX, y: window.scrollY } : { x: target.scrollLeft, y: target.scrollTop };
15999
+ const previous = positions.get(target);
16000
+ positions.set(target, position);
16001
+ const dx = previous ? position.x - previous.x : 0;
16002
+ const dy = previous ? position.y - previous.y : 0;
16003
+ if (previous && !dx && !dy) return;
16004
+ const direction = !previous ? "unknown" : Math.abs(dy) >= Math.abs(dx) ? dy > 0 ? "down" : "up" : dx > 0 ? "right" : "left";
16005
+ showScroll(direction);
16006
+ }, listenerOptions);
15891
16007
  const hide = () => {
15892
16008
  pointer.style.display = "none";
16009
+ pointer.classList.remove("is-pressed");
15893
16010
  };
15894
16011
  const move = (event) => {
15895
- if (event.pointerType === "touch") return;
16012
+ if (event.pointerType === "touch") return false;
15896
16013
  if (event.target instanceof HTMLIFrameElement || event.target instanceof HTMLFrameElement) {
15897
16014
  hide();
15898
- return;
16015
+ return false;
15899
16016
  }
15900
16017
  pointer.style.display = "block";
15901
16018
  pointer.style.transform = `translate(${event.clientX}px, ${event.clientY}px)`;
16019
+ pointer.classList.toggle("label-left", event.clientX > window.innerWidth - 90);
16020
+ pointer.classList.toggle("label-above", event.clientY > window.innerHeight - 34);
16021
+ pointer.classList.toggle("is-pressed", event.buttons !== 0);
16022
+ return true;
16023
+ };
16024
+ const release = (event) => {
16025
+ if (event.pointerType !== "touch") pointer.classList.toggle("is-pressed", event.type !== "pointercancel" && event.buttons !== 0);
15902
16026
  };
15903
16027
  document.addEventListener("pointermove", move, listenerOptions);
15904
16028
  document.addEventListener("pointerover", move, listenerOptions);
15905
- document.addEventListener("pointerdown", (event) => {
15906
- if (event.pointerType === "touch") return;
15907
- move(event);
15908
- const pulse = document.createElement("div");
15909
- pulse.className = "pulse";
15910
- pulse.style.left = `${event.clientX - 16}px`;
15911
- pulse.style.top = `${event.clientY - 16}px`;
15912
- root.insertBefore(pulse, pointer);
15913
- const animation = pulse.animate([
15914
- { transform: "scale(.4)", opacity: 0.9 },
15915
- { transform: "scale(1.8)", opacity: 0 }
15916
- ], { duration: 400, easing: "ease-out" });
16029
+ document.addEventListener("pointerup", release, listenerOptions);
16030
+ document.addEventListener("pointercancel", release, listenerOptions);
16031
+ const animateFeedback = (element, frames, duration3, easing) => {
16032
+ root.insertBefore(element, pointer);
16033
+ const animation = element.animate(frames, { duration: duration3, easing });
15917
16034
  animations.add(animation);
15918
16035
  void animation.finished.catch(() => void 0).finally(() => {
15919
16036
  animations.delete(animation);
15920
- pulse.remove();
16037
+ element.remove();
15921
16038
  });
16039
+ };
16040
+ document.addEventListener("pointerdown", (event) => {
16041
+ if (!move(event)) return;
16042
+ const dot = document.createElement("div");
16043
+ dot.className = "click-dot";
16044
+ dot.style.left = `${event.clientX}px`;
16045
+ dot.style.top = `${event.clientY}px`;
16046
+ animateFeedback(dot, reducedMotion.matches ? [{ opacity: 1 }, { opacity: 0 }] : [
16047
+ { transform: "translate(-50%,-50%) scale(1)", opacity: 1, offset: 0 },
16048
+ { transform: "translate(-50%,-50%) scale(1)", opacity: 1, offset: 0.5 },
16049
+ { transform: "translate(-50%,-50%) scale(.3)", opacity: 0, offset: 1 }
16050
+ ], reducedMotion.matches ? 120 : 300, "ease-in");
16051
+ const ring = document.createElement("div");
16052
+ ring.className = "click-ring";
16053
+ ring.style.left = `${event.clientX}px`;
16054
+ ring.style.top = `${event.clientY}px`;
16055
+ if (event.button === 2) ring.style.borderStyle = "dashed";
16056
+ if (reducedMotion.matches) {
16057
+ ring.style.width = "26px";
16058
+ ring.style.height = "26px";
16059
+ }
16060
+ animateFeedback(ring, reducedMotion.matches ? [{ opacity: 1 }, { opacity: 0 }] : [
16061
+ { width: "4px", height: "4px", opacity: 1, offset: 0 },
16062
+ { opacity: 1, offset: 0.4 },
16063
+ { width: "26px", height: "26px", opacity: 0, offset: 1 }
16064
+ ], reducedMotion.matches ? 120 : 320, "cubic-bezier(.2,.7,.2,1)");
15922
16065
  }, listenerOptions);
15923
16066
  document.addEventListener("pointerout", (event) => {
15924
16067
  if (!event.relatedTarget) hide();
@@ -15936,7 +16079,7 @@ async function attachCursorOverlay(page, cdp, input) {
15936
16079
  if (!appearance.enabled) return async () => {
15937
16080
  };
15938
16081
  const key2 = `__rillCursor_${crypto.randomUUID().replaceAll("-", "")}`;
15939
- const source = `(${installCursorOverlay.toString()})(${JSON.stringify({ ...appearance, key: key2 })})`;
16082
+ const source = `(${installCursorOverlay.toString()})(${JSON.stringify({ ...appearance, key: key2, pointerMarkup: collaboratorPointerMarkup, pointerStyles: collaboratorPointerStyles, scrollMarkup: scrollCapsuleSvg, scrollStyles: scrollCapsuleStyles })})`;
15940
16083
  await cdp.send("Page.enable");
15941
16084
  const { identifier } = await cdp.send("Page.addScriptToEvaluateOnNewDocument", { source });
15942
16085
  let stopped = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runalabs/rill-cli",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Record, inspect, and share agent-controlled browser runs with Rill.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {