@vibro/bro 0.0.1-alpha.1 → 0.0.1-alpha.3

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/README.md CHANGED
@@ -30,12 +30,35 @@ export default defineConfig({
30
30
  });
31
31
  ```
32
32
 
33
- Run some CLI commands:
33
+ Run as **CLI commands:**
34
34
  ```bash
35
35
  pnpm vibro -h
36
- pnpm pnpm vibro --screenshot --to-file ./tmp/screenshot.png
36
+ pnpm vibro --screenshot --to-file ./tmp/screenshot.png
37
37
  ```
38
38
 
39
+ Or directly:
40
+ ```bash
41
+ node_modules/.bin/vibro --mcp
42
+ ```
43
+
44
+ Use **MCP** server mode:
45
+ ```json
46
+ {
47
+ "mcpServers": {
48
+ "vibro": {
49
+ "command": "vibro",
50
+ "args": ["--mcp"]
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+
57
+ Available MCP tools:
58
+ - `vibro_list`
59
+ - `vibro_request`
60
+ - `vibro_screenshot`
61
+
39
62
 
40
63
  ## License
41
64
 
@@ -47,6 +47,7 @@ type VibroBridgeRequestHandler = (request: VibroBridgeRequest) => VibroBridgeRes
47
47
  declare global {
48
48
  interface Window {
49
49
  __vibroRequestHandler?: VibroBridgeRequestHandler;
50
+ __vibroVerboseClient?: boolean;
50
51
  }
51
52
  }
52
53
 
@@ -1 +1 @@
1
- var _="__vibro__:request",b="__vibro__:response",f="__vibro__:tab-register",T="__vibro__:tab-heartbeat",w="__vibro__:tab-focus",y="__vibro__:list-request",h="__vibro__:list-response";function v(e){return e!==null&&typeof e=="object"}var N=5e3,R="__vibroBridgeTabId";function k(){let e=window,r=e[R];if(typeof r=="string"&&r.length>0)return r;let t=x();return e[R]=t,t}var a=k(),i,S=false,I=false;function q(e){return e!==null&&typeof e=="object"}function M(e){return q(e)&&"ok"in e&&typeof e.ok=="boolean"&&("payload"in e||"error"in e)}function L(e){return e instanceof Error?e.message:String(e)}function O(e,r=.92){if(typeof e!="string")return r;let t=Number.parseFloat(e);return !Number.isFinite(t)||t<=0?r:t>1?1:t}function P(e){if(typeof e=="string"){let r=e.toLowerCase();if(r==="jpeg"||r==="jpg")return "jpeg"}return "png"}function x(){let e=new Uint8Array(4);return crypto.getRandomValues(e),Array.from(e).map(r=>r.toString(16).padStart(2,"0")).join("")}function D(){if(I)return;let e=window.__vibroRequestHandler;window.__vibroRequestHandler=async r=>r.path==="/screenshot"?j(r):typeof e=="function"?e(r):{ok:false,error:"No vibro request handler found on window.__vibroRequestHandler"},I=true;}function H(e){return e.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&e.videoWidth>0&&e.videoHeight>0?Promise.resolve():new Promise((r,t)=>{let n=setTimeout(()=>t(new Error("Timed out waiting for camera frame")),5e3),s=()=>{clearTimeout(n),e.removeEventListener("loadedmetadata",d),e.removeEventListener("error",o);},d=()=>{s(),r();},o=c=>{s(),t(new Error(`Video error: ${String(c)}`));};e.addEventListener("loadedmetadata",d,{once:true}),e.addEventListener("error",o,{once:true});})}function U(e){e!==void 0&&e.getTracks().forEach(r=>{r.stop();});}async function F(e){if(!navigator.mediaDevices||!("getDisplayMedia"in navigator.mediaDevices))throw new Error("Screen capture is not supported in this browser");let r,t=null;try{let n={audio:!1,preferCurrentTab:!0,video:{frameRate:{ideal:30}}};r=await navigator.mediaDevices.getDisplayMedia({...n,selfBrowserSurface:"include",surfaceSwitching:"exclude"}),t=document.createElement("video"),t.srcObject=r,t.muted=!0,t.autoplay=!0,t.playsInline=!0,await t.play().catch(()=>{}),await H(t);let s=t.videoWidth,d=t.videoHeight;if(s<=0||d<=0)throw new Error("Failed to read video frame size for screenshot");let o=document.createElement("canvas");o.width=s,o.height=d;let c=o.getContext("2d");if(c===null)throw new Error("Canvas context is not available");c.drawImage(t,0,0,s,d);let g=e.format==="jpeg"?"image/jpeg":"image/png";return {dataUrl:e.format==="png"?o.toDataURL(g):o.toDataURL(g,e.quality),width:s,height:d,format:e.format,quality:e.quality}}finally{t!==null&&t.remove(),U(r);}}async function j(e){let r=P(e.query.format??e.query.quality),t=O(e.query.quality,r==="png"?.92:.75);try{let n=await F({format:r,quality:t});return {ok:!0,payload:{dataUrl:n.dataUrl,width:n.width,height:n.height,format:n.format,quality:n.quality}}}catch(n){return {ok:false,error:L(n)}}}function C(){return `${location.protocol==="https:"?"wss:":"ws:"}//${location.host}/@vite/client`}function u(){let e=Date.now();return {title:document.title||"",pathname:location.pathname,href:location.href,focused:document.visibilityState==="visible",wsUrl:C(),userAgent:navigator.userAgent,registeredAt:e,lastSeenAt:e}}function W(e){return v(e)&&typeof e.requestId=="string"&&e.requestId.length>0}function l(e){import.meta.hot&&import.meta.hot.send(b,e);}function E(e,r){if(!import.meta.hot)return;let t=u();if(e===f){import.meta.hot.send(e,{tabId:a,metadata:r});return}import.meta.hot.send(e,{tabId:a,metadata:{...t,focused:r.focused,lastSeenAt:Date.now()}});}function z(e){if(!W(e)||!import.meta.hot)return;let r=u(),t={requestId:e.requestId,tabId:a,metadata:{...r,lastSeenAt:Date.now()},state:"open"};import.meta.hot.send(h,t);}function Q(e){import.meta.hot&&z(e);}function m(){import.meta.hot&&E(w,u());}function $(e){if(D(),e.targetTabId&&e.targetTabId!==a)return;let r=window.__vibroRequestHandler;if(typeof r!="function"){l({id:e.id,sourceTabId:a,ok:false,error:"No Srv request handler found on window.__vibroRequestHandler"});return}(async()=>{try{let t=await r(e);if(M(t)){l({id:e.id,sourceTabId:a,ok:t.ok,payload:t.payload,error:t.error});return}l({id:e.id,sourceTabId:a,ok:!0,payload:t});}catch(t){l({id:e.id,sourceTabId:a,ok:false,error:L(t)});}})();}function G(){E(f,u());}function V(){E(T,u());}function p(e=0){if(!S){if(import.meta.hot){console.log("[vibro] initialized"),S=true,G(),V(),i===void 0&&(i=setInterval(V,N)),import.meta.hot.on(_,$),import.meta.hot.on(y,Q),document.addEventListener("visibilitychange",m),window.addEventListener("focus",m),window.addEventListener("blur",m),window.addEventListener("beforeunload",()=>{i!==void 0&&(clearInterval(i),i=void 0);}),import.meta.hot.on("vite:beforeFullReload",()=>{i!==void 0&&(clearInterval(i),i=void 0);});return}if(e>=20){console.warn("[vibro] HMR is not available, bridge is disabled");return}setTimeout(()=>{p(e+1);},50);}}document.readyState==="loading"?window.addEventListener("DOMContentLoaded",()=>{p();},{once:true}):p();
1
+ var _="__vibro__:request",b="__vibro__:response",f="__vibro__:tab-register",T="__vibro__:tab-heartbeat",w="__vibro__:tab-focus",y="__vibro__:list-request",h="__vibro__:list-response";function v(e){return e!==null&&typeof e=="object"}var k=5e3,R="__vibroBridgeTabId",S=window.__vibroVerboseClient===true;function q(){let e=window,r=e[R];if(typeof r=="string"&&r.length>0)return r;let t=D();return e[R]=t,t}var a=q(),i,I=false,V=false;function M(e){return e!==null&&typeof e=="object"}function O(e){return M(e)&&"ok"in e&&typeof e.ok=="boolean"&&("payload"in e||"error"in e)}function A(e){return e instanceof Error?e.message:String(e)}function P(e,r=.92){if(typeof e!="string")return r;let t=Number.parseFloat(e);return !Number.isFinite(t)||t<=0?r:t>1?1:t}function x(e){if(typeof e=="string"){let r=e.toLowerCase();if(r==="jpeg"||r==="jpg")return "jpeg"}return "png"}function D(){let e=new Uint8Array(4);return crypto.getRandomValues(e),Array.from(e).map(r=>r.toString(16).padStart(2,"0")).join("")}function H(){if(V)return;let e=window.__vibroRequestHandler;window.__vibroRequestHandler=async r=>r.path==="/screenshot"?j(r):typeof e=="function"?e(r):{ok:false,error:"No vibro request handler found on window.__vibroRequestHandler"},V=true;}function U(e){return e.readyState>=HTMLMediaElement.HAVE_CURRENT_DATA&&e.videoWidth>0&&e.videoHeight>0?Promise.resolve():new Promise((r,t)=>{let n=setTimeout(()=>t(new Error("Timed out waiting for camera frame")),1e4),s=()=>{clearTimeout(n),e.removeEventListener("loadedmetadata",d),e.removeEventListener("error",o);},d=()=>{s(),r();},o=c=>{s(),t(new Error(`Video error: ${String(c)}`));};e.addEventListener("loadedmetadata",d,{once:true}),e.addEventListener("error",o,{once:true});})}function F(e){e!==void 0&&e.getTracks().forEach(r=>{r.stop();});}async function C(e){if(!navigator.mediaDevices||!("getDisplayMedia"in navigator.mediaDevices))throw new Error("Screen capture is not supported in this browser");let r,t=null;try{let n={audio:!1,preferCurrentTab:!0,video:{frameRate:{ideal:30}}};r=await navigator.mediaDevices.getDisplayMedia({...n,selfBrowserSurface:"include",surfaceSwitching:"exclude"}),t=document.createElement("video"),t.srcObject=r,t.muted=!0,t.autoplay=!0,t.playsInline=!0,await t.play().catch(()=>{}),await U(t);let s=t.videoWidth,d=t.videoHeight;if(s<=0||d<=0)throw new Error("Failed to read video frame size for screenshot");let o=document.createElement("canvas");o.width=s,o.height=d;let c=o.getContext("2d");if(c===null)throw new Error("Canvas context is not available");c.drawImage(t,0,0,s,d);let g=e.format==="jpeg"?"image/jpeg":"image/png";return {dataUrl:e.format==="png"?o.toDataURL(g):o.toDataURL(g,e.quality),width:s,height:d,format:e.format,quality:e.quality}}finally{t!==null&&t.remove(),F(r);}}async function j(e){let r=x(e.query.format??e.query.quality),t=P(e.query.quality,r==="png"?.92:.75);try{let n=await C({format:r,quality:t});return {ok:!0,payload:{dataUrl:n.dataUrl,width:n.width,height:n.height,format:n.format,quality:n.quality}}}catch(n){return {ok:false,error:A(n)}}}function W(){return `${location.protocol==="https:"?"wss:":"ws:"}//${location.host}/@vite/client`}function u(){let e=Date.now();return {title:document.title||"",pathname:location.pathname,href:location.href,focused:document.visibilityState==="visible",wsUrl:W(),userAgent:navigator.userAgent,registeredAt:e,lastSeenAt:e}}function z(e){return v(e)&&typeof e.requestId=="string"&&e.requestId.length>0}function l(e){import.meta.hot&&import.meta.hot.send(b,e);}function E(e,r){if(!import.meta.hot)return;let t=u();if(e===f){import.meta.hot.send(e,{tabId:a,metadata:r});return}import.meta.hot.send(e,{tabId:a,metadata:{...t,focused:r.focused,lastSeenAt:Date.now()}});}function Q(e){if(!z(e)||!import.meta.hot)return;let r=u(),t={requestId:e.requestId,tabId:a,metadata:{...r,lastSeenAt:Date.now()},state:"open"};import.meta.hot.send(h,t);}function $(e){import.meta.hot&&Q(e);}function m(){import.meta.hot&&E(w,u());}function G(e){if(H(),e.targetTabId&&e.targetTabId!==a)return;let r=window.__vibroRequestHandler;if(typeof r!="function"){l({id:e.id,sourceTabId:a,ok:false,error:"No Srv request handler found on window.__vibroRequestHandler"});return}(async()=>{try{let t=await r(e);if(O(t)){l({id:e.id,sourceTabId:a,ok:t.ok,payload:t.payload,error:t.error});return}l({id:e.id,sourceTabId:a,ok:!0,payload:t});}catch(t){l({id:e.id,sourceTabId:a,ok:false,error:A(t)});}})();}function K(){E(f,u());}function L(){E(T,u());}function p(e=0){if(!I){if(import.meta.hot){S&&console.log("[vibro] initialized"),I=true,K(),L(),i===void 0&&(i=setInterval(L,k)),import.meta.hot.on(_,G),import.meta.hot.on(y,$),document.addEventListener("visibilitychange",m),window.addEventListener("focus",m),window.addEventListener("blur",m),window.addEventListener("beforeunload",()=>{i!==void 0&&(clearInterval(i),i=void 0);}),import.meta.hot.on("vite:beforeFullReload",()=>{i!==void 0&&(clearInterval(i),i=void 0);});return}if(e>=20){S&&console.warn("[vibro] HMR is not available, bridge is disabled");return}setTimeout(()=>{p(e+1);},50);}}document.readyState==="loading"?window.addEventListener("DOMContentLoaded",()=>{p();},{once:true}):p();
@@ -8,6 +8,8 @@ type VibroBridgePluginOptions = {
8
8
  registryFileName?: string;
9
9
  registryRetries?: number;
10
10
  registryRetryDelayMs?: number;
11
+ verboseServer?: boolean;
12
+ verboseClient?: boolean;
11
13
  };
12
14
  declare function vibroVitePlugin(options?: VibroBridgePluginOptions): Plugin;
13
15
 
@@ -60,6 +62,7 @@ type VibroBridgeRequestHandler = (request: VibroBridgeRequest) => VibroBridgeRes
60
62
  declare global {
61
63
  interface Window {
62
64
  __vibroRequestHandler?: VibroBridgeRequestHandler;
65
+ __vibroVerboseClient?: boolean;
63
66
  }
64
67
  }
65
68
 
@@ -1,11 +1,11 @@
1
- 'use strict';var crypto=require('crypto'),promises=require('fs/promises'),fs=require('fs'),path=require('path');var L="/__vibro__",at="__vibro__:request",ct="__vibro__:response",z="__vibro__:tab-register",G="__vibro__:tab-heartbeat",W="__vibro__:tab-focus",ut="__vibro__:list-request",dt="__vibro__:list-response",$="node_modules",Q="vibro-sessions.json";function T(t){return t!==null&&typeof t=="object"}var Y="dist",lt="vibro-cli.js",pt="vibro-client.js",C="vibro",xt=path.join($,".bin");function Ct(){let t=c=>`/@fs/${c.replace(/\\/g,"/")}`,e=__dirname;for(;;){let c=path.join(e,Y),d=path.join(c,lt),u=path.join(c,pt);if(fs.existsSync(d)&&fs.existsSync(u))return {packageRoot:e,cliSourceFilePath:d,clientScriptPathForVite:t(u)};let f=path.dirname(e);if(f===e)break;e=f;}let r=path.resolve(__dirname,"../.."),s=path.join(r,Y,pt);return {packageRoot:r,cliSourceFilePath:path.join(r,Y,lt),clientScriptPathForVite:t(s)}}var{cliSourceFilePath:jt,clientScriptPathForVite:Ut}=Ct(),Ht=4e3,qt=4e3,Jt=8e3,zt=3e4,mt=3e4,Gt=12e4,Wt=3,Qt=50;function P(t){return promises.stat(t).then(()=>true,()=>false)}function Yt(t){return promises.readFile(t,"utf8").then(e=>{try{return JSON.parse(e)}catch{return}},()=>{})}function Xt(t){return Array.isArray(t)?t.length>0:T(t)&&Object.keys(t).length>0}async function Kt(t){async function e(c){if(await Promise.all([P(path.join(c,".git")),P(path.join(c,"pnpm-workspace.yaml")),P(path.join(c,".pnpm-workspace-state-v1.json")),P(path.join(c,"lerna.json")),P(path.join(c,"nx.json")),P(path.join(c,"turbo.json"))]).then(l=>l.some(Boolean)))return true;let u=path.join(c,"package.json"),f=await Yt(u);return f!==void 0&&Xt(f.workspaces)}let r=path.resolve(t),s="";for(;;){await e(r)&&(s=r);let c=path.dirname(r);if(c===r)break;r=c;}return s.length>0?s:path.resolve(t)}function F(t,e){return typeof t=="number"&&Number.isFinite(t)?t:e}function k(t,e){return typeof t=="string"?t:e}function Zt(t){try{return process.kill(t,0),!0}catch(e){if(!(e instanceof Error))return false;let r=e.code;return !(r==="ESRCH"||r==="EINVAL")}}function Et(t){let e=k(t.config.server.host,"localhost");return e==="0.0.0.0"||e==="::"?"localhost":e}function _t(t){return t.config.server.https?"https":"http"}function te(t){let e=t.httpServer?.address();if(!(e==null||typeof e=="string"))return Number.isFinite(e.port)?e.port:void 0}function ee(t){let e=t.config.configFile;return typeof e=="string"?e:void 0}function Z(){return {updatedAt:Date.now(),instances:{}}}function U(t,e){let r=Date.now(),s={};for(let[c,d]of Object.entries(t)){if(d.pid<=0||!Number.isFinite(d.pid)||!Zt(d.pid)||r-d.lastSeenAt>e)continue;let u=String(d.pid);c===u&&(s[c]=d);}return s}function ne(t,e){if(!T(t))return Z();let r=t.updatedAt,s=t.instances;if(!T(s))return Z();let c={};for(let[d,u]of Object.entries(s)){if(!T(u))continue;let f=F(u.pid,NaN);if(!Number.isFinite(f)||String(Math.trunc(f))!==d)continue;let l=F(u.port,NaN);if(!Number.isFinite(l))continue;let m=F(u.startedAt,Date.now()),b=F(u.lastSeenAt,Date.now()),R=k(u.protocol,"http");if(R!=="http"&&R!=="https")continue;let E=k(u.host,"localhost"),y=k(u.cacheDir,"");if(y.length<=0)continue;let I=k(u.projectRoot,"");I.length<=0||(c[d]={pid:f,port:l,host:E,protocol:R,cacheDir:y,projectRoot:I,configFile:k(u.configFile,""),startedAt:m,lastSeenAt:b});}return {updatedAt:F(r,Date.now()),instances:U(c,e)}}function re(t,e){return path.join(t,$,e)}async function oe(t,e){try{let r=await promises.readFile(t,"utf8");return ne(JSON.parse(r),e)}catch{return Z()}}async function ie(t,e){await promises.mkdir(path.dirname(t),{recursive:true});let r=`${t}.tmp`;await promises.writeFile(r,JSON.stringify(e,null,2),"utf8"),await promises.rename(r,t);}function se(t){return new Promise(e=>{setTimeout(e,t);})}function x(t,e){console.error("[vibro]",t,e);}async function et(t,e,r,s,c,d){for(let u=0;u<=s;u+=1)try{let f=await oe(t,r),l=d(f);await ie(t,l);return}catch(f){if(u>=s)throw f;await se(c);}}function bt(t){return `'${t.replace(/'/g,`'"'"'`)}'`}function ht(t){return `"${t.replace(/"/g,'""')}"`}function St(t){return `'${t.replace(/'/g,"''")}'`}function D(t,e=C){return path.join(t,xt,e)}async function ae(t,e,r){let s=D(t),c=D(t,`${C}.CMD`),d=D(t,`${C}.ps1`),u=D(t,`${C}.cli.mjs`),f=bt(e),l=bt(r),m=ht(r),b=St(r),R=`#!/usr/bin/env sh
2
- exec node ${f} --sessions-file ${l} "$@"
3
- `,E=`@ECHO OFF
4
- node ${ht(e)} --sessions-file ${m} %*
5
- `,y=`$ErrorActionPreference = 'Stop'
6
- $cli = ${St(e)}
7
- $sessionFile = ${b}
1
+ 'use strict';var crypto=require('crypto'),promises=require('fs/promises'),fs=require('fs'),path=require('path'),vite=require('vite');var L="/__vibro__",de="__vibro__:request",fe="__vibro__:response",W="__vibro__:tab-register",z="__vibro__:tab-heartbeat",Y="__vibro__:tab-focus",le="__vibro__:list-request",ge="__vibro__:list-response",$="node_modules",K="vibro-sessions.json";function y(e){return e!==null&&typeof e=="object"}var x="dist",be="vibro-cli.js",he="vibro-client.js",j="vibro",Ge=path.join($,".bin");function We(){let e=c=>`/@fs/${c.replace(/\\/g,"/")}`,t=__dirname;for(;;){let c=path.join(t,x),d=path.join(c,be),u=path.join(c,he);if(fs.existsSync(d)&&fs.existsSync(u))return {packageRoot:t,cliSourceFilePath:d,clientScriptPathForVite:e(u)};let f=path.dirname(t);if(f===t)break;t=f;}let r=path.resolve(__dirname,"../.."),a=path.join(r,x,he);return {packageRoot:r,cliSourceFilePath:path.join(r,x,be),clientScriptPathForVite:e(a)}}var{packageRoot:Z,cliSourceFilePath:ze,clientScriptPathForVite:Ye}=We(),Se=path.join(Z,x);function Ke(e){let t=new Map;for(let r of e)t.set(r,true);return Array.from(t.keys())}function Re(e){try{return fs.realpathSync(e)}catch{return e}}var Qe=4e3,Xe=4e3,Ze=8e3,et=3e4,ye=3e4,tt=12e4,nt=3,rt=50;function P(e){return promises.stat(e).then(()=>true,()=>false)}function ot(e){return promises.readFile(e,"utf8").then(t=>{try{return JSON.parse(t)}catch{return}},()=>{})}function it(e){return Array.isArray(e)?e.length>0:y(e)&&Object.keys(e).length>0}async function st(e){async function t(c){if(await Promise.all([P(path.join(c,".git")),P(path.join(c,"pnpm-workspace.yaml")),P(path.join(c,".pnpm-workspace-state-v1.json")),P(path.join(c,"lerna.json")),P(path.join(c,"nx.json")),P(path.join(c,"turbo.json"))]).then(g=>g.some(Boolean)))return true;let u=path.join(c,"package.json"),f=await ot(u);return f!==void 0&&it(f.workspaces)}let r=path.resolve(e),a="";for(;;){await t(r)&&(a=r);let c=path.dirname(r);if(c===r)break;r=c;}return a.length>0?a:path.resolve(e)}function F(e,t){return typeof e=="number"&&Number.isFinite(e)?e:t}function B(e,t){return typeof e=="string"?e:t}function at(e){try{return process.kill(e,0),!0}catch(t){if(!(t instanceof Error))return false;let r=t.code;return !(r==="ESRCH"||r==="EINVAL")}}function Ve(e){let t=B(e.config.server.host,"localhost");return t==="0.0.0.0"||t==="::"?"localhost":t}function ve(e){return e.config.server.https?"https":"http"}function ct(e){let t=e.httpServer?.address();if(!(t==null||typeof t=="string"))return Number.isFinite(t.port)?t.port:void 0}function ut(e){let t=e.config.configFile;return typeof t=="string"?t:void 0}function ee(){return {updatedAt:Date.now(),instances:{}}}function H(e,t){let r=Date.now(),a={};for(let[c,d]of Object.entries(e)){if(d.pid<=0||!Number.isFinite(d.pid)||!at(d.pid)||r-d.lastSeenAt>t)continue;let u=String(d.pid);c===u&&(a[c]=d);}return a}function dt(e,t){if(!y(e))return ee();let r=e.updatedAt,a=e.instances;if(!y(a))return ee();let c={};for(let[d,u]of Object.entries(a)){if(!y(u))continue;let f=F(u.pid,NaN);if(!Number.isFinite(f)||String(Math.trunc(f))!==d)continue;let g=F(u.port,NaN);if(!Number.isFinite(g))continue;let b=F(u.startedAt,Date.now()),S=F(u.lastSeenAt,Date.now()),V=B(u.protocol,"http");if(V!=="http"&&V!=="https")continue;let R=B(u.host,"localhost"),T=B(u.cacheDir,"");if(T.length<=0)continue;let _=B(u.projectRoot,"");_.length<=0||(c[d]={pid:f,port:g,host:R,protocol:V,cacheDir:T,projectRoot:_,configFile:B(u.configFile,""),startedAt:b,lastSeenAt:S});}return {updatedAt:F(r,Date.now()),instances:H(c,t)}}function ft(e,t){return path.join(e,$,t)}async function lt(e,t){try{let r=await promises.readFile(e,"utf8");return dt(JSON.parse(r),t)}catch{return ee()}}async function gt(e,t){await promises.mkdir(path.dirname(e),{recursive:true});let r=`${e}.tmp`;await promises.writeFile(r,JSON.stringify(t,null,2),"utf8"),await promises.rename(r,e);}function pt(e){return new Promise(t=>{setTimeout(t,e);})}function mt(e,t,...r){e&&t(...r);}function C(e,t,r){mt(r,console.error,"[vibro]",e,t);}async function ne(e,t,r,a,c,d){for(let u=0;u<=a;u+=1)try{let f=await lt(e,r),g=d(f);await gt(e,g);return}catch(f){if(u>=a)throw f;await pt(c);}}function Te(e){return `'${e.replace(/'/g,`'"'"'`)}'`}function _e(e){return `"${e.replace(/"/g,'""')}"`}function Ee(e){return `'${e.replace(/'/g,"''")}'`}function D(e,t=j){return path.join(e,Ge,t)}async function bt(e,t,r){let a=D(e),c=D(e,`${j}.CMD`),d=D(e,`${j}.ps1`),u=D(e,`${j}.cli.mjs`),f=Te(t),g=Te(r),b=_e(r),S=Ee(r),V=`#!/usr/bin/env sh
2
+ exec node ${f} --sessions-file ${g} "$@"
3
+ `,R=`@ECHO OFF
4
+ node ${_e(t)} --sessions-file ${b} %*
5
+ `,T=`$ErrorActionPreference = 'Stop'
6
+ $cli = ${Ee(t)}
7
+ $sessionFile = ${S}
8
8
  & node $cli --sessions-file $sessionFile @args
9
9
  exit $LASTEXITCODE
10
- `,I=[{path:s,content:R,executable:true},{path:c,content:E},{path:d,content:y}];await promises.unlink(u).catch(()=>{});for(let h of I){try{if(await promises.readFile(h.path,"utf8")===h.content){h.executable&&await promises.chmod(h.path,493);continue}}catch{}await promises.mkdir(path.dirname(h.path),{recursive:true});let B=`${h.path}.tmp`;await promises.writeFile(B,h.content,"utf8"),await promises.rename(B,h.path),h.executable&&await promises.chmod(h.path,493);}}async function ce(t,e,r,s,c,d){await et(t,e,r,s,c,u=>{let f=Date.now(),l=String(process.pid),m=U(u.instances,r),b=m[l]?.startedAt??f;return m[l]={pid:process.pid,port:d,host:Et(e),protocol:_t(e),cacheDir:e.config.cacheDir,projectRoot:e.config.root,configFile:ee(e),startedAt:b,lastSeenAt:f},{updatedAt:f,instances:m}});}async function ue(t,e,r,s,c){await et(t,e,r,s,c,d=>{let u=Date.now(),f=String(process.pid),l=d.instances[f];if(!l)return d;let m=U(d.instances,r);return m[f]={...l,lastSeenAt:u},{updatedAt:u,instances:m}});}async function de(t,e,r,s,c){await et(t,e,r,s,c,d=>{let u=Date.now(),f=U(d.instances,r);return delete f[String(process.pid)],{updatedAt:u,instances:f}});}function fe(t){let e={};for(let[r,s]of Object.entries(t))s!==void 0&&(typeof s=="string"?e[r]=s:Array.isArray(s)&&(e[r]=s.join(",")));return e}function ge(t){return new Promise((e,r)=>{let s="";t.on("data",c=>{s+=c.toString();}),t.on("error",r),t.on("end",()=>{e(s||void 0);});})}function le(t,e){let r=t===void 0?NaN:Number.parseInt(t,10);return Number.isFinite(r)&&r>=0?r:e}function pe(t){return typeof t=="string"&&t.length>0}function me(t){return !(!T(t)||typeof t.id!="string"||typeof t.ok!="boolean")}function be(t){return !(!T(t)||typeof t.requestId!="string"||typeof t.tabId!="string"||!T(t.metadata)||"state"in t&&typeof t.state!="string")}function X(t){let e=Date.now();if(!T(t))return {title:"",pathname:"",href:"",focused:false,wsUrl:"",userAgent:"",registeredAt:e,lastSeenAt:e};let r=typeof t.registeredAt=="number"?t.registeredAt:e,s=typeof t.lastSeenAt=="number"?t.lastSeenAt:e;return {title:typeof t.title=="string"?t.title:"",pathname:typeof t.pathname=="string"?t.pathname:"",href:typeof t.href=="string"?t.href:"",focused:typeof t.focused=="boolean"?t.focused:false,wsUrl:typeof t.wsUrl=="string"?t.wsUrl:"",userAgent:typeof t.userAgent=="string"?t.userAgent:"",registeredAt:r,lastSeenAt:s}}function A(t,e){let r=e-t;return r>zt?"closed":r>Jt?"stale":"open"}function he(t={}){let e=new Map,r=new Map,s=new Map,c=t.removeFromListOnReload??false,d=t.instanceHeartbeatMs??mt,u=t.instanceTtlMs??Gt,f=t.sessionFileName??t.registryFileName??Q,l=t.registryRetries??Wt,m=t.registryRetryDelayMs??Qt,b="",R="",E,y,I=false,B=false;function H(){E!==void 0&&(clearInterval(E),E=void 0);}async function nt(n){R=await Kt(n.config.root),b=re(R,f);let i=jt;if(!await P(i))throw new Error(`vibro cli source file not found: ${i}`);await ae(R,i,b);}async function wt(n){let i=y;if(i===void 0)return;(b.length<=0||R.length<=0)&&await nt(n);let o=Number.isFinite(d)&&d>0?d:mt;await ce(b,n,u,l,m,i),I=true,E!==void 0&&H(),E=setInterval(()=>{ue(b,n,u,l,m).catch(a=>{x("failed to touch Vite instance",a);});},o);}async function rt(n){!b.length||!I||(I=false,H(),await de(b,n,u,l,m));}function At(n){return new Promise((i,o)=>{let a=setTimeout(()=>{e.delete(n),o(new Error(`Bridge request timeout (${n})`));},Ht);e.set(n,{resolve:i,reject:o,timeout:a});})}function It(n){let i=e.get(n.id);i&&(clearTimeout(i.timeout),e.delete(n.id),i.resolve(n));}function M(){let n=Date.now();return Array.from(s.values()).map(i=>({...i,state:A(i.metadata.lastSeenAt,n),metadata:{...i.metadata,lastSeenAt:i.metadata.lastSeenAt}}))}function Vt(){let n=Date.now(),o=M().filter(g=>A(g.metadata.lastSeenAt,n)!=="closed");if(o.length<=0)return;let a=o.find(g=>g.metadata.focused);return a!==void 0?a.id:o[0].id}function ot(n,i,o){let a=Date.now(),g=X(i),_=s.get(n),V={id:n,state:o??A(g.lastSeenAt,a),metadata:{...g,registeredAt:_?.metadata.registeredAt??g.registeredAt,lastSeenAt:a}};return s.set(n,V),V}function vt(n,i,o){let a=Date.now();return i<=0?Promise.resolve(M().map(g=>({...g,state:A(g.metadata.lastSeenAt,a)}))):new Promise((g,_)=>{let V=setTimeout(()=>{it(n);},o);r.set(n,{expected:i,resolve:g,reject:_,timeout:V,responses:new Map});})}function it(n){let i=r.get(n);if(!i)return;clearTimeout(i.timeout),r.delete(n);let o=Date.now(),a=new Map;M().forEach(g=>{a.set(g.id,{...g,state:A(g.metadata.lastSeenAt,o)});}),i.responses.forEach(g=>{a.set(g.id,{...g,state:A(g.metadata.lastSeenAt,o)});}),i.resolve(Array.from(a.values()));}function Pt(n){let i=r.get(n.requestId);if(!i)return;let o=n.state??A(n.metadata.lastSeenAt,Date.now()),a={...X(n.metadata),lastSeenAt:Date.now()},g=ot(n.tabId,a,o);i.responses.set(n.tabId,g),i.expected>0&&i.responses.size>=i.expected&&it(n.requestId);}function q(n,i){if(!T(i))return;let o=i.tabId,a=i.metadata;if(!pe(o)||!T(a))return;let g=X(a);ot(o,g);}function Nt(n){let i=n.split("/").filter(Boolean);if(i.length<2)return;let o=i[0];if(!(o!=="ping"&&o!=="screenshot"))return {commandPath:`/${o}`,targetTabId:i[1]}}return {name:"vibro-plugin",apply:"serve",configureServer(n){let i=async()=>{if(y=te(n),y!==void 0)try{if(await nt(n),await wt(n),!B){let o=_t(n),a=Et(n);console.info(` \u25A0 Registered server ${a?`${o}://${a}:${y}`:`:${y}`}`),console.info(` [vibro] registry ready at ${a?`${o}://${a}:${y}`:`:${y}`}`),console.info(` [vibro] sessions: ${b}`),console.info(` [vibro] cli: ${D(R)}`),B=!0;}}catch(o){x("failed to register Vite instance",o);}};n.httpServer?.listening?i():n.httpServer&&n.httpServer.once("listening",()=>{i();}),n.httpServer?.once("close",()=>{rt(n).catch(o=>{x("failed to detach Vite instance",o);});}),c&&n.ws.on("vite:beforeFullReload",()=>{rt(n).catch(o=>{x("failed to detach Vite instance on reload",o);});}),n.ws.on(ct,o=>{me(o)&&It(o);}),n.ws.on(z,o=>{q(z,o);}),n.ws.on(G,o=>{q(G,o);}),n.ws.on(W,o=>{q(W,o);}),n.ws.on(dt,o=>{be(o)&&Pt(o);}),n.middlewares.use(L,async(o,a,g)=>{if(!o.url||!o.method){g();return}let _=new URL(o.url,"http://localhost"),V=o.method.toUpperCase(),kt=!["GET","HEAD"].includes(V),w={id:crypto.randomUUID(),path:_.pathname.startsWith(L)?_.pathname.substring(L.length)||"/":_.pathname,method:V,query:Object.fromEntries(_.searchParams.entries()),headers:fe(o.headers),body:kt?await ge(o).catch(()=>{}):void 0};if(console.log(`[vibro] Received a signal: ${V} ${_}`),w.path==="/list"){let S=le(w.query.timeout,qt),N=w.id,Ft=Date.now(),st=M().map(O=>({...O,state:A(O.metadata.lastSeenAt,Ft)})).filter(O=>O.state!=="closed").length,Dt=vt(N,st,S);st>0&&n.ws.send(ut,{requestId:N});let Mt=await Dt;a.statusCode=200,a.setHeader("content-type","application/json; charset=utf-8"),a.end(JSON.stringify({ok:true,payload:{tabs:Mt}}));return}let v,J=Nt(w.path);if(J!==void 0?(v=J.targetTabId,w.path=J.commandPath):w.path==="/screenshot"&&(v=Vt()),v!==void 0&&(w.targetTabId=v),v!==void 0){let S=s.get(v),N=Date.now();if(!S||A(S.metadata.lastSeenAt,N)==="closed"){a.statusCode=404,a.setHeader("content-type","application/json; charset=utf-8"),a.end(JSON.stringify({ok:false,error:`Unknown target tab: ${v}`}));return}}let Bt=At(w.id);n.ws.send(at,w);try{let S=await Bt;a.statusCode=S.ok?200:500,a.setHeader("content-type","application/json; charset=utf-8"),a.end(JSON.stringify({ok:S.ok,payload:S.payload,error:S.error}));}catch(S){let N=S instanceof Error?S.message:String(S);a.statusCode=504,a.setHeader("content-type","application/json; charset=utf-8"),a.end(JSON.stringify({ok:false,error:N}));}});},transformIndexHtml(n){return {html:n,tags:[{tag:"script",injectTo:"body-prepend",attrs:{type:"module",src:Ut}}]}}}}
11
- exports.vibroVitePlugin=he;
10
+ `,_=[{path:a,content:V,executable:true},{path:c,content:R},{path:d,content:T}];await promises.unlink(u).catch(()=>{});for(let p of _){try{if(await promises.readFile(p.path,"utf8")===p.content){p.executable&&await promises.chmod(p.path,493);continue}}catch{}await promises.mkdir(path.dirname(p.path),{recursive:true});let N=`${p.path}.tmp`;await promises.writeFile(N,p.content,"utf8"),await promises.rename(N,p.path),p.executable&&await promises.chmod(p.path,493);}}async function ht(e,t,r,a,c,d){await ne(e,t,r,a,c,u=>{let f=Date.now(),g=String(process.pid),b=H(u.instances,r),S=b[g]?.startedAt??f;return b[g]={pid:process.pid,port:d,host:Ve(t),protocol:ve(t),cacheDir:t.config.cacheDir,projectRoot:t.config.root,configFile:ut(t),startedAt:S,lastSeenAt:f},{updatedAt:f,instances:b}});}async function St(e,t,r,a,c){await ne(e,t,r,a,c,d=>{let u=Date.now(),f=String(process.pid),g=d.instances[f];if(!g)return d;let b=H(d.instances,r);return b[f]={...g,lastSeenAt:u},{updatedAt:u,instances:b}});}async function Rt(e,t,r,a,c){await ne(e,t,r,a,c,d=>{let u=Date.now(),f=H(d.instances,r);return delete f[String(process.pid)],{updatedAt:u,instances:f}});}function yt(e){let t={};for(let[r,a]of Object.entries(e))a!==void 0&&(typeof a=="string"?t[r]=a:Array.isArray(a)&&(t[r]=a.join(",")));return t}function Tt(e){return new Promise((t,r)=>{let a="";e.on("data",c=>{a+=c.toString();}),e.on("error",r),e.on("end",()=>{t(a||void 0);});})}function _t(e,t){let r=e===void 0?NaN:Number.parseInt(e,10);return Number.isFinite(r)&&r>=0?r:t}function Et(e){return typeof e=="string"&&e.length>0}function wt(e){return !(!y(e)||typeof e.id!="string"||typeof e.ok!="boolean")}function At(e){return !(!y(e)||typeof e.requestId!="string"||typeof e.tabId!="string"||!y(e.metadata)||"state"in e&&typeof e.state!="string")}function Q(e){let t=Date.now();if(!y(e))return {title:"",pathname:"",href:"",focused:false,wsUrl:"",userAgent:"",registeredAt:t,lastSeenAt:t};let r=typeof e.registeredAt=="number"?e.registeredAt:t,a=typeof e.lastSeenAt=="number"?e.lastSeenAt:t;return {title:typeof e.title=="string"?e.title:"",pathname:typeof e.pathname=="string"?e.pathname:"",href:typeof e.href=="string"?e.href:"",focused:typeof e.focused=="boolean"?e.focused:false,wsUrl:typeof e.wsUrl=="string"?e.wsUrl:"",userAgent:typeof e.userAgent=="string"?e.userAgent:"",registeredAt:r,lastSeenAt:a}}function A(e,t){let r=t-e;return r>et?"closed":r>Ze?"stale":"open"}function It(e={}){let t=new Map,r=new Map,a=new Map,c=e.removeFromListOnReload??false,d=e.instanceHeartbeatMs??ye,u=e.instanceTtlMs??tt,f=e.sessionFileName??e.registryFileName??K,g=e.registryRetries??nt,b=e.registryRetryDelayMs??rt,S=e.verboseServer??false,V=e.verboseClient??false,R="",T="",_,p,N=false,re=false;function oe(){_!==void 0&&(clearInterval(_),_=void 0);}async function ie(n){T=await st(n.config.root),R=ft(T,f);let i=ze;if(!await P(i))throw new Error(`vibro cli source file not found: ${i}`);await bt(T,i,R);}async function Pe(n){let i=p;if(i===void 0)return;(R.length<=0||T.length<=0)&&await ie(n);let o=Number.isFinite(d)&&d>0?d:ye;await ht(R,n,u,g,b,i),N=true,_!==void 0&&oe(),_=setInterval(()=>{St(R,n,u,g,b).catch(s=>{C("failed to touch Vite instance",s,S);});},o);}async function se(n){!R.length||!N||(N=false,oe(),await Rt(R,n,u,g,b));}function Ne(n){return new Promise((i,o)=>{let s=setTimeout(()=>{t.delete(n),o(new Error(`Bridge request timeout (${n})`));},Qe);t.set(n,{resolve:i,reject:o,timeout:s});})}function ke(n){let i=t.get(n.id);i&&(clearTimeout(i.timeout),t.delete(n.id),i.resolve(n));}function M(){let n=Date.now();return Array.from(a.values()).map(i=>({...i,state:A(i.metadata.lastSeenAt,n),metadata:{...i.metadata,lastSeenAt:i.metadata.lastSeenAt}}))}function Be(){let n=Date.now(),o=M().filter(l=>A(l.metadata.lastSeenAt,n)!=="closed");if(o.length<=0)return;let s=o.find(l=>l.metadata.focused);return s!==void 0?s.id:o[0].id}function ae(n,i,o){let s=Date.now(),l=Q(i),E=a.get(n),I={id:n,state:o??A(l.lastSeenAt,s),metadata:{...l,registeredAt:E?.metadata.registeredAt??l.registeredAt,lastSeenAt:s}};return a.set(n,I),I}function Fe(n,i,o){let s=Date.now();return i<=0?Promise.resolve(M().map(l=>({...l,state:A(l.metadata.lastSeenAt,s)}))):new Promise((l,E)=>{let I=setTimeout(()=>{ce(n);},o);r.set(n,{expected:i,resolve:l,reject:E,timeout:I,responses:new Map});})}function ce(n){let i=r.get(n);if(!i)return;clearTimeout(i.timeout),r.delete(n);let o=Date.now(),s=new Map;M().forEach(l=>{s.set(l.id,{...l,state:A(l.metadata.lastSeenAt,o)});}),i.responses.forEach(l=>{s.set(l.id,{...l,state:A(l.metadata.lastSeenAt,o)});}),i.resolve(Array.from(s.values()));}function De(n){let i=r.get(n.requestId);if(!i)return;let o=n.state??A(n.metadata.lastSeenAt,Date.now()),s={...Q(n.metadata),lastSeenAt:Date.now()},l=ae(n.tabId,s,o);i.responses.set(n.tabId,l),i.expected>0&&i.responses.size>=i.expected&&ce(n.requestId);}function J(n,i){if(!y(i))return;let o=i.tabId,s=i.metadata;if(!Et(o)||!y(s))return;let l=Q(s);ae(o,l);}function Me(n){let i=n.split("/").filter(Boolean);if(i.length<2)return;let o=i[0];if(!(o!=="ping"&&o!=="screenshot"))return {commandPath:`/${o}`,targetTabId:i[1]}}return {name:"vibro-plugin",apply:"serve",config(n){let i=vite.searchForWorkspaceRoot(process.cwd()),o=n.server?.fs?.allow,s=Array.isArray(o)?o:[];return {server:{fs:{allow:Ke([...s,i,Z,Se,Re(Z),Re(Se)])}}}},configureServer(n){let i=async()=>{if(p=ct(n),p!==void 0)try{if(await ie(n),await Pe(n),!re){let o=ve(n),s=Ve(n);S&&(console.info(` \u279C Registered Vibro ${s?`${o}://${s}:${p}`:`:${p}`}`),console.info(`[vibro] registry ready at ${s?`${o}://${s}:${p}`:`:${p}`}`),console.info(`[vibro] sessions: ${R}`),console.info(`[vibro] cli: ${D(T)}`)),re=!0;}}catch(o){C("failed to register Vite instance",o,S);}};n.httpServer?.listening?i():n.httpServer&&n.httpServer.once("listening",()=>{i();}),n.httpServer?.once("close",()=>{se(n).catch(o=>{C("failed to detach Vite instance",o,S);});}),c&&n.ws.on("vite:beforeFullReload",()=>{se(n).catch(o=>{C("failed to detach Vite instance on reload",o,S);});}),n.ws.on(fe,o=>{wt(o)&&ke(o);}),n.ws.on(W,o=>{J(W,o);}),n.ws.on(z,o=>{J(z,o);}),n.ws.on(Y,o=>{J(Y,o);}),n.ws.on(ge,o=>{At(o)&&De(o);}),n.middlewares.use(L,async(o,s,l)=>{if(!o.url||!o.method){l();return}let E=new URL(o.url,"http://localhost"),I=o.method.toUpperCase(),Oe=!["GET","HEAD"].includes(I),w={id:crypto.randomUUID(),path:E.pathname.startsWith(L)?E.pathname.substring(L.length)||"/":E.pathname,method:I,query:Object.fromEntries(E.searchParams.entries()),headers:yt(o.headers),body:Oe?await Tt(o).catch(()=>{}):void 0};if(S&&console.log(`[vibro] Received a signal: ${I} ${E}`),w.path==="/list"){let h=_t(w.query.timeout,Xe),k=w.id,$e=Date.now(),ue=M().map(O=>({...O,state:A(O.metadata.lastSeenAt,$e)})).filter(O=>O.state!=="closed").length,Ce=Fe(k,ue,h);ue>0&&n.ws.send(le,{requestId:k});let xe=await Ce;s.statusCode=200,s.setHeader("content-type","application/json; charset=utf-8"),s.end(JSON.stringify({ok:true,payload:{tabs:xe}}));return}let v,G=Me(w.path);if(G!==void 0?(v=G.targetTabId,w.path=G.commandPath):w.path==="/screenshot"&&(v=Be()),v!==void 0&&(w.targetTabId=v),v!==void 0){let h=a.get(v),k=Date.now();if(!h||A(h.metadata.lastSeenAt,k)==="closed"){s.statusCode=404,s.setHeader("content-type","application/json; charset=utf-8"),s.end(JSON.stringify({ok:false,error:`Unknown target tab: ${v}`}));return}}let Le=Ne(w.id);n.ws.send(de,w);try{let h=await Le;s.statusCode=h.ok?200:500,s.setHeader("content-type","application/json; charset=utf-8"),s.end(JSON.stringify({ok:h.ok,payload:h.payload,error:h.error}));}catch(h){let k=h instanceof Error?h.message:String(h);s.statusCode=504,s.setHeader("content-type","application/json; charset=utf-8"),s.end(JSON.stringify({ok:false,error:k}));}});},transformIndexHtml(n){return {html:n,tags:[{tag:"script",injectTo:"body-prepend",children:`window.__vibroVerboseClient = ${V};`},{tag:"script",injectTo:"body-prepend",attrs:{type:"module",src:Ye}}]}}}}
11
+ exports.vibroVitePlugin=It;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibro/bro",
3
- "version": "0.0.1-alpha.1",
3
+ "version": "0.0.1-alpha.3",
4
4
  "description": "Vibro plugin and runtime bridge",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -44,7 +44,11 @@
44
44
  "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
45
45
  },
46
46
  "files": [
47
- "dist",
47
+ "dist/vibro-plugin.js",
48
+ "dist/vibro-plugin.d.ts",
49
+ "dist/vibro-cli.js",
50
+ "dist/vibro-client.js",
51
+ "dist/vibro-client.d.mts",
48
52
  "package.json",
49
53
  "README.md",
50
54
  "LICENSE"