@flowriki/agent 0.1.0-beta.3 → 0.1.0-beta.5
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/dist/accname.global.js +1 -0
- package/dist/{chunk-XT52RW5S.js → chunk-QJOMJVCO.js} +141 -67
- package/dist/cli.js +9 -3
- package/dist/engine.js +5 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{function U(e,t,i){function u(r){let o=e.__flAccName;if(o){let a=o(r);return a||t(r.placeholder)||t(r.title)||""}return b(r)}function b(r){let o=r.getAttribute&&r.getAttribute("aria-labelledby");if(o){let d=o.split(/\s+/).map(g=>document.getElementById(g)).filter(Boolean).map(g=>t(g.textContent)).filter(Boolean).join(" ");if(d)return d}let a=t(r.getAttribute&&r.getAttribute("aria-label"));if(a)return a;if(r.id){let d=document.querySelector('label[for="'+CSS.escape(r.id)+'"]');if(d&&t(d.textContent))return t(d.textContent)}let l=r.closest&&r.closest("label");if(l&&t(l.textContent))return t(l.textContent);let s=r.tagName.toLowerCase(),p=(r.type||"").toLowerCase();return(["button","a","summary"].includes(s)||r.getAttribute&&r.getAttribute("role")==="button")&&t(r.textContent)?t(r.textContent):s==="input"&&["submit","button","reset"].includes(p)&&r.value?t(r.value):t(r.placeholder)||t(r.title)||""}let S="input,select,textarea,button,meter,output,progress,[contenteditable]";function y(r){let o=r.parentElement;if(!o||!r.matches?.(S))return"";for(let a of Array.from(o.querySelectorAll("label"))){let l=a.getAttribute("for");if(l&&document.getElementById(l))continue;let s=t(a.textContent);if(s)return s}return""}let E=new WeakMap,P=crypto.randomUUID(),_=0;function T(r){let o=E.get(r);o||(o=`${P}:${++_}`,E.set(r,o));let a={__targetId:o},l=r.getRootNode(),s=r.getAttribute("data-testid");if(s&&l.querySelectorAll(`[data-testid=${JSON.stringify(s)}]`).length===1)return{...a,name:u(r),locator:{strategy:"testId",value:s}};if(r.type==="password"&&u(r))return{...a,name:u(r),locator:{strategy:"label",value:u(r)}};let p=r.getAttribute("title");if(p&&l.querySelectorAll(`[title=${JSON.stringify(p)}]`).length===1)return{...a,name:u(r),locator:{strategy:"title",value:p}};let d=u(r);if(d)return{...a,name:d};let g=y(r);if(g)return{...a,name:g,nameFrom:"adjacent-label"};let v=t(Array.from(r.childNodes||[]).filter(A=>A.nodeType===3).map(A=>A.textContent).join(" "));return v&&v.length<=80?{...a,name:v,nameFrom:"text"}:r.id&&!/:r|[a-f0-9]{12}|\d{6}/i.test(r.id)&&l.querySelectorAll(`#${CSS.escape(r.id)}`).length===1?{...a,name:"",locator:{strategy:"css",value:`#${CSS.escape(r.id)}`}}:{...a,name:""}}function N(r){let o=r.getAttribute&&r.getAttribute("role");if(o)return o;let a=r.tagName.toLowerCase(),l=(r.type||"").toLowerCase();return a==="button"?"button":a==="a"&&r.href?"link":a==="select"?r.multiple||r.size>1?"listbox":"combobox":a==="textarea"?"textbox":a==="input"?["submit","button","reset","file"].includes(l)?"button":l==="checkbox"||l==="radio"?l:l==="number"?"spinbutton":l==="search"?"searchbox":l==="range"?"slider":"textbox":r.isContentEditable?"textbox":H[a]??""}let H={li:"listitem",ul:"list",ol:"list",tr:"row",td:"cell",th:"columnheader",table:"table",nav:"navigation",main:"main",header:"banner",footer:"contentinfo",aside:"complementary",form:"form",dialog:"dialog",details:"group",fieldset:"group",img:"img",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading"};function j(r){let o=r,a=null;for(let l=0;o&&l<6&&!(o===document.body||o===document.documentElement);l++){let s="";try{s=getComputedStyle(o).cursor}catch{break}if(s==="pointer")a=o;else if(a)break;o=o.parentElement}return a}let C="tr, [role=row], li, [role=listitem], [role=article], [role=gridcell]";function L(r){try{let o=r.cloneNode(!0);for(let a of Array.from(o.querySelectorAll(i+", input, select, textarea")))a.remove();for(let a of Array.from(o.querySelectorAll("td, th, li, p, div, span, tr")))a.append(" ");return t(o.textContent).slice(0,120)}catch{return""}}function D(r,o,a){if(!a)return!1;let l;try{l=Array.from(document.querySelectorAll(i+", input, select, textarea"))}catch{return!1}if(l.length>400)return!0;let s=0;for(let p of l)if(p!==r&&N(p)===o&&T(p).name===a&&++s>0)return!0;return!1}function V(r,o,a){if(!D(r,o,a))return null;let l=r.closest&&r.closest(C);if(!l)return null;let s=L(l);if(!s)return null;let p=l.getAttribute&&l.getAttribute("role"),d=l.tagName.toLowerCase();return{scope:s,scopeRole:p||(d==="tr"?"row":d==="li"?"listitem":d)}}function x(r,o,a){let l=V(r,o,a);return l||{scope:n(r)}}function n(r){let o=r.closest&&r.closest("form, fieldset, section, [role=group], [role=region], [role=dialog], [role=alertdialog], dialog");return o?u(o):""}function f(r){if(r.id)return"#"+CSS.escape(r.id);let o=[],a=r;for(;a&&a.nodeType===1&&a!==document.body;){let l=Array.from(a.parentNode?a.parentNode.children:[]).filter(s=>s.tagName===a.tagName);o.unshift(l.length>1?`${a.tagName.toLowerCase()}:nth-of-type(${l.indexOf(a)+1})`:a.tagName.toLowerCase()),a=a.parentElement}return"body > "+o.join(" > ")}return{accName:u,identify:T,roleOf:N,pointerTarget:j,scoping:x,cssPath:f}}var ge=Object.prototype.toString;function Q(e){return typeof e=="function"||ge.call(e)==="[object Function]"}function ye(e){var t=Number(e);return isNaN(t)?0:t===0||!isFinite(t)?t:(t>0?1:-1)*Math.floor(Math.abs(t))}var he=Math.pow(2,53)-1;function ve(e){var t=ye(e);return Math.min(Math.max(t,0),he)}function h(e,t){var i=Array,u=Object(e);if(e==null)throw new TypeError("Array.from requires an array-like object - not null or undefined");if(typeof t<"u"&&!Q(t))throw new TypeError("Array.from: when provided, the second argument must be a function");for(var b=ve(u.length),S=Q(i)?Object(new i(b)):new Array(b),y=0,E;y<b;)E=u[y],t?S[y]=t(E,y):S[y]=E,y+=1;return S.length=b,S}function I(e){"@babel/helpers - typeof";return I=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},I(e)}function we(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function X(e,t){for(var i=0;i<t.length;i++){var u=t[i];u.enumerable=u.enumerable||!1,u.configurable=!0,"value"in u&&(u.writable=!0),Object.defineProperty(e,Y(u.key),u)}}function Se(e,t,i){return t&&X(e.prototype,t),i&&X(e,i),Object.defineProperty(e,"prototype",{writable:!1}),e}function Ee(e,t,i){return t=Y(t),t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function Y(e){var t=xe(e,"string");return I(t)=="symbol"?t:t+""}function xe(e,t){if(I(e)!="object"||!e)return e;var i=e[Symbol.toPrimitive];if(i!==void 0){var u=i.call(e,t||"default");if(I(u)!="object")return u;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}var Ae=(function(){function e(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:[];we(this,e),Ee(this,"items",void 0),this.items=t}return Se(e,[{key:"add",value:function(i){return this.has(i)===!1&&this.items.push(i),this}},{key:"clear",value:function(){this.items=[]}},{key:"delete",value:function(i){var u=this.items.length;return this.items=this.items.filter(function(b){return b!==i}),u!==this.items.length}},{key:"forEach",value:function(i){var u=this;this.items.forEach(function(b){i(b,b,u)})}},{key:"has",value:function(i){return this.items.indexOf(i)!==-1}},{key:"size",get:function(){return this.items.length}}])})(),Z=typeof Set>"u"?Set:Ae;function m(e){var t;return(t=e.localName)!==null&&t!==void 0?t:e.tagName.toLowerCase()}var Le={article:"article",aside:"complementary",button:"button",datalist:"listbox",dd:"definition",details:"group",dialog:"dialog",dt:"term",fieldset:"group",figure:"figure",form:"form",footer:"contentinfo",h1:"heading",h2:"heading",h3:"heading",h4:"heading",h5:"heading",h6:"heading",header:"banner",hr:"separator",html:"document",legend:"legend",li:"listitem",math:"math",main:"main",menu:"list",nav:"navigation",ol:"list",optgroup:"group",option:"option",output:"status",progress:"progressbar",section:"region",summary:"button",table:"table",tbody:"rowgroup",textarea:"textbox",tfoot:"rowgroup",td:"cell",th:"columnheader",thead:"rowgroup",tr:"row",ul:"list"},Te={caption:new Set(["aria-label","aria-labelledby"]),code:new Set(["aria-label","aria-labelledby"]),deletion:new Set(["aria-label","aria-labelledby"]),emphasis:new Set(["aria-label","aria-labelledby"]),generic:new Set(["aria-label","aria-labelledby","aria-roledescription"]),insertion:new Set(["aria-label","aria-labelledby"]),none:new Set(["aria-label","aria-labelledby"]),paragraph:new Set(["aria-label","aria-labelledby"]),presentation:new Set(["aria-label","aria-labelledby"]),strong:new Set(["aria-label","aria-labelledby"]),subscript:new Set(["aria-label","aria-labelledby"]),superscript:new Set(["aria-label","aria-labelledby"])};function Ne(e,t){return["aria-atomic","aria-busy","aria-controls","aria-current","aria-description","aria-describedby","aria-details","aria-dropeffect","aria-flowto","aria-grabbed","aria-hidden","aria-keyshortcuts","aria-label","aria-labelledby","aria-live","aria-owns","aria-relevant","aria-roledescription"].some(function(i){var u;return e.hasAttribute(i)&&!((u=Te[t])!==null&&u!==void 0&&u.has(i))})}function ee(e,t){return Ne(e,t)}function k(e){var t=Ie(e);if(t===null||O.indexOf(t)!==-1){var i=Ce(e);if(O.indexOf(t||"")===-1||ee(e,i||""))return i}return t}function Ce(e){var t=Le[m(e)];if(t!==void 0)return t;switch(m(e)){case"a":case"area":case"link":if(e.hasAttribute("href"))return"link";break;case"img":return e.getAttribute("alt")===""&&!ee(e,"img")?"presentation":"img";case"input":{var i=e,u=i.type;switch(u){case"button":case"image":case"reset":case"submit":return"button";case"checkbox":case"radio":return u;case"range":return"slider";case"email":case"tel":case"text":case"url":return e.hasAttribute("list")?"combobox":"textbox";case"search":return e.hasAttribute("list")?"combobox":"searchbox";case"number":return"spinbutton";default:return null}}case"select":return e.hasAttribute("multiple")||e.size>1?"listbox":"combobox"}return null}function Ie(e){var t=e.getAttribute("role");if(t!==null){var i=t.trim().split(" ")[0];if(i.length>0)return i}return null}var O=["presentation","none"];function c(e){return e!==null&&e.nodeType===e.ELEMENT_NODE}function G(e){return c(e)&&m(e)==="caption"}function R(e){return c(e)&&m(e)==="input"}function te(e){return c(e)&&m(e)==="optgroup"}function re(e){return c(e)&&m(e)==="select"}function ne(e){return c(e)&&m(e)==="table"}function ie(e){return c(e)&&m(e)==="textarea"}function ae(e){var t=e.ownerDocument===null?e:e.ownerDocument,i=t.defaultView;if(i===null)throw new TypeError("no window available");return i}function oe(e){return c(e)&&m(e)==="fieldset"}function ue(e){return c(e)&&m(e)==="legend"}function le(e){return c(e)&&m(e)==="slot"}function Oe(e){return c(e)&&e.ownerSVGElement!==void 0}function se(e){return c(e)&&m(e)==="svg"}function fe(e){return Oe(e)&&m(e)==="title"}function M(e,t){if(c(e)&&e.hasAttribute(t)){var i=e.getAttribute(t).split(" "),u=e.getRootNode?e.getRootNode():e.ownerDocument;return i.map(function(b){return u.getElementById(b)}).filter(function(b){return b!==null})}return[]}function w(e,t){return c(e)?t.indexOf(k(e))!==-1:!1}function Re(e){return e.trim().replace(/\s\s+/g," ")}function Me(e,t){if(!c(e))return!1;if(e.hasAttribute("hidden")||e.getAttribute("aria-hidden")==="true")return!0;var i=t(e);return i.getPropertyValue("display")==="none"||i.getPropertyValue("visibility")==="hidden"}function Pe(e){return w(e,["button","combobox","listbox","textbox"])||me(e,"range")}function me(e,t){if(!c(e))return!1;if(t==="range")return w(e,["meter","progressbar","scrollbar","slider","spinbutton"]);throw new TypeError("No knowledge about abstract role '".concat(t,"'. This is likely a bug :("))}function ce(e,t){var i=h(e.querySelectorAll(t));return M(e,"aria-owns").forEach(function(u){i.push.apply(i,h(u.querySelectorAll(t)))}),i}function _e(e){return re(e)?e.selectedOptions||ce(e,"[selected]"):ce(e,'[aria-selected="true"]')}function je(e){return w(e,O)}function ke(e){return G(e)}function He(e){return w(e,["button","cell","checkbox","columnheader","gridcell","heading","label","legend","link","menuitem","menuitemcheckbox","menuitemradio","option","radio","row","rowheader","switch","tab","tooltip","treeitem"])}function De(e){return!1}function Ve(e){return R(e)||ie(e)?e.value:e.textContent||""}function de(e){var t=e.getPropertyValue("content");return/^["'].*["']$/.test(t)?t.slice(1,-1):""}function pe(e){var t=m(e);return t==="button"||t==="input"&&e.getAttribute("type")!=="hidden"||t==="meter"||t==="output"||t==="progress"||t==="select"||t==="textarea"}function be(e){if(pe(e))return e;var t=null;return e.childNodes.forEach(function(i){if(t===null&&c(i)){var u=be(i);u!==null&&(t=u)}}),t}function $e(e){if(e.control!==void 0)return e.control;var t=e.getAttribute("for");return t!==null?e.ownerDocument.getElementById(t):be(e)}function qe(e){var t=e.labels;if(t===null)return t;if(t!==void 0)return h(t);if(!pe(e))return null;var i=e.ownerDocument;return h(i.querySelectorAll("label")).filter(function(u){return $e(u)===e})}function Ge(e){var t=e.assignedNodes();return t.length===0?h(e.childNodes):t}function B(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},i=new Z,u=typeof Map>"u"?void 0:new Map,b=ae(e),S=t.compute,y=S===void 0?"name":S,E=t.computedStyleSupportsPseudoElements,P=E===void 0?t.getComputedStyle!==void 0:E,_=t.getComputedStyle,T=_===void 0?b.getComputedStyle.bind(b):_,N=t.hidden,H=N===void 0?!1:N,j=function(f,r){if(r!==void 0)throw new Error("use uncachedGetComputedStyle directly for pseudo elements");if(u===void 0)return T(f);var o=u.get(f);if(o)return o;var a=T(f,r);return u.set(f,a),a};function C(n,f){var r="";if(c(n)&&P){var o=T(n,"::before"),a=de(o);r="".concat(a," ").concat(r)}var l=le(n)?Ge(n):h(n.childNodes).concat(M(n,"aria-owns"));if(l.forEach(function(d){var g=x(d,{isEmbeddedInLabel:f.isEmbeddedInLabel,isReferenced:!1,recursion:!0}),v=c(d)?j(d).getPropertyValue("display"):"inline",A=v!=="inline"?" ":"";r+="".concat(A).concat(g).concat(A)}),c(n)&&P){var s=T(n,"::after"),p=de(s);r="".concat(r," ").concat(p)}return r.trim()}function L(n,f){var r=n.getAttributeNode(f);return r!==null&&!i.has(r)&&r.value.trim()!==""?(i.add(r),r.value):null}function D(n){return c(n)?L(n,"title"):null}function V(n){if(!c(n))return null;if(oe(n)){i.add(n);for(var f=h(n.childNodes),r=0;r<f.length;r+=1){var o=f[r];if(ue(o))return x(o,{isEmbeddedInLabel:!1,isReferenced:!1,recursion:!1})}}else if(ne(n)){i.add(n);for(var a=h(n.childNodes),l=0;l<a.length;l+=1){var s=a[l];if(G(s))return x(s,{isEmbeddedInLabel:!1,isReferenced:!1,recursion:!1})}}else if(se(n)){i.add(n);for(var p=h(n.childNodes),d=0;d<p.length;d+=1){var g=p[d];if(fe(g))return g.textContent}return null}else if(m(n)==="img"||m(n)==="area"){var v=L(n,"alt");if(v!==null)return v}else if(te(n)){var A=L(n,"label");if(A!==null)return A}if(R(n)&&(n.type==="button"||n.type==="submit"||n.type==="reset")){var z=L(n,"value");if(z!==null)return z;if(n.type==="submit")return"Submit";if(n.type==="reset")return"Reset"}var $=qe(n);if($!==null&&$.length!==0)return i.add(n),h($).map(function(q){return x(q,{isEmbeddedInLabel:!0,isReferenced:!1,recursion:!0})}).filter(function(q){return q.length>0}).join(" ");if(R(n)&&n.type==="image"){var F=L(n,"alt");if(F!==null)return F;var J=L(n,"title");return J!==null?J:"Submit Query"}if(w(n,["button"])){var K=C(n,{isEmbeddedInLabel:!1,isReferenced:!1});if(K!=="")return K}return null}function x(n,f){if(i.has(n))return"";if(!H&&Me(n,j)&&!f.isReferenced)return i.add(n),"";var r=c(n)?n.getAttributeNode("aria-labelledby"):null,o=r!==null&&!i.has(r)?M(n,"aria-labelledby"):[];if(y==="name"&&!f.isReferenced&&o.length>0)return i.add(r),o.map(function(v){return x(v,{isEmbeddedInLabel:f.isEmbeddedInLabel,isReferenced:!0,recursion:!1})}).join(" ");var a=f.recursion&&Pe(n)&&y==="name";if(!a){var l=(c(n)&&n.getAttribute("aria-label")||"").trim();if(l!==""&&y==="name")return i.add(n),l;if(!je(n)){var s=V(n);if(s!==null)return i.add(n),s}}if(w(n,["menu"]))return i.add(n),"";if(a||f.isEmbeddedInLabel||f.isReferenced){if(w(n,["combobox","listbox"])){i.add(n);var p=_e(n);return p.length===0?R(n)?n.value:"":h(p).map(function(v){return x(v,{isEmbeddedInLabel:f.isEmbeddedInLabel,isReferenced:!1,recursion:!0})}).join(" ")}if(me(n,"range"))return i.add(n),n.hasAttribute("aria-valuetext")?n.getAttribute("aria-valuetext"):n.hasAttribute("aria-valuenow")?n.getAttribute("aria-valuenow"):n.getAttribute("value")||"";if(w(n,["textbox"]))return i.add(n),Ve(n)}if(He(n)||c(n)&&f.isReferenced||ke(n)||De(n)){var d=C(n,{isEmbeddedInLabel:f.isEmbeddedInLabel,isReferenced:!1});if(d!=="")return i.add(n),d}if(n.nodeType===n.TEXT_NODE)return i.add(n),n.textContent||"";if(f.recursion)return i.add(n),C(n,{isEmbeddedInLabel:f.isEmbeddedInLabel,isReferenced:!1});var g=D(n);return g!==null?(i.add(n),g):(i.add(n),"")}return Re(x(e,{isEmbeddedInLabel:!1,isReferenced:y==="description",recursion:!1}))}function Be(e){return w(e,["caption","code","deletion","emphasis","generic","insertion","none","paragraph","presentation","strong","subscript","superscript"])}function W(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};return Be(e)?"":B(e,t)}window.__flAccName=e=>{try{return W(e).replace(/\s+/g," ").trim()}catch{return""}};window.__flCreateTargetIdentity=U;})();
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
// src/engine.ts
|
|
4
4
|
import os5 from "os";
|
|
5
|
+
import { createRequire as createRequire3 } from "module";
|
|
6
|
+
import { spawnSync } from "child_process";
|
|
5
7
|
|
|
6
8
|
// ../agent-core/dist/index.js
|
|
7
9
|
import { z as z4 } from "zod";
|
|
8
10
|
import fs5 from "fs";
|
|
9
|
-
import
|
|
11
|
+
import path5 from "path";
|
|
10
12
|
import crypto22 from "crypto";
|
|
11
|
-
import { createRequire as
|
|
13
|
+
import { createRequire as createRequire2 } from "module";
|
|
12
14
|
import { WebSocket, WebSocketServer } from "ws";
|
|
13
15
|
import fs23 from "fs";
|
|
14
16
|
import os2 from "os";
|
|
@@ -16,7 +18,7 @@ import path23 from "path";
|
|
|
16
18
|
|
|
17
19
|
// ../orchestrator/dist/index.js
|
|
18
20
|
import fs4 from "fs";
|
|
19
|
-
import
|
|
21
|
+
import path4 from "path";
|
|
20
22
|
|
|
21
23
|
// ../protocol/dist/chunk-ROEX7TWK.js
|
|
22
24
|
import { z } from "zod";
|
|
@@ -880,8 +882,8 @@ function installRecorder() {
|
|
|
880
882
|
return Boolean(el?.closest?.("[data-flowriki],[data-flowriki-debug]"));
|
|
881
883
|
}
|
|
882
884
|
function actualTarget(e) {
|
|
883
|
-
const
|
|
884
|
-
const first =
|
|
885
|
+
const path8 = typeof e.composedPath === "function" ? e.composedPath() : [];
|
|
886
|
+
const first = path8[0];
|
|
885
887
|
return (first && first.tagName ? first : e.target) ?? null;
|
|
886
888
|
}
|
|
887
889
|
w.__flSignature = () => {
|
|
@@ -2136,14 +2138,15 @@ function installDebugPanel() {
|
|
|
2136
2138
|
// ../runner/dist/index.js
|
|
2137
2139
|
import fs from "fs";
|
|
2138
2140
|
import { createRequire } from "module";
|
|
2141
|
+
import path from "path";
|
|
2142
|
+
import { fileURLToPath } from "url";
|
|
2139
2143
|
import "playwright";
|
|
2140
2144
|
import "playwright";
|
|
2141
2145
|
import { errors } from "playwright";
|
|
2142
2146
|
import fs2 from "fs";
|
|
2143
|
-
import
|
|
2147
|
+
import path2 from "path";
|
|
2144
2148
|
import "playwright";
|
|
2145
2149
|
import fs3 from "fs";
|
|
2146
|
-
import { createRequire as createRequire2 } from "module";
|
|
2147
2150
|
import "playwright";
|
|
2148
2151
|
var DEFAULT_ENVIRONMENT = {
|
|
2149
2152
|
browser: "chromium",
|
|
@@ -2407,15 +2410,24 @@ var COMMITS = /* @__PURE__ */ new Set([
|
|
|
2407
2410
|
"forward"
|
|
2408
2411
|
]);
|
|
2409
2412
|
var cachedAccNameScript = null;
|
|
2413
|
+
var ACCNAME_ASSET = "accname.global.js";
|
|
2410
2414
|
function accNameScript() {
|
|
2411
2415
|
if (cachedAccNameScript === null) {
|
|
2412
|
-
|
|
2413
|
-
"@flowriki/recorder/accname.global.js"
|
|
2414
|
-
);
|
|
2415
|
-
cachedAccNameScript = fs.readFileSync(path24, "utf8");
|
|
2416
|
+
cachedAccNameScript = fs.readFileSync(accNameScriptPath(), "utf8");
|
|
2416
2417
|
}
|
|
2417
2418
|
return cachedAccNameScript;
|
|
2418
2419
|
}
|
|
2420
|
+
function accNameScriptPath() {
|
|
2421
|
+
try {
|
|
2422
|
+
return createRequire(import.meta.url).resolve("@flowriki/recorder/accname.global.js");
|
|
2423
|
+
} catch {
|
|
2424
|
+
const beside = path.join(path.dirname(fileURLToPath(import.meta.url)), ACCNAME_ASSET);
|
|
2425
|
+
if (fs.existsSync(beside)) return beside;
|
|
2426
|
+
throw new Error(
|
|
2427
|
+
`this build is missing ${ACCNAME_ASSET}, which recording injects into the page \u2014 reinstall the agent`
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2419
2431
|
async function startRecordingSession(opts) {
|
|
2420
2432
|
const { headless = false, onStep, onState, onDisconnect, onStopRequested } = opts;
|
|
2421
2433
|
const url = normalizeStartUrl(opts.url);
|
|
@@ -2872,7 +2884,7 @@ async function captureFailure(opts) {
|
|
|
2872
2884
|
const file = `step-${String(ordinal).padStart(2, "0")}.png`;
|
|
2873
2885
|
fs2.mkdirSync(dir, { recursive: true });
|
|
2874
2886
|
await page.screenshot({
|
|
2875
|
-
path:
|
|
2887
|
+
path: path2.join(dir, file),
|
|
2876
2888
|
// The viewport, not the full page: a failure is about what was on screen,
|
|
2877
2889
|
// and a full-page capture of an infinite-scroll app is a 20MB image.
|
|
2878
2890
|
fullPage: false,
|
|
@@ -2923,7 +2935,7 @@ async function finaliseArtifacts(opts) {
|
|
|
2923
2935
|
const out = [];
|
|
2924
2936
|
const size = (file) => {
|
|
2925
2937
|
try {
|
|
2926
|
-
return fs2.statSync(
|
|
2938
|
+
return fs2.statSync(path2.join(dir, file)).size;
|
|
2927
2939
|
} catch {
|
|
2928
2940
|
return null;
|
|
2929
2941
|
}
|
|
@@ -2933,7 +2945,7 @@ async function finaliseArtifacts(opts) {
|
|
|
2933
2945
|
try {
|
|
2934
2946
|
if (keep(artifacts.trace)) {
|
|
2935
2947
|
fs2.mkdirSync(dir, { recursive: true });
|
|
2936
|
-
await context.tracing.stop({ path:
|
|
2948
|
+
await context.tracing.stop({ path: path2.join(dir, file) });
|
|
2937
2949
|
out.push({ kind: "trace", relPath: file, bytes: size(file) });
|
|
2938
2950
|
} else {
|
|
2939
2951
|
await context.tracing.stop();
|
|
@@ -2945,7 +2957,7 @@ async function finaliseArtifacts(opts) {
|
|
|
2945
2957
|
const file = "console.log";
|
|
2946
2958
|
try {
|
|
2947
2959
|
fs2.mkdirSync(dir, { recursive: true });
|
|
2948
|
-
fs2.writeFileSync(
|
|
2960
|
+
fs2.writeFileSync(path2.join(dir, file), consoleLines.join("\n") + "\n");
|
|
2949
2961
|
out.push({ kind: "console", relPath: file, bytes: size(file) });
|
|
2950
2962
|
} catch {
|
|
2951
2963
|
}
|
|
@@ -2960,13 +2972,13 @@ function collectVideos(dir, keep) {
|
|
|
2960
2972
|
return [];
|
|
2961
2973
|
}
|
|
2962
2974
|
if (!keep) {
|
|
2963
|
-
for (const f of files) fs2.rmSync(
|
|
2975
|
+
for (const f of files) fs2.rmSync(path2.join(dir, f), { force: true });
|
|
2964
2976
|
return [];
|
|
2965
2977
|
}
|
|
2966
2978
|
return files.map((f) => {
|
|
2967
2979
|
let bytes = null;
|
|
2968
2980
|
try {
|
|
2969
|
-
bytes = fs2.statSync(
|
|
2981
|
+
bytes = fs2.statSync(path2.join(dir, f)).size;
|
|
2970
2982
|
} catch {
|
|
2971
2983
|
bytes = null;
|
|
2972
2984
|
}
|
|
@@ -3609,8 +3621,8 @@ async function verifySteps(opts) {
|
|
|
3609
3621
|
var cachedAccName = null;
|
|
3610
3622
|
function accNameScript2() {
|
|
3611
3623
|
if (cachedAccName === null) {
|
|
3612
|
-
const
|
|
3613
|
-
cachedAccName = fs3.readFileSync(
|
|
3624
|
+
const path33 = accNameScriptPath();
|
|
3625
|
+
cachedAccName = fs3.readFileSync(path33, "utf8");
|
|
3614
3626
|
}
|
|
3615
3627
|
return cachedAccName;
|
|
3616
3628
|
}
|
|
@@ -3992,7 +4004,7 @@ async function startDebugSession(opts) {
|
|
|
3992
4004
|
|
|
3993
4005
|
// ../rundb/dist/index.js
|
|
3994
4006
|
import os from "os";
|
|
3995
|
-
import
|
|
4007
|
+
import path3 from "path";
|
|
3996
4008
|
var MIGRATIONS2 = [
|
|
3997
4009
|
// 1 — initial
|
|
3998
4010
|
`
|
|
@@ -4139,10 +4151,10 @@ var MIGRATIONS2 = [
|
|
|
4139
4151
|
];
|
|
4140
4152
|
var SCHEMA_VERSION = MIGRATIONS2.length;
|
|
4141
4153
|
function flowrikiHome() {
|
|
4142
|
-
return process.env.FLOWRIKI_HOME ||
|
|
4154
|
+
return process.env.FLOWRIKI_HOME || path3.join(os.homedir(), ".flowriki");
|
|
4143
4155
|
}
|
|
4144
4156
|
function runArtifactsDir(runId, projectId = "default") {
|
|
4145
|
-
return
|
|
4157
|
+
return path3.join(flowrikiHome(), "projects", safe(projectId), "runs", safe(runId));
|
|
4146
4158
|
}
|
|
4147
4159
|
function safe(segment) {
|
|
4148
4160
|
if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(segment) || segment.includes("..")) {
|
|
@@ -4151,9 +4163,9 @@ function safe(segment) {
|
|
|
4151
4163
|
return segment;
|
|
4152
4164
|
}
|
|
4153
4165
|
function isInside(root, candidate) {
|
|
4154
|
-
const base =
|
|
4155
|
-
const target =
|
|
4156
|
-
return target === base || target.startsWith(base +
|
|
4166
|
+
const base = path3.resolve(root);
|
|
4167
|
+
const target = path3.resolve(candidate);
|
|
4168
|
+
return target === base || target.startsWith(base + path3.sep);
|
|
4157
4169
|
}
|
|
4158
4170
|
|
|
4159
4171
|
// ../orchestrator/dist/index.js
|
|
@@ -4225,7 +4237,7 @@ var Store = class {
|
|
|
4225
4237
|
}
|
|
4226
4238
|
root;
|
|
4227
4239
|
get featuresDir() {
|
|
4228
|
-
return
|
|
4240
|
+
return path4.join(this.root, ".flowriki", "features");
|
|
4229
4241
|
}
|
|
4230
4242
|
/** Every path that comes from a request goes through this. A slug is a
|
|
4231
4243
|
* single path segment and nothing else — no traversal, no absolute paths. */
|
|
@@ -4238,13 +4250,13 @@ var Store = class {
|
|
|
4238
4250
|
const out = [];
|
|
4239
4251
|
for (const entry of fs4.readdirSync(this.featuresDir, { withFileTypes: true })) {
|
|
4240
4252
|
if (!entry.isDirectory()) continue;
|
|
4241
|
-
const file =
|
|
4253
|
+
const file = path4.join(this.featuresDir, entry.name, "feature.json");
|
|
4242
4254
|
if (!fs4.existsSync(file)) continue;
|
|
4243
4255
|
try {
|
|
4244
4256
|
out.push(FeatureSchema.parse(JSON.parse(fs4.readFileSync(file, "utf8"))));
|
|
4245
4257
|
} catch (err) {
|
|
4246
4258
|
this.featureProblems.push({
|
|
4247
|
-
path:
|
|
4259
|
+
path: path4.relative(this.root, file),
|
|
4248
4260
|
error: String(err instanceof Error ? err.message : err).split("\n")[0].trim(),
|
|
4249
4261
|
recoverable: false
|
|
4250
4262
|
});
|
|
@@ -4255,7 +4267,7 @@ var Store = class {
|
|
|
4255
4267
|
featureProblems = [];
|
|
4256
4268
|
createFeature(name, description = "") {
|
|
4257
4269
|
const slug = this.assertSlug(slugify(name));
|
|
4258
|
-
const dir =
|
|
4270
|
+
const dir = path4.join(this.featuresDir, slug);
|
|
4259
4271
|
if (fs4.existsSync(dir)) throw new Error(`a feature named "${name}" already exists`);
|
|
4260
4272
|
fs4.mkdirSync(dir, { recursive: true });
|
|
4261
4273
|
const doc = {
|
|
@@ -4266,11 +4278,11 @@ var Store = class {
|
|
|
4266
4278
|
description: description.trim(),
|
|
4267
4279
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4268
4280
|
};
|
|
4269
|
-
fs4.writeFileSync(
|
|
4281
|
+
fs4.writeFileSync(path4.join(dir, "feature.json"), JSON.stringify(doc, null, 2) + "\n");
|
|
4270
4282
|
return doc;
|
|
4271
4283
|
}
|
|
4272
4284
|
deleteFeature(slug) {
|
|
4273
|
-
fs4.rmSync(
|
|
4285
|
+
fs4.rmSync(path4.join(this.featuresDir, this.assertSlug(slug)), { recursive: true, force: true });
|
|
4274
4286
|
}
|
|
4275
4287
|
/** Every flow that could be read.
|
|
4276
4288
|
*
|
|
@@ -4284,16 +4296,16 @@ var Store = class {
|
|
|
4284
4296
|
const out = [];
|
|
4285
4297
|
this.problemsFound = [];
|
|
4286
4298
|
for (const slug of features) {
|
|
4287
|
-
const dir =
|
|
4299
|
+
const dir = path4.join(this.featuresDir, slug);
|
|
4288
4300
|
if (!fs4.existsSync(dir)) continue;
|
|
4289
4301
|
for (const file of fs4.readdirSync(dir)) {
|
|
4290
4302
|
if (!file.endsWith(".flow.json")) continue;
|
|
4291
|
-
const full =
|
|
4303
|
+
const full = path4.join(dir, file);
|
|
4292
4304
|
try {
|
|
4293
4305
|
out.push(parseFlowDocument(JSON.parse(fs4.readFileSync(full, "utf8"))));
|
|
4294
4306
|
} catch (err) {
|
|
4295
4307
|
this.problemsFound.push({
|
|
4296
|
-
path:
|
|
4308
|
+
path: path4.relative(this.root, full),
|
|
4297
4309
|
error: String(err instanceof Error ? err.message : err).split("\n")[0].trim(),
|
|
4298
4310
|
recoverable: fs4.existsSync(this.recoveryPathFor(full))
|
|
4299
4311
|
});
|
|
@@ -4318,12 +4330,12 @@ var Store = class {
|
|
|
4318
4330
|
* Outside `features/`, because that directory is the product and is
|
|
4319
4331
|
* committed; a recovery copy is machine-local noise. */
|
|
4320
4332
|
recoveryPathFor(file) {
|
|
4321
|
-
return
|
|
4333
|
+
return path4.join(this.root, ".flowriki", ".recovery", path4.basename(file) + ".bak");
|
|
4322
4334
|
}
|
|
4323
4335
|
/** Restore a flow file from its recovery copy. Returns false when there is
|
|
4324
4336
|
* none, which is the honest answer rather than an invented document. */
|
|
4325
4337
|
recoverFlowFile(relativePath) {
|
|
4326
|
-
const file =
|
|
4338
|
+
const file = path4.join(this.root, relativePath);
|
|
4327
4339
|
const backup = this.recoveryPathFor(file);
|
|
4328
4340
|
if (!fs4.existsSync(backup)) return false;
|
|
4329
4341
|
fs4.copyFileSync(backup, file);
|
|
@@ -4343,9 +4355,9 @@ var Store = class {
|
|
|
4343
4355
|
saveFlow(input, opts = {}) {
|
|
4344
4356
|
const doc = parseFlowDocument(input);
|
|
4345
4357
|
const featureSlug = this.assertSlug(doc.featureId.replace(/^f_/, ""));
|
|
4346
|
-
const dir =
|
|
4358
|
+
const dir = path4.join(this.featuresDir, featureSlug);
|
|
4347
4359
|
fs4.mkdirSync(dir, { recursive: true });
|
|
4348
|
-
const file =
|
|
4360
|
+
const file = path4.join(dir, `${this.assertSlug(doc.slug)}.flow.json`);
|
|
4349
4361
|
const destination = this.readFlowFile(file);
|
|
4350
4362
|
if (fs4.existsSync(file) && (!destination || destination.id !== doc.id)) {
|
|
4351
4363
|
throw new FlowConflict("the destination contains another flow or an unreadable document \u2014 choose another name or recover it first", destination?.revision ?? 0);
|
|
@@ -4364,16 +4376,16 @@ var Store = class {
|
|
|
4364
4376
|
}
|
|
4365
4377
|
}
|
|
4366
4378
|
doc.revision = (current?.revision ?? doc.revision ?? 0) + 1;
|
|
4367
|
-
const previousFile = current ?
|
|
4379
|
+
const previousFile = current ? path4.join(this.root, this.relPath(current)) : file;
|
|
4368
4380
|
if (fs4.existsSync(previousFile)) {
|
|
4369
4381
|
const backup = this.recoveryPathFor(previousFile);
|
|
4370
|
-
fs4.mkdirSync(
|
|
4382
|
+
fs4.mkdirSync(path4.dirname(backup), { recursive: true });
|
|
4371
4383
|
fs4.copyFileSync(previousFile, backup);
|
|
4372
4384
|
this.ensureRecoveryIgnored();
|
|
4373
4385
|
}
|
|
4374
4386
|
writeFileAtomic(file, JSON.stringify(doc, null, 2) + "\n");
|
|
4375
4387
|
if (previousFile !== file) fs4.rmSync(previousFile);
|
|
4376
|
-
return
|
|
4388
|
+
return path4.relative(this.root, file);
|
|
4377
4389
|
}
|
|
4378
4390
|
/** Read one flow file, or null when it is missing or unreadable. */
|
|
4379
4391
|
readFlowFile(file) {
|
|
@@ -4415,10 +4427,10 @@ var Store = class {
|
|
|
4415
4427
|
deleteFlowDocument(doc) {
|
|
4416
4428
|
const featureSlug = this.assertSlug(doc.featureId.replace(/^f_/, ""));
|
|
4417
4429
|
this.assertSlug(doc.slug);
|
|
4418
|
-
fs4.rmSync(
|
|
4430
|
+
fs4.rmSync(path4.join(this.featuresDir, featureSlug, `${doc.slug}.flow.json`), { force: true });
|
|
4419
4431
|
}
|
|
4420
4432
|
relPath(doc) {
|
|
4421
|
-
return
|
|
4433
|
+
return path4.join(".flowriki", "features", doc.featureId.replace(/^f_/, ""), `${doc.slug}.flow.json`);
|
|
4422
4434
|
}
|
|
4423
4435
|
/** The environment a flow actually executes in.
|
|
4424
4436
|
*
|
|
@@ -4444,7 +4456,7 @@ var Store = class {
|
|
|
4444
4456
|
* per flow, and it travels with the repo like everything else in
|
|
4445
4457
|
* `.flowriki/`. */
|
|
4446
4458
|
get configPath() {
|
|
4447
|
-
return
|
|
4459
|
+
return path4.join(this.root, ".flowriki", "config.json");
|
|
4448
4460
|
}
|
|
4449
4461
|
readConfig() {
|
|
4450
4462
|
try {
|
|
@@ -4477,7 +4489,7 @@ var Store = class {
|
|
|
4477
4489
|
artifacts: ArtifactPolicySchema.parse(input.artifacts ?? existing.artifacts),
|
|
4478
4490
|
flakinessRepeat: clampRepeat(input.flakinessRepeat ?? existing.flakinessRepeat)
|
|
4479
4491
|
};
|
|
4480
|
-
fs4.mkdirSync(
|
|
4492
|
+
fs4.mkdirSync(path4.dirname(this.configPath), { recursive: true });
|
|
4481
4493
|
fs4.writeFileSync(this.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
4482
4494
|
return config;
|
|
4483
4495
|
}
|
|
@@ -4502,7 +4514,7 @@ var Store = class {
|
|
|
4502
4514
|
return resolveStartUrl(this.baseUrlFor(flow), flow.startPath);
|
|
4503
4515
|
}
|
|
4504
4516
|
get secretsPath() {
|
|
4505
|
-
return
|
|
4517
|
+
return path4.join(this.root, ".flowriki", "secrets.local.json");
|
|
4506
4518
|
}
|
|
4507
4519
|
readSecrets() {
|
|
4508
4520
|
try {
|
|
@@ -4552,7 +4564,7 @@ var Store = class {
|
|
|
4552
4564
|
changed = true;
|
|
4553
4565
|
}
|
|
4554
4566
|
if (changed) {
|
|
4555
|
-
fs4.mkdirSync(
|
|
4567
|
+
fs4.mkdirSync(path4.dirname(this.secretsPath), { recursive: true });
|
|
4556
4568
|
fs4.writeFileSync(this.secretsPath, JSON.stringify(secrets, null, 2) + "\n", { mode: 384 });
|
|
4557
4569
|
this.ensureSecretsIgnored();
|
|
4558
4570
|
}
|
|
@@ -4565,14 +4577,14 @@ var Store = class {
|
|
|
4565
4577
|
* file. Committed alongside the flows, because a test that needs a 2KB
|
|
4566
4578
|
* sample CSV should not need a side-channel to share it. */
|
|
4567
4579
|
get filesDir() {
|
|
4568
|
-
return
|
|
4580
|
+
return path4.join(this.root, ".flowriki", "files");
|
|
4569
4581
|
}
|
|
4570
4582
|
/** Resolve an upload step's file name to a path, or undefined when it is
|
|
4571
4583
|
* not on this machine. */
|
|
4572
4584
|
resolveFile(name) {
|
|
4573
4585
|
const first = name;
|
|
4574
4586
|
if (!first || first.includes("/") || first.includes("\\") || first.includes("..")) return void 0;
|
|
4575
|
-
const file =
|
|
4587
|
+
const file = path4.join(this.filesDir, first);
|
|
4576
4588
|
return fs4.existsSync(file) ? file : void 0;
|
|
4577
4589
|
}
|
|
4578
4590
|
/** The secret references a flow needs that this machine does not hold.
|
|
@@ -4600,7 +4612,7 @@ var Store = class {
|
|
|
4600
4612
|
if (!/^[a-z0-9][a-z0-9_-]*$/.test(ref)) throw new Error(`invalid secret name: ${ref}`);
|
|
4601
4613
|
const secrets = this.readSecrets();
|
|
4602
4614
|
secrets[ref] = value;
|
|
4603
|
-
fs4.mkdirSync(
|
|
4615
|
+
fs4.mkdirSync(path4.dirname(this.secretsPath), { recursive: true });
|
|
4604
4616
|
fs4.writeFileSync(this.secretsPath, JSON.stringify(secrets, null, 2) + "\n", { mode: 384 });
|
|
4605
4617
|
this.ensureSecretsIgnored();
|
|
4606
4618
|
}
|
|
@@ -4641,7 +4653,7 @@ var Store = class {
|
|
|
4641
4653
|
}
|
|
4642
4654
|
}
|
|
4643
4655
|
if (healed.length) {
|
|
4644
|
-
fs4.mkdirSync(
|
|
4656
|
+
fs4.mkdirSync(path4.dirname(this.secretsPath), { recursive: true });
|
|
4645
4657
|
fs4.writeFileSync(this.secretsPath, JSON.stringify(secrets, null, 2) + "\n", { mode: 384 });
|
|
4646
4658
|
this.ensureSecretsIgnored();
|
|
4647
4659
|
}
|
|
@@ -4658,10 +4670,10 @@ var Store = class {
|
|
|
4658
4670
|
}
|
|
4659
4671
|
/** Add one entry to .flowriki/.gitignore if it is not already there. */
|
|
4660
4672
|
ensureIgnored(line, why) {
|
|
4661
|
-
const ignore =
|
|
4673
|
+
const ignore = path4.join(this.root, ".flowriki", ".gitignore");
|
|
4662
4674
|
const existing = fs4.existsSync(ignore) ? fs4.readFileSync(ignore, "utf8") : "";
|
|
4663
4675
|
if (existing.split("\n").includes(line)) return;
|
|
4664
|
-
fs4.mkdirSync(
|
|
4676
|
+
fs4.mkdirSync(path4.dirname(ignore), { recursive: true });
|
|
4665
4677
|
fs4.writeFileSync(
|
|
4666
4678
|
ignore,
|
|
4667
4679
|
`${existing}${existing && !existing.endsWith("\n") ? "\n" : ""}# ${why}
|
|
@@ -5650,13 +5662,13 @@ var EventJournal = class {
|
|
|
5650
5662
|
return this.state ? this.state.size() : this.events.length;
|
|
5651
5663
|
}
|
|
5652
5664
|
};
|
|
5653
|
-
var { DatabaseSync } =
|
|
5665
|
+
var { DatabaseSync } = createRequire2(import.meta.url)("node:sqlite");
|
|
5654
5666
|
var AgentState = class {
|
|
5655
5667
|
constructor(file, deviceId, commandLimit = 1e5) {
|
|
5656
5668
|
this.commandLimit = commandLimit;
|
|
5657
5669
|
if (!file || file === ":memory:") throw new Error("a persistent agent state file is required");
|
|
5658
5670
|
if (!Number.isInteger(commandLimit) || commandLimit < 1) throw new Error("invalid command capacity");
|
|
5659
|
-
fs5.mkdirSync(
|
|
5671
|
+
fs5.mkdirSync(path5.dirname(file), { recursive: true, mode: 448 });
|
|
5660
5672
|
const fd = fs5.openSync(file, "a", 384);
|
|
5661
5673
|
fs5.closeSync(fd);
|
|
5662
5674
|
fs5.chmodSync(file, 384);
|
|
@@ -6061,16 +6073,39 @@ var AgentLink = class {
|
|
|
6061
6073
|
}
|
|
6062
6074
|
}
|
|
6063
6075
|
};
|
|
6076
|
+
var HEARTBEAT_MS = 3e4;
|
|
6064
6077
|
function adapt(socket) {
|
|
6065
6078
|
let closed = false;
|
|
6066
6079
|
const closeHandlers = [];
|
|
6067
6080
|
const fire = () => {
|
|
6068
6081
|
if (closed) return;
|
|
6069
6082
|
closed = true;
|
|
6083
|
+
clearInterval(heartbeat);
|
|
6070
6084
|
for (const handler of closeHandlers) handler();
|
|
6071
6085
|
};
|
|
6072
6086
|
socket.on("close", fire);
|
|
6073
6087
|
socket.on("error", fire);
|
|
6088
|
+
let answered = true;
|
|
6089
|
+
socket.on("pong", () => {
|
|
6090
|
+
answered = true;
|
|
6091
|
+
});
|
|
6092
|
+
const heartbeat = setInterval(() => {
|
|
6093
|
+
if (!answered) {
|
|
6094
|
+
try {
|
|
6095
|
+
socket.terminate();
|
|
6096
|
+
} catch {
|
|
6097
|
+
}
|
|
6098
|
+
fire();
|
|
6099
|
+
return;
|
|
6100
|
+
}
|
|
6101
|
+
answered = false;
|
|
6102
|
+
try {
|
|
6103
|
+
socket.ping();
|
|
6104
|
+
} catch {
|
|
6105
|
+
fire();
|
|
6106
|
+
}
|
|
6107
|
+
}, HEARTBEAT_MS);
|
|
6108
|
+
heartbeat.unref?.();
|
|
6074
6109
|
return {
|
|
6075
6110
|
send: (data) => {
|
|
6076
6111
|
if (socket.readyState !== WebSocket.OPEN) return;
|
|
@@ -6756,7 +6791,7 @@ function createAgentRuntime(options) {
|
|
|
6756
6791
|
|
|
6757
6792
|
// src/engine.ts
|
|
6758
6793
|
import fs9 from "fs";
|
|
6759
|
-
import
|
|
6794
|
+
import path7 from "path";
|
|
6760
6795
|
|
|
6761
6796
|
// src/credentials.ts
|
|
6762
6797
|
import crypto3 from "crypto";
|
|
@@ -6765,19 +6800,19 @@ import fs7 from "fs";
|
|
|
6765
6800
|
// src/paths.ts
|
|
6766
6801
|
import fs6 from "fs";
|
|
6767
6802
|
import os3 from "os";
|
|
6768
|
-
import
|
|
6803
|
+
import path6 from "path";
|
|
6769
6804
|
function dataDir(env = process.env) {
|
|
6770
6805
|
const override = env["FLOWRIKI_HOME"]?.trim();
|
|
6771
|
-
if (override) return
|
|
6806
|
+
if (override) return path6.resolve(override);
|
|
6772
6807
|
if (process.platform === "win32") {
|
|
6773
6808
|
const appData = env["APPDATA"]?.trim();
|
|
6774
|
-
return appData ?
|
|
6809
|
+
return appData ? path6.join(appData, "Flowriki") : path6.join(os3.homedir(), "AppData", "Roaming", "Flowriki");
|
|
6775
6810
|
}
|
|
6776
6811
|
if (process.platform === "darwin") {
|
|
6777
|
-
return
|
|
6812
|
+
return path6.join(os3.homedir(), "Library", "Application Support", "Flowriki");
|
|
6778
6813
|
}
|
|
6779
6814
|
const state = env["XDG_STATE_HOME"]?.trim();
|
|
6780
|
-
return state ?
|
|
6815
|
+
return state ? path6.join(state, "flowriki") : path6.join(os3.homedir(), ".local", "state", "flowriki");
|
|
6781
6816
|
}
|
|
6782
6817
|
function ensureDataDir(env = process.env) {
|
|
6783
6818
|
const dir = dataDir(env);
|
|
@@ -6790,9 +6825,9 @@ function ensureDataDir(env = process.env) {
|
|
|
6790
6825
|
}
|
|
6791
6826
|
return dir;
|
|
6792
6827
|
}
|
|
6793
|
-
var credentialsPath = (env = process.env) =>
|
|
6794
|
-
var lockPath = (env = process.env) =>
|
|
6795
|
-
var ledgerPath = (deviceId, env = process.env) =>
|
|
6828
|
+
var credentialsPath = (env = process.env) => path6.join(dataDir(env), "credentials.json");
|
|
6829
|
+
var lockPath = (env = process.env) => path6.join(dataDir(env), "agent.lock");
|
|
6830
|
+
var ledgerPath = (deviceId, env = process.env) => path6.join(dataDir(env), `ledger-${deviceId}.sqlite`);
|
|
6796
6831
|
|
|
6797
6832
|
// src/credentials.ts
|
|
6798
6833
|
function readFile(env = process.env) {
|
|
@@ -6946,7 +6981,7 @@ function openBrowser(url, env = process.env) {
|
|
|
6946
6981
|
}
|
|
6947
6982
|
|
|
6948
6983
|
// src/engine.ts
|
|
6949
|
-
var AGENT_VERSION = "0.1.0-beta.
|
|
6984
|
+
var AGENT_VERSION = "0.1.0-beta.5";
|
|
6950
6985
|
async function connect(options = {}) {
|
|
6951
6986
|
let service;
|
|
6952
6987
|
try {
|
|
@@ -7029,7 +7064,7 @@ function resolveCheckouts(dirs) {
|
|
|
7029
7064
|
const projects = [];
|
|
7030
7065
|
const skipped = [];
|
|
7031
7066
|
for (const dir of dirs) {
|
|
7032
|
-
const root =
|
|
7067
|
+
const root = path7.resolve(dir);
|
|
7033
7068
|
if (!fs9.existsSync(root)) {
|
|
7034
7069
|
skipped.push({ root, why: "no such folder" });
|
|
7035
7070
|
continue;
|
|
@@ -7070,6 +7105,13 @@ async function start(options = {}) {
|
|
|
7070
7105
|
message: `this installation is not connected to ${service} yet`
|
|
7071
7106
|
};
|
|
7072
7107
|
}
|
|
7108
|
+
if (!browsersReady()) {
|
|
7109
|
+
options.onStatus?.("preparing", "downloading the browser Flowriki records with \u2014 this happens once");
|
|
7110
|
+
const prepared = await prepareBrowsers();
|
|
7111
|
+
if (!prepared.ok) {
|
|
7112
|
+
return { ok: false, reason: "refused", message: `this machine cannot record yet \u2014 ${prepared.message}` };
|
|
7113
|
+
}
|
|
7114
|
+
}
|
|
7073
7115
|
const lock = takeLock();
|
|
7074
7116
|
if (!lock.ok) {
|
|
7075
7117
|
return {
|
|
@@ -7116,6 +7158,36 @@ async function start(options = {}) {
|
|
|
7116
7158
|
}
|
|
7117
7159
|
};
|
|
7118
7160
|
}
|
|
7161
|
+
async function prepareBrowsers() {
|
|
7162
|
+
if (browsersReady()) {
|
|
7163
|
+
return { ok: true, already: true, message: "chromium is already installed" };
|
|
7164
|
+
}
|
|
7165
|
+
let cli;
|
|
7166
|
+
try {
|
|
7167
|
+
cli = createRequire3(import.meta.url).resolve("playwright/cli.js");
|
|
7168
|
+
} catch {
|
|
7169
|
+
return {
|
|
7170
|
+
ok: false,
|
|
7171
|
+
already: false,
|
|
7172
|
+
message: "playwright is not installed beside this agent \u2014 reinstall it"
|
|
7173
|
+
};
|
|
7174
|
+
}
|
|
7175
|
+
const run = spawnSync(process.execPath, [cli, "install", "chromium"], { stdio: "inherit" });
|
|
7176
|
+
if (run.status !== 0) {
|
|
7177
|
+
return {
|
|
7178
|
+
ok: false,
|
|
7179
|
+
already: false,
|
|
7180
|
+
message: `could not install chromium (exit ${run.status ?? "unknown"}) \u2014 try \`npx playwright@${playwrightVersion() ?? "latest"} install chromium\` yourself`
|
|
7181
|
+
};
|
|
7182
|
+
}
|
|
7183
|
+
return { ok: browsersReady(), already: false, message: "chromium installed" };
|
|
7184
|
+
}
|
|
7185
|
+
function browsersReady() {
|
|
7186
|
+
return inspectPlaywright().chromiumInstalled === true;
|
|
7187
|
+
}
|
|
7188
|
+
function playwrightVersion() {
|
|
7189
|
+
return inspectPlaywright().version;
|
|
7190
|
+
}
|
|
7119
7191
|
function status(serviceArg) {
|
|
7120
7192
|
const service = resolveService(serviceArg);
|
|
7121
7193
|
const connection = connectionFor(service);
|
|
@@ -7177,7 +7249,7 @@ async function doctor(serviceArg) {
|
|
|
7177
7249
|
}
|
|
7178
7250
|
function inspectPlaywright() {
|
|
7179
7251
|
try {
|
|
7180
|
-
const browsersPath = process.env["PLAYWRIGHT_BROWSERS_PATH"] ?? (process.platform === "win32" ?
|
|
7252
|
+
const browsersPath = process.env["PLAYWRIGHT_BROWSERS_PATH"] ?? (process.platform === "win32" ? path7.join(os5.homedir(), "AppData", "Local", "ms-playwright") : process.platform === "darwin" ? path7.join(os5.homedir(), "Library", "Caches", "ms-playwright") : path7.join(os5.homedir(), ".cache", "ms-playwright"));
|
|
7181
7253
|
const chromiumInstalled = fs9.existsSync(browsersPath) ? fs9.readdirSync(browsersPath).some((d) => d.startsWith("chromium")) : false;
|
|
7182
7254
|
return { version: null, browsersPath, chromiumInstalled };
|
|
7183
7255
|
} catch {
|
|
@@ -7195,6 +7267,8 @@ export {
|
|
|
7195
7267
|
connect,
|
|
7196
7268
|
resolveCheckouts,
|
|
7197
7269
|
start,
|
|
7270
|
+
prepareBrowsers,
|
|
7271
|
+
browsersReady,
|
|
7198
7272
|
status,
|
|
7199
7273
|
doctor,
|
|
7200
7274
|
disconnect
|
package/dist/cli.js
CHANGED
|
@@ -4,10 +4,11 @@ import {
|
|
|
4
4
|
connect,
|
|
5
5
|
disconnect,
|
|
6
6
|
doctor,
|
|
7
|
+
prepareBrowsers,
|
|
7
8
|
resolveCheckouts,
|
|
8
9
|
start,
|
|
9
10
|
status
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QJOMJVCO.js";
|
|
11
12
|
|
|
12
13
|
// src/cli.ts
|
|
13
14
|
import { parseArgs } from "util";
|
|
@@ -27,6 +28,7 @@ ${bold("USAGE")}
|
|
|
27
28
|
flowriki-agent start run the agent (stays in the foreground)
|
|
28
29
|
flowriki-agent status is it connected, and what is prepared
|
|
29
30
|
flowriki-agent doctor diagnose setup problems
|
|
31
|
+
flowriki-agent prepare download the browser recording needs
|
|
30
32
|
flowriki-agent disconnect forget this computer's credential
|
|
31
33
|
|
|
32
34
|
${bold("OPTIONS")}
|
|
@@ -129,8 +131,7 @@ Run \`flowriki-agent --help\`.`);
|
|
|
129
131
|
console.log(`${bold("Flowriki agent")} ${dim(AGENT_VERSION)}`);
|
|
130
132
|
console.log(dim(` connected as ${started.connection.machineName}`));
|
|
131
133
|
if (started.projects.length === 0) {
|
|
132
|
-
console.log(
|
|
133
|
-
console.log(dim(" Add one: flowriki-agent start --project /path/to/a/checkout"));
|
|
134
|
+
console.log(dim(" ready \u2014 this machine records and runs whatever the dashboard asks for"));
|
|
134
135
|
}
|
|
135
136
|
for (const project of started.projects) {
|
|
136
137
|
console.log(dim(` project ${project.name} (${project.root})`));
|
|
@@ -150,6 +151,11 @@ Run \`flowriki-agent --help\`.`);
|
|
|
150
151
|
return await new Promise(() => {
|
|
151
152
|
});
|
|
152
153
|
}
|
|
154
|
+
case "prepare": {
|
|
155
|
+
const result = await prepareBrowsers();
|
|
156
|
+
console.log(result.ok ? green(result.message) : red(result.message));
|
|
157
|
+
return result.ok ? 0 : 1;
|
|
158
|
+
}
|
|
153
159
|
case "status": {
|
|
154
160
|
const state = status(service);
|
|
155
161
|
if (values.json) {
|
package/dist/engine.js
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
AGENT_VERSION,
|
|
4
|
+
browsersReady,
|
|
4
5
|
connect,
|
|
5
6
|
disconnect,
|
|
6
7
|
doctor,
|
|
8
|
+
prepareBrowsers,
|
|
7
9
|
resolveCheckouts,
|
|
8
10
|
start,
|
|
9
11
|
status
|
|
10
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QJOMJVCO.js";
|
|
11
13
|
export {
|
|
12
14
|
AGENT_VERSION,
|
|
15
|
+
browsersReady,
|
|
13
16
|
connect,
|
|
14
17
|
disconnect,
|
|
15
18
|
doctor,
|
|
19
|
+
prepareBrowsers,
|
|
16
20
|
resolveCheckouts,
|
|
17
21
|
start,
|
|
18
22
|
status
|
package/package.json
CHANGED