@runalabs/rill-cli 0.1.17 → 0.1.19

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 +168 -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,71 @@ 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-label { left:auto; right:calc(100% + 7px); top:50%; transform:translateY(-50%); }
15900
+ .scroll-indicator.is-visible { opacity:1; transform:none; transition:opacity 160ms ease-out,transform 260ms cubic-bezier(.2,.9,.3,1.25); }
15901
+ .scroll-indicator svg { position:absolute; left:50%; top:50%; width:20.5px; height:42.5px; translate:-50% -50%; transform-origin:center; }
15902
+ .scroll-indicator[data-direction="right"],.scroll-indicator[data-direction="left"] { width:42.5px; height:20.5px; }
15903
+ .scroll-indicator[data-direction="right"] svg { rotate:-90deg; }
15904
+ .scroll-indicator[data-direction="left"] svg { rotate:90deg; }
15905
+ .scroll-indicator[data-direction="unknown"] #chevrons { visibility:hidden; }
15906
+ @media (prefers-reduced-motion:reduce) { .scroll-indicator,.scroll-indicator.is-visible { transform:none; transition:none; } }
15907
+ `;
15908
+
15856
15909
  // ../recorder/src/cursor-overlay.ts
15857
15910
  function installCursorOverlay(options) {
15858
15911
  const scope = window;
15859
15912
  if (scope[options.key]) return;
15860
15913
  let host;
15914
+ let scrollTimer;
15915
+ let scrollExitTimer;
15861
15916
  const controller = new AbortController();
15862
15917
  const animations = /* @__PURE__ */ new Set();
15863
15918
  const cleanup = () => {
15864
15919
  controller.abort();
15920
+ window.clearTimeout(scrollTimer);
15921
+ window.clearTimeout(scrollExitTimer);
15865
15922
  for (const animation of animations) animation.cancel();
15866
15923
  host?.remove();
15867
15924
  delete scope[options.key];
@@ -15877,48 +15934,135 @@ function installCursorOverlay(options) {
15877
15934
  const style = document.createElement("style");
15878
15935
  style.textContent = `
15879
15936
  :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%; }
15937
+ ${options.pointerStyles}
15938
+ .pointer { display:none; --rill-cursor-accent:${options.color}; }
15939
+ ${options.scrollStyles}
15940
+ .scroll-indicator { --rill-cursor-accent:${options.color}; }
15941
+ .click-dot, .click-ring { position:absolute; border-radius:50%; transform:translate(-50%,-50%); }
15942
+ .click-dot { width:5px; height:5px; background:${options.color}; box-shadow:0 0 0 1px #fff,0 0 2px rgba(0,0,0,.3); }
15943
+ .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
15944
  `;
15885
15945
  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);
15946
+ pointer.className = "pointer rill-cursor-visual";
15947
+ pointer.innerHTML = options.pointerMarkup;
15948
+ const scrollIndicator = document.createElement("div");
15949
+ scrollIndicator.className = "scroll-indicator";
15950
+ scrollIndicator.innerHTML = options.scrollMarkup + '<span class="rill-cursor-label scroll-label">Scrolling</span>';
15951
+ const chevrons = scrollIndicator.querySelector("#chevrons");
15952
+ root.append(style, pointer, scrollIndicator);
15889
15953
  document.documentElement.appendChild(host);
15890
15954
  const listenerOptions = { capture: true, passive: true, signal: controller.signal };
15955
+ const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
15956
+ let scrollDirection;
15957
+ let drift;
15958
+ const stopDrift = () => {
15959
+ if (!drift) return;
15960
+ animations.delete(drift);
15961
+ drift.cancel();
15962
+ drift = void 0;
15963
+ };
15964
+ const showScroll = (direction) => {
15965
+ window.clearTimeout(scrollTimer);
15966
+ window.clearTimeout(scrollExitTimer);
15967
+ scrollIndicator.dataset.direction = direction;
15968
+ chevrons.setAttribute("transform", direction === "up" ? "rotate(180 10.25 21.25)" : "");
15969
+ scrollIndicator.classList.add("is-visible");
15970
+ if (reducedMotion.matches || direction === "unknown") stopDrift();
15971
+ else if (direction !== scrollDirection || !drift) {
15972
+ stopDrift();
15973
+ const distance = direction === "up" || direction === "left" ? -3 : 3;
15974
+ const translate = direction === "left" || direction === "right" ? `${distance}px 0` : `0 ${distance}px`;
15975
+ drift = scrollIndicator.animate([
15976
+ { translate: "0 0", easing: "cubic-bezier(.4,0,.6,1)" },
15977
+ { translate, offset: 0.65, easing: "cubic-bezier(.4,0,.2,1)" },
15978
+ { translate: "0 0" }
15979
+ ], { duration: 820, iterations: Infinity });
15980
+ animations.add(drift);
15981
+ void drift.finished.catch(() => void 0);
15982
+ }
15983
+ scrollDirection = direction;
15984
+ scrollTimer = window.setTimeout(() => {
15985
+ scrollIndicator.classList.remove("is-visible");
15986
+ if (reducedMotion.matches) stopDrift();
15987
+ else scrollExitTimer = window.setTimeout(stopDrift, 180);
15988
+ }, 550);
15989
+ };
15990
+ reducedMotion.addEventListener("change", () => {
15991
+ if (reducedMotion.matches) stopDrift();
15992
+ }, { signal: controller.signal });
15993
+ const positions = /* @__PURE__ */ new WeakMap();
15994
+ positions.set(document, { x: window.scrollX, y: window.scrollY });
15995
+ document.addEventListener("scroll", (event) => {
15996
+ if (!event.isTrusted || document.hidden) return;
15997
+ const target = event.target;
15998
+ if (target !== document && !(target instanceof Element)) return;
15999
+ const position = target === document ? { x: window.scrollX, y: window.scrollY } : { x: target.scrollLeft, y: target.scrollTop };
16000
+ const previous = positions.get(target);
16001
+ positions.set(target, position);
16002
+ const dx = previous ? position.x - previous.x : 0;
16003
+ const dy = previous ? position.y - previous.y : 0;
16004
+ if (previous && !dx && !dy) return;
16005
+ const direction = !previous ? "unknown" : Math.abs(dy) >= Math.abs(dx) ? dy > 0 ? "down" : "up" : dx > 0 ? "right" : "left";
16006
+ showScroll(direction);
16007
+ }, listenerOptions);
15891
16008
  const hide = () => {
15892
16009
  pointer.style.display = "none";
16010
+ pointer.classList.remove("is-pressed");
15893
16011
  };
15894
16012
  const move = (event) => {
15895
- if (event.pointerType === "touch") return;
16013
+ if (event.pointerType === "touch") return false;
15896
16014
  if (event.target instanceof HTMLIFrameElement || event.target instanceof HTMLFrameElement) {
15897
16015
  hide();
15898
- return;
16016
+ return false;
15899
16017
  }
15900
16018
  pointer.style.display = "block";
15901
16019
  pointer.style.transform = `translate(${event.clientX}px, ${event.clientY}px)`;
16020
+ pointer.classList.toggle("label-left", event.clientX > window.innerWidth - 90);
16021
+ pointer.classList.toggle("label-above", event.clientY > window.innerHeight - 34);
16022
+ pointer.classList.toggle("is-pressed", event.buttons !== 0);
16023
+ return true;
16024
+ };
16025
+ const release = (event) => {
16026
+ if (event.pointerType !== "touch") pointer.classList.toggle("is-pressed", event.type !== "pointercancel" && event.buttons !== 0);
15902
16027
  };
15903
16028
  document.addEventListener("pointermove", move, listenerOptions);
15904
16029
  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" });
16030
+ document.addEventListener("pointerup", release, listenerOptions);
16031
+ document.addEventListener("pointercancel", release, listenerOptions);
16032
+ const animateFeedback = (element, frames, duration3, easing) => {
16033
+ root.insertBefore(element, pointer);
16034
+ const animation = element.animate(frames, { duration: duration3, easing });
15917
16035
  animations.add(animation);
15918
16036
  void animation.finished.catch(() => void 0).finally(() => {
15919
16037
  animations.delete(animation);
15920
- pulse.remove();
16038
+ element.remove();
15921
16039
  });
16040
+ };
16041
+ document.addEventListener("pointerdown", (event) => {
16042
+ if (!move(event)) return;
16043
+ const dot = document.createElement("div");
16044
+ dot.className = "click-dot";
16045
+ dot.style.left = `${event.clientX}px`;
16046
+ dot.style.top = `${event.clientY}px`;
16047
+ animateFeedback(dot, reducedMotion.matches ? [{ opacity: 1 }, { opacity: 0 }] : [
16048
+ { transform: "translate(-50%,-50%) scale(1)", opacity: 1, offset: 0 },
16049
+ { transform: "translate(-50%,-50%) scale(1)", opacity: 1, offset: 0.5 },
16050
+ { transform: "translate(-50%,-50%) scale(.3)", opacity: 0, offset: 1 }
16051
+ ], reducedMotion.matches ? 120 : 300, "ease-in");
16052
+ const ring = document.createElement("div");
16053
+ ring.className = "click-ring";
16054
+ ring.style.left = `${event.clientX}px`;
16055
+ ring.style.top = `${event.clientY}px`;
16056
+ if (event.button === 2) ring.style.borderStyle = "dashed";
16057
+ if (reducedMotion.matches) {
16058
+ ring.style.width = "26px";
16059
+ ring.style.height = "26px";
16060
+ }
16061
+ animateFeedback(ring, reducedMotion.matches ? [{ opacity: 1 }, { opacity: 0 }] : [
16062
+ { width: "4px", height: "4px", opacity: 1, offset: 0 },
16063
+ { opacity: 1, offset: 0.4 },
16064
+ { width: "26px", height: "26px", opacity: 0, offset: 1 }
16065
+ ], reducedMotion.matches ? 120 : 320, "cubic-bezier(.2,.7,.2,1)");
15922
16066
  }, listenerOptions);
15923
16067
  document.addEventListener("pointerout", (event) => {
15924
16068
  if (!event.relatedTarget) hide();
@@ -15936,7 +16080,7 @@ async function attachCursorOverlay(page, cdp, input) {
15936
16080
  if (!appearance.enabled) return async () => {
15937
16081
  };
15938
16082
  const key2 = `__rillCursor_${crypto.randomUUID().replaceAll("-", "")}`;
15939
- const source = `(${installCursorOverlay.toString()})(${JSON.stringify({ ...appearance, key: key2 })})`;
16083
+ const source = `(${installCursorOverlay.toString()})(${JSON.stringify({ ...appearance, key: key2, pointerMarkup: collaboratorPointerMarkup, pointerStyles: collaboratorPointerStyles, scrollMarkup: scrollCapsuleSvg, scrollStyles: scrollCapsuleStyles })})`;
15940
16084
  await cdp.send("Page.enable");
15941
16085
  const { identifier } = await cdp.send("Page.addScriptToEvaluateOnNewDocument", { source });
15942
16086
  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.19",
4
4
  "description": "Record, inspect, and share agent-controlled browser runs with Rill.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {