gazesight 0.5.1 → 0.5.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/dist/chrome/background.js +1 -1
- package/dist/chrome/manifest.json +2 -2
- package/dist/chrome/popup.html +2 -2
- package/dist/chrome/popup.js +1 -1
- package/dist/cli/index.js +55 -14
- package/dist/firefox/background.js +21 -21
- package/dist/firefox/manifest.json +90 -90
- package/dist/firefox/popup.html +2 -2
- package/dist/firefox/popup.js +1 -1
- package/dist/gazesight-firefox.xpi +0 -0
- package/dist/mcp/index.js +100 -49
- package/package.json +141 -141
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "GazeSight",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.1",
|
|
5
5
|
"description": "Give coding agents visual access to the Chrome tab you're already using.",
|
|
6
6
|
"minimum_chrome_version": "102",
|
|
7
7
|
"icons": {
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"open_in_tab": true
|
|
52
52
|
},
|
|
53
53
|
"content_security_policy": {
|
|
54
|
-
"extension_pages": "script-src 'self'; object-src 'none'; connect-src ws://127.0.0.1:* http://127.0.0.1:* data:"
|
|
54
|
+
"extension_pages": "script-src 'self'; object-src 'none'; connect-src ws://127.0.0.1:* http://127.0.0.1:* data:"
|
|
55
55
|
},
|
|
56
56
|
"content_scripts": [
|
|
57
57
|
{
|
package/dist/chrome/popup.html
CHANGED
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
<div class="paper">
|
|
20
20
|
<main>
|
|
21
21
|
<section id="pairing-connect" class="pairing-connect" hidden>
|
|
22
|
-
<strong>Connect your browser</strong>
|
|
23
|
-
<p id="pairing-message">
|
|
22
|
+
<strong id="pairing-title">Connect your browser</strong>
|
|
23
|
+
<p id="pairing-message">Click Connect to GazeSight and approve the matching code in your terminal.</p>
|
|
24
24
|
<p id="pairing-code" class="pairing-code" hidden></p>
|
|
25
25
|
<button id="connect" class="primary connect">Connect to GazeSight</button>
|
|
26
26
|
</section>
|
package/dist/chrome/popup.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Q=Object.create;var $=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var te=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports);var ne=(e,r,a,c)=>{if(r&&typeof r=="object"||typeof r=="function")for(let l of X(r))!re.call(e,l)&&l!==a&&$(e,l,{get:()=>r[l],enumerable:!(c=Y(r,l))||c.enumerable});return e};var se=(e,r,a)=>(a=e!=null?Q(ee(e)):{},ne(r||!e||!e.__esModule?$(a,"default",{value:e,enumerable:!0}):a,e));var q=te((z,O)=>{(function(e,r){if(typeof define=="function"&&define.amd)define("webextension-polyfill",["module"],r);else if(typeof z<"u")r(O);else{var a={exports:{}};r(a),e.browser=a.exports}})(typeof globalThis<"u"?globalThis:typeof self<"u"?self:z,function(e){"use strict";if(!(globalThis.chrome&&globalThis.chrome.runtime&&globalThis.chrome.runtime.id))throw new Error("This script should only be loaded in a browser extension.");if(globalThis.browser&&globalThis.browser.runtime&&globalThis.browser.runtime.id)e.exports=globalThis.browser;else{let r="The message port closed before a response was received.",a=c=>{let l={alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getSubTree:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{disable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},openPopup:{minArgs:0,maxArgs:0},setBadgeBackgroundColor:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},browsingData:{remove:{minArgs:2,maxArgs:2},removeCache:{minArgs:1,maxArgs:1},removeCookies:{minArgs:1,maxArgs:1},removeDownloads:{minArgs:1,maxArgs:1},removeFormData:{minArgs:1,maxArgs:1},removeHistory:{minArgs:1,maxArgs:1},removeLocalStorage:{minArgs:1,maxArgs:1},removePasswords:{minArgs:1,maxArgs:1},removePluginData:{minArgs:1,maxArgs:1},settings:{minArgs:0,maxArgs:0}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},devtools:{inspectedWindow:{eval:{minArgs:1,maxArgs:2,singleCallbackArg:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},elements:{createSidebarPane:{minArgs:1,maxArgs:1}}}},downloads:{cancel:{minArgs:1,maxArgs:1},download:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},identity:{launchWebAuthFlow:{minArgs:1,maxArgs:1}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},setEnabled:{minArgs:2,maxArgs:2},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},permissions:{contains:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},request:{minArgs:1,maxArgs:1}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},sessions:{getDevices:{minArgs:0,maxArgs:1},getRecentlyClosed:{minArgs:0,maxArgs:1},restore:{minArgs:0,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{captureVisibleTab:{minArgs:0,maxArgs:2},create:{minArgs:1,maxArgs:1},detectLanguage:{minArgs:0,maxArgs:1},discard:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},goBack:{minArgs:0,maxArgs:1},goForward:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},query:{minArgs:1,maxArgs:1},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},topSites:{get:{minArgs:0,maxArgs:0}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}};if(Object.keys(l).length===0)throw new Error("api-metadata.json has not been included in browser-polyfill");class h extends WeakMap{constructor(n,i=void 0){super(i),this.createItem=n}get(n){return this.has(n)||this.set(n,this.createItem(n)),super.get(n)}}let C=t=>t&&typeof t=="object"&&typeof t.then=="function",k=(t,n)=>(...i)=>{c.runtime.lastError?t.reject(new Error(c.runtime.lastError.message)):n.singleCallbackArg||i.length<=1&&n.singleCallbackArg!==!1?t.resolve(i[0]):t.resolve(i)},A=t=>t==1?"argument":"arguments",E=(t,n)=>function(o,...d){if(d.length<n.minArgs)throw new Error(`Expected at least ${n.minArgs} ${A(n.minArgs)} for ${t}(), got ${d.length}`);if(d.length>n.maxArgs)throw new Error(`Expected at most ${n.maxArgs} ${A(n.maxArgs)} for ${t}(), got ${d.length}`);return new Promise((u,b)=>{if(n.fallbackToNoCallback)try{o[t](...d,k({resolve:u,reject:b},n))}catch(s){console.warn(`${t} API method doesn't seem to support the callback parameter, falling back to call it without a callback: `,s),o[t](...d),n.fallbackToNoCallback=!1,n.noCallback=!0,u()}else n.noCallback?(o[t](...d),u()):o[t](...d,k({resolve:u,reject:b},n))})},N=(t,n,i)=>new Proxy(n,{apply(o,d,u){return i.call(d,t,...u)}}),P=Function.call.bind(Object.prototype.hasOwnProperty),I=(t,n={},i={})=>{let o=Object.create(null),d={has(b,s){return s in t||s in o},get(b,s,p){if(s in o)return o[s];if(!(s in t))return;let m=t[s];if(typeof m=="function")if(typeof n[s]=="function")m=N(t,t[s],n[s]);else if(P(i,s)){let v=E(s,i[s]);m=N(t,t[s],v)}else m=m.bind(t);else if(typeof m=="object"&&m!==null&&(P(n,s)||P(i,s)))m=I(m,n[s],i[s]);else if(P(i,"*"))m=I(m,n[s],i["*"]);else return Object.defineProperty(o,s,{configurable:!0,enumerable:!0,get(){return t[s]},set(v){t[s]=v}}),m;return o[s]=m,m},set(b,s,p,m){return s in o?o[s]=p:t[s]=p,!0},defineProperty(b,s,p){return Reflect.defineProperty(o,s,p)},deleteProperty(b,s){return Reflect.deleteProperty(o,s)}},u=Object.create(t);return new Proxy(u,d)},R=t=>({addListener(n,i,...o){n.addListener(t.get(i),...o)},hasListener(n,i){return n.hasListener(t.get(i))},removeListener(n,i){n.removeListener(t.get(i))}}),K=new h(t=>typeof t!="function"?t:function(i){let o=I(i,{},{getContent:{minArgs:0,maxArgs:0}});t(o)}),B=new h(t=>typeof t!="function"?t:function(i,o,d){let u=!1,b,s=new Promise(T=>{b=function(f){u=!0,T(f)}}),p;try{p=t(i,o,b)}catch(T){p=Promise.reject(T)}let m=p!==!0&&C(p);if(p!==!0&&!m&&!u)return!1;let v=T=>{T.then(f=>{d(f)},f=>{let M;f&&(f instanceof Error||typeof f.message=="string")?M=f.message:M="An unexpected error occurred",d({__mozWebExtensionPolyfillReject__:!0,message:M})}).catch(f=>{console.error("Failed to send onMessage rejected reply",f)})};return v(m?p:s),!0}),Z=({reject:t,resolve:n},i)=>{c.runtime.lastError?c.runtime.lastError.message===r?n():t(new Error(c.runtime.lastError.message)):i&&i.__mozWebExtensionPolyfillReject__?t(new Error(i.message)):n(i)},L=(t,n,i,...o)=>{if(o.length<n.minArgs)throw new Error(`Expected at least ${n.minArgs} ${A(n.minArgs)} for ${t}(), got ${o.length}`);if(o.length>n.maxArgs)throw new Error(`Expected at most ${n.maxArgs} ${A(n.maxArgs)} for ${t}(), got ${o.length}`);return new Promise((d,u)=>{let b=Z.bind(null,{resolve:d,reject:u});o.push(b),i.sendMessage(...o)})},J={devtools:{network:{onRequestFinished:R(K)}},runtime:{onMessage:R(B),onMessageExternal:R(B),sendMessage:L.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:L.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},_={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return l.privacy={network:{"*":_},services:{"*":_},websites:{"*":_}},I(c,J,l)};e.exports=a(chrome)}})});var U=se(q(),1);globalThis.browser=U.default;var x="pendingPairing";function ie(){return[...crypto.getRandomValues(new Uint8Array(32))].map(r=>r.toString(16).padStart(2,"0")).join("")}function ae(){return location.protocol==="moz-extension:"?"firefox":"chrome"}async function j(e,r,a,c,l=2500){return fetch(`http://127.0.0.1:${e}/gazesight/pairing/${r}`,{method:"POST",headers:{"Content-Type":"application/json",...c?{Authorization:`Bearer ${c}`}:{}},body:JSON.stringify(a),signal:AbortSignal.timeout(l)})}async function D(e,r){let{requestId:a,proof:c,code:l,expiresAt:h,port:C}=r;for(;;){if(Date.now()>=h)return await browser.storage.local.remove(x),e("expired",l),!1;e("waiting_approval",l);let k;try{k=await j(C,"status",{requestId:a,secret:c})}catch{await new Promise(E=>setTimeout(E,800));continue}let A=await k.json();if(A.state==="approved"&&A.credential&&A.pairingId)return await browser.storage.local.set({token:A.credential,pairingId:A.pairingId,port:C,pairingState:"connected"}),await browser.storage.local.remove(x),e("connected"),!0;if(A.state==="rejected")return await browser.storage.local.remove(x),e("reconnect_required",l),!1;if(A.state==="expired"||k.status===410)return await browser.storage.local.remove(x),e("expired",l),!1;await new Promise(E=>setTimeout(E,800))}}async function F(e,r=32147){e("searching");let a=ie(),c;try{c=await j(r,"request",{browser:ae(),extensionId:browser.runtime.id,secret:a},void 0,6e4)}catch{return e("unavailable"),!1}if(!c.ok)return e("unavailable"),!1;let l=await c.json(),h={requestId:l.requestId,proof:a,code:l.code,expiresAt:l.expiresAt,port:r};return await browser.storage.local.set({[x]:h}),e("pending",l.code),D(e,h)}async function G(e){let a=(await browser.storage.local.get(x))[x];if(a){if(Date.now()>=a.expiresAt){await browser.storage.local.remove(x);return}return D(e,a)}}function g(e,r){document.getElementById(e).textContent=r}var S=!1,W;function V(e,r=!1){clearTimeout(W),g("feedback",e),r&&(W=setTimeout(()=>g("feedback",""),3500))}async function y(e){let r=await browser.runtime.sendMessage({type:"gazesight-ui",action:e});if(!r?.ok)throw new Error(r?.error??"GazeSight unavailable. Open settings to check pairing.");return r.value}async function w(){let e=await y("status");document.body.dataset.connected=String(e.connected),g("connection",e.connected?"Connected":"Disconnected");let r=await browser.storage.local.get(["token","port"]);document.getElementById("pairing-connect").hidden=typeof r.token=="string",document.body.dataset.background=e.backgroundCapture.enabled?"enabled":"disabled",g("background-state",e.backgroundCapture.enabled?"On":"Off"),g("background-toggle",e.backgroundCapture.enabled?"Disable":"Enable"),document.getElementById("background-toggle").setAttribute("aria-pressed",String(e.backgroundCapture.enabled)),g("background-description",e.backgroundCapture.enabled?"GazeSight can capture this target while you work elsewhere.":e.backgroundCapture.permissionGranted?"Background mode is off. Firefox still reports the optional permission; remove it in Add-ons Manager if needed.":e.backgroundMode==="permission_denied"?"Permission was not granted. Standard foreground capture remains available.":"Allow GazeSight to keep capturing the selected development tab while you work in another tab or application."),document.body.dataset.continuous=e.continuousAuthorization.enabled?"enabled":"disabled",g("continuous-state",e.continuousAuthorization.enabled?"On":"Off"),g("continuous-toggle",e.continuousAuthorization.enabled?"Disable":"Enable"),document.getElementById("continuous-toggle").setAttribute("aria-pressed",String(e.continuousAuthorization.enabled)),g("continuous-description",e.continuousAuthorization.enabled?e.continuousAuthorization.authorizedOrigin?`Staying connected to ${e.continuousAuthorization.authorizedOrigin} across reloads, navigation and previews.`:"Keeps GazeSight connected across reloads, navigation and previews once you select a tab.":"Keep GazeSight connected to this development tab across reloads, navigation and responsive previews, so you don't have to reauthorize it every time."),g("pairing",e.paired?"Paired":"Not paired"),g("target",e.targetState==="authorized"?"Authorized":e.targetState==="none"?"None":"Reauthorize"),g("url",e.url??"No target selected"),g("viewport",e.viewport?`${e.viewport.width} \xD7 ${e.viewport.height} CSS \xB7 DPR ${e.viewport.devicePixelRatio}`:"Viewport unavailable"),g("select-label",e.targetState==="reauthorization_required"?"Reauthorize this tab":"Use this tab"),g("last-capture",e.lastCapture?`${e.lastCapture.mode} \xB7 ${e.lastCapture.width} \xD7 ${e.lastCapture.height} \xB7 ${new Date(e.lastCapture.time).toLocaleTimeString()}`:"None yet"),g("last-error",e.lastError?`${e.lastError.code}: ${e.lastError.message}`:"None");for(let a of["fast","stable"])document.getElementById(a).disabled=S||!e.connected||e.targetState!=="authorized";document.getElementById("disconnect").disabled=S||e.targetState==="none"}var oe={not_connected:"Not connected.",searching:"Searching for local GazeSight\u2026",pending:"Pairing request pending.",waiting_approval:"Waiting for approval in your terminal\u2026",connected:"Connected.",unavailable:"Connection unavailable. Run gazesight pair and try again.",expired:"Pairing expired. Try again.",reconnect_required:"Reconnect required."};function H(e,r){let a=document.getElementById("pairing-code");g("pairing-message",oe[e]),a.hidden=!r,a.textContent=r?`Verification code: ${r}`:""}document.getElementById("connect").addEventListener("click",async()=>{let e=document.getElementById("connect");e.disabled=!0;let r=await browser.storage.local.get(["port"]);await F(H,Number(r.port??32147)),e.disabled=!1,await w()});(async()=>typeof(await browser.storage.local.get(["token"])).token!="string"&&await G(H)&&await w())();for(let e of["select","disconnect","fast","stable","diagnostics"])document.getElementById(e).addEventListener("click",async()=>{if(!S){S=!0,document.querySelectorAll("button").forEach(r=>r.disabled=!0),g("feedback",e==="fast"||e==="stable"?"Capturing\u2026":"Working\u2026");try{if(e==="fast"&&!await browser.permissions.contains({permissions:["downloads"]})){await browser.windows.create({url:browser.runtime.getURL("permission.html?action=download"),type:"popup",focused:!0,width:600,height:700}),window.close();return}let r=await y(e);e==="diagnostics"&&(document.getElementById("diagnostics-panel").hidden=!1,g("diagnostics-output",JSON.stringify(r,null,2))),V(e==="disconnect"?"Target disconnected.":e==="select"?"Target selected.":e==="diagnostics"?"Diagnostics updated.":e==="fast"?`\u2713 Saved to Downloads/${r.filename}`:"Capture completed.",e==="fast")}catch(r){V(r instanceof Error?r.message:"Operation failed.")}finally{S=!1,document.querySelectorAll("button").forEach(r=>r.disabled=!1),await w().catch(r=>g("feedback",String(r)))}}});document.getElementById("copy-url").addEventListener("click",async()=>{let e=document.getElementById("url").textContent;if(!(!e||e==="No target selected"))try{await navigator.clipboard.writeText(e),g("feedback","URL copied.")}catch{g("feedback","Unable to copy URL. Select and copy it manually.")}});document.getElementById("background-toggle").addEventListener("click",async()=>{if((await y("status")).backgroundCapture.enabled){await y("background-disable"),await w();return}await browser.windows.create({url:browser.runtime.getURL("permission.html?action=background"),type:"popup",focused:!0,width:600,height:700}),window.close()});document.getElementById("continuous-toggle").addEventListener("click",async()=>{let e=await y("status");if(e.continuousAuthorization.enabled){await y("continuous-disable"),await w();return}if(e.continuousAuthorization.permissionGranted){await y("continuous-enable"),await w();return}await browser.windows.create({url:browser.runtime.getURL("permission.html?action=continuous"),type:"popup",focused:!0,width:600,height:700}),window.close()});browser.commands.getAll().then(e=>{let r=e.find(a=>a.name==="gazesight-select-target")?.shortcut;r&&g("shortcut",r)}).catch(()=>{});document.getElementById("settings").addEventListener("click",()=>void browser.runtime.openOptionsPage());w().catch(e=>g("feedback",String(e)));var ge=setInterval(()=>{S||w().catch(e=>g("feedback",String(e)))},2e3);window.addEventListener("pagehide",()=>clearInterval(ge),{once:!0});
|
|
1
|
+
var Q=Object.create;var $=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var ee=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var te=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports);var ne=(e,r,a,l)=>{if(r&&typeof r=="object"||typeof r=="function")for(let c of X(r))!re.call(e,c)&&c!==a&&$(e,c,{get:()=>r[c],enumerable:!(l=Y(r,c))||l.enumerable});return e};var se=(e,r,a)=>(a=e!=null?Q(ee(e)):{},ne(r||!e||!e.__esModule?$(a,"default",{value:e,enumerable:!0}):a,e));var q=te((z,O)=>{(function(e,r){if(typeof define=="function"&&define.amd)define("webextension-polyfill",["module"],r);else if(typeof z<"u")r(O);else{var a={exports:{}};r(a),e.browser=a.exports}})(typeof globalThis<"u"?globalThis:typeof self<"u"?self:z,function(e){"use strict";if(!(globalThis.chrome&&globalThis.chrome.runtime&&globalThis.chrome.runtime.id))throw new Error("This script should only be loaded in a browser extension.");if(globalThis.browser&&globalThis.browser.runtime&&globalThis.browser.runtime.id)e.exports=globalThis.browser;else{let r="The message port closed before a response was received.",a=l=>{let c={alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getSubTree:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{disable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},enable:{minArgs:0,maxArgs:1,fallbackToNoCallback:!0},getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},openPopup:{minArgs:0,maxArgs:0},setBadgeBackgroundColor:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setBadgeText:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},browsingData:{remove:{minArgs:2,maxArgs:2},removeCache:{minArgs:1,maxArgs:1},removeCookies:{minArgs:1,maxArgs:1},removeDownloads:{minArgs:1,maxArgs:1},removeFormData:{minArgs:1,maxArgs:1},removeHistory:{minArgs:1,maxArgs:1},removeLocalStorage:{minArgs:1,maxArgs:1},removePasswords:{minArgs:1,maxArgs:1},removePluginData:{minArgs:1,maxArgs:1},settings:{minArgs:0,maxArgs:0}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},devtools:{inspectedWindow:{eval:{minArgs:1,maxArgs:2,singleCallbackArg:!1}},panels:{create:{minArgs:3,maxArgs:3,singleCallbackArg:!0},elements:{createSidebarPane:{minArgs:1,maxArgs:1}}}},downloads:{cancel:{minArgs:1,maxArgs:1},download:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},identity:{launchWebAuthFlow:{minArgs:1,maxArgs:1}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},setEnabled:{minArgs:2,maxArgs:2},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setIcon:{minArgs:1,maxArgs:1},setPopup:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},setTitle:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0},show:{minArgs:1,maxArgs:1,fallbackToNoCallback:!0}},permissions:{contains:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},request:{minArgs:1,maxArgs:1}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},sessions:{getDevices:{minArgs:0,maxArgs:1},getRecentlyClosed:{minArgs:0,maxArgs:1},restore:{minArgs:0,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{captureVisibleTab:{minArgs:0,maxArgs:2},create:{minArgs:1,maxArgs:1},detectLanguage:{minArgs:0,maxArgs:1},discard:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},goBack:{minArgs:0,maxArgs:1},goForward:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},query:{minArgs:1,maxArgs:1},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},topSites:{get:{minArgs:0,maxArgs:0}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}};if(Object.keys(c).length===0)throw new Error("api-metadata.json has not been included in browser-polyfill");class w extends WeakMap{constructor(n,i=void 0){super(i),this.createItem=n}get(n){return this.has(n)||this.set(n,this.createItem(n)),super.get(n)}}let C=t=>t&&typeof t=="object"&&typeof t.then=="function",k=(t,n)=>(...i)=>{l.runtime.lastError?t.reject(new Error(l.runtime.lastError.message)):n.singleCallbackArg||i.length<=1&&n.singleCallbackArg!==!1?t.resolve(i[0]):t.resolve(i)},A=t=>t==1?"argument":"arguments",E=(t,n)=>function(o,...d){if(d.length<n.minArgs)throw new Error(`Expected at least ${n.minArgs} ${A(n.minArgs)} for ${t}(), got ${d.length}`);if(d.length>n.maxArgs)throw new Error(`Expected at most ${n.maxArgs} ${A(n.maxArgs)} for ${t}(), got ${d.length}`);return new Promise((u,b)=>{if(n.fallbackToNoCallback)try{o[t](...d,k({resolve:u,reject:b},n))}catch(s){console.warn(`${t} API method doesn't seem to support the callback parameter, falling back to call it without a callback: `,s),o[t](...d),n.fallbackToNoCallback=!1,n.noCallback=!0,u()}else n.noCallback?(o[t](...d),u()):o[t](...d,k({resolve:u,reject:b},n))})},N=(t,n,i)=>new Proxy(n,{apply(o,d,u){return i.call(d,t,...u)}}),P=Function.call.bind(Object.prototype.hasOwnProperty),I=(t,n={},i={})=>{let o=Object.create(null),d={has(b,s){return s in t||s in o},get(b,s,p){if(s in o)return o[s];if(!(s in t))return;let m=t[s];if(typeof m=="function")if(typeof n[s]=="function")m=N(t,t[s],n[s]);else if(P(i,s)){let v=E(s,i[s]);m=N(t,t[s],v)}else m=m.bind(t);else if(typeof m=="object"&&m!==null&&(P(n,s)||P(i,s)))m=I(m,n[s],i[s]);else if(P(i,"*"))m=I(m,n[s],i["*"]);else return Object.defineProperty(o,s,{configurable:!0,enumerable:!0,get(){return t[s]},set(v){t[s]=v}}),m;return o[s]=m,m},set(b,s,p,m){return s in o?o[s]=p:t[s]=p,!0},defineProperty(b,s,p){return Reflect.defineProperty(o,s,p)},deleteProperty(b,s){return Reflect.deleteProperty(o,s)}},u=Object.create(t);return new Proxy(u,d)},R=t=>({addListener(n,i,...o){n.addListener(t.get(i),...o)},hasListener(n,i){return n.hasListener(t.get(i))},removeListener(n,i){n.removeListener(t.get(i))}}),K=new w(t=>typeof t!="function"?t:function(i){let o=I(i,{},{getContent:{minArgs:0,maxArgs:0}});t(o)}),B=new w(t=>typeof t!="function"?t:function(i,o,d){let u=!1,b,s=new Promise(T=>{b=function(f){u=!0,T(f)}}),p;try{p=t(i,o,b)}catch(T){p=Promise.reject(T)}let m=p!==!0&&C(p);if(p!==!0&&!m&&!u)return!1;let v=T=>{T.then(f=>{d(f)},f=>{let M;f&&(f instanceof Error||typeof f.message=="string")?M=f.message:M="An unexpected error occurred",d({__mozWebExtensionPolyfillReject__:!0,message:M})}).catch(f=>{console.error("Failed to send onMessage rejected reply",f)})};return v(m?p:s),!0}),Z=({reject:t,resolve:n},i)=>{l.runtime.lastError?l.runtime.lastError.message===r?n():t(new Error(l.runtime.lastError.message)):i&&i.__mozWebExtensionPolyfillReject__?t(new Error(i.message)):n(i)},L=(t,n,i,...o)=>{if(o.length<n.minArgs)throw new Error(`Expected at least ${n.minArgs} ${A(n.minArgs)} for ${t}(), got ${o.length}`);if(o.length>n.maxArgs)throw new Error(`Expected at most ${n.maxArgs} ${A(n.maxArgs)} for ${t}(), got ${o.length}`);return new Promise((d,u)=>{let b=Z.bind(null,{resolve:d,reject:u});o.push(b),i.sendMessage(...o)})},J={devtools:{network:{onRequestFinished:R(K)}},runtime:{onMessage:R(B),onMessageExternal:R(B),sendMessage:L.bind(null,"sendMessage",{minArgs:1,maxArgs:3})},tabs:{sendMessage:L.bind(null,"sendMessage",{minArgs:2,maxArgs:3})}},_={clear:{minArgs:1,maxArgs:1},get:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}};return c.privacy={network:{"*":_},services:{"*":_},websites:{"*":_}},I(l,J,c)};e.exports=a(chrome)}})});var U=se(q(),1);globalThis.browser=U.default;var x="pendingPairing";function ie(){return[...crypto.getRandomValues(new Uint8Array(32))].map(r=>r.toString(16).padStart(2,"0")).join("")}function ae(){return location.protocol==="moz-extension:"?"firefox":"chrome"}async function j(e,r,a,l,c=2500){return fetch(`http://127.0.0.1:${e}/gazesight/pairing/${r}`,{method:"POST",headers:{"Content-Type":"application/json",...l?{Authorization:`Bearer ${l}`}:{}},body:JSON.stringify(a),signal:AbortSignal.timeout(c)})}async function D(e,r){let{requestId:a,proof:l,code:c,expiresAt:w,port:C}=r;for(;;){if(Date.now()>=w)return await browser.storage.local.remove(x),e("expired",c),!1;e("waiting_approval",c);let k;try{k=await j(C,"status",{requestId:a,secret:l})}catch{await new Promise(E=>setTimeout(E,800));continue}let A=await k.json();if(A.state==="approved"&&A.credential&&A.pairingId)return await browser.storage.local.set({token:A.credential,pairingId:A.pairingId,port:C,pairingState:"connected"}),await browser.storage.local.remove(x),e("connected"),!0;if(A.state==="rejected")return await browser.storage.local.remove(x),e("reconnect_required",c),!1;if(A.state==="expired"||k.status===410)return await browser.storage.local.remove(x),e("expired",c),!1;await new Promise(E=>setTimeout(E,800))}}async function F(e,r=32147){e("searching");let a=ie(),l;try{l=await j(r,"request",{browser:ae(),extensionId:browser.runtime.id,secret:a},void 0,6e4)}catch{return e("unavailable"),!1}if(!l.ok)return e("unavailable"),!1;let c=await l.json(),w={requestId:c.requestId,proof:a,code:c.code,expiresAt:c.expiresAt,port:r};return await browser.storage.local.set({[x]:w}),e("pending",c.code),D(e,w)}async function G(e){let a=(await browser.storage.local.get(x))[x];if(a){if(Date.now()>=a.expiresAt){await browser.storage.local.remove(x);return}return D(e,a)}}function g(e,r){document.getElementById(e).textContent=r}var S=!1,W;function V(e,r=!1){clearTimeout(W),g("feedback",e),r&&(W=setTimeout(()=>g("feedback",""),3500))}async function y(e){let r=await browser.runtime.sendMessage({type:"gazesight-ui",action:e});if(!r?.ok)throw new Error(r?.error??"GazeSight unavailable. Open settings to check pairing.");return r.value}async function h(){let e=await y("status");document.body.dataset.connected=String(e.connected),g("connection",e.connected?"Connected":"Disconnected");let r=await browser.storage.local.get(["token","port"]);document.getElementById("pairing-connect").hidden=e.connected,g("pairing-title",typeof r.token=="string"?"Reconnect or re-pair":"Connect your browser"),document.body.dataset.background=e.backgroundCapture.enabled?"enabled":"disabled",g("background-state",e.backgroundCapture.enabled?"On":"Off"),g("background-toggle",e.backgroundCapture.enabled?"Disable":"Enable"),document.getElementById("background-toggle").setAttribute("aria-pressed",String(e.backgroundCapture.enabled)),g("background-description",e.backgroundCapture.enabled?"GazeSight can capture this target while you work elsewhere.":e.backgroundCapture.permissionGranted?"Background mode is off. Firefox still reports the optional permission; remove it in Add-ons Manager if needed.":e.backgroundMode==="permission_denied"?"Permission was not granted. Standard foreground capture remains available.":"Allow GazeSight to keep capturing the selected development tab while you work in another tab or application."),document.body.dataset.continuous=e.continuousAuthorization.enabled?"enabled":"disabled",g("continuous-state",e.continuousAuthorization.enabled?"On":"Off"),g("continuous-toggle",e.continuousAuthorization.enabled?"Disable":"Enable"),document.getElementById("continuous-toggle").setAttribute("aria-pressed",String(e.continuousAuthorization.enabled)),g("continuous-description",e.continuousAuthorization.enabled?e.continuousAuthorization.authorizedOrigin?`Staying connected to ${e.continuousAuthorization.authorizedOrigin} across reloads, navigation and previews.`:"Keeps GazeSight connected across reloads, navigation and previews once you select a tab.":"Keep GazeSight connected to this development tab across reloads, navigation and responsive previews, so you don't have to reauthorize it every time."),g("pairing",e.paired?"Paired":"Not paired"),g("target",e.targetState==="authorized"?"Authorized":e.targetState==="none"?"None":"Reauthorize"),g("url",e.url??"No target selected"),g("viewport",e.viewport?`${e.viewport.width} \xD7 ${e.viewport.height} CSS \xB7 DPR ${e.viewport.devicePixelRatio}`:"Viewport unavailable"),g("select-label",e.targetState==="reauthorization_required"?"Reauthorize this tab":"Use this tab"),g("last-capture",e.lastCapture?`${e.lastCapture.mode} \xB7 ${e.lastCapture.width} \xD7 ${e.lastCapture.height} \xB7 ${new Date(e.lastCapture.time).toLocaleTimeString()}`:"None yet"),g("last-error",e.lastError?`${e.lastError.code}: ${e.lastError.message}`:"None");for(let a of["fast","stable"])document.getElementById(a).disabled=S||!e.connected||e.targetState!=="authorized";document.getElementById("disconnect").disabled=S||e.targetState==="none"}var oe={not_connected:"Not connected. Choose Connect and approve the matching code in your terminal.",searching:"Searching for local GazeSight\u2026",pending:"Pairing request pending.",waiting_approval:"Check that this code matches the one in your terminal.",connected:"Connected.",unavailable:"Connection unavailable. Run gazesight pair and try again.",expired:"Pairing expired. Try again.",reconnect_required:"Reconnect required."};function H(e,r){let a=document.getElementById("pairing-code");g("pairing-message",oe[e]),a.hidden=!r,a.textContent=r?`Verification code: ${r}`:""}document.getElementById("connect").addEventListener("click",async()=>{let e=document.getElementById("connect");e.disabled=!0;let r=await browser.storage.local.get(["port"]);await F(H,Number(r.port??32147)),e.disabled=!1,await h()});(async()=>typeof(await browser.storage.local.get(["token"])).token!="string"&&await G(H)&&await h())();for(let e of["select","disconnect","fast","stable","diagnostics"])document.getElementById(e).addEventListener("click",async()=>{if(!S){S=!0,document.querySelectorAll("button").forEach(r=>r.disabled=!0),g("feedback",e==="fast"||e==="stable"?"Capturing\u2026":"Working\u2026");try{if(e==="fast"&&!await browser.permissions.contains({permissions:["downloads"]})){await browser.windows.create({url:browser.runtime.getURL("permission.html?action=download"),type:"popup",focused:!0,width:600,height:700}),window.close();return}let r=await y(e);e==="diagnostics"&&(document.getElementById("diagnostics-panel").hidden=!1,g("diagnostics-output",JSON.stringify(r,null,2))),V(e==="disconnect"?"Target disconnected.":e==="select"?"Target selected.":e==="diagnostics"?"Diagnostics updated.":e==="fast"?`\u2713 Saved to Downloads/${r.filename}`:"Capture completed.",e==="fast")}catch(r){V(r instanceof Error?r.message:"Operation failed.")}finally{S=!1,document.querySelectorAll("button").forEach(r=>r.disabled=!1),await h().catch(r=>g("feedback",String(r)))}}});document.getElementById("copy-url").addEventListener("click",async()=>{let e=document.getElementById("url").textContent;if(!(!e||e==="No target selected"))try{await navigator.clipboard.writeText(e),g("feedback","URL copied.")}catch{g("feedback","Unable to copy URL. Select and copy it manually.")}});document.getElementById("background-toggle").addEventListener("click",async()=>{if((await y("status")).backgroundCapture.enabled){await y("background-disable"),await h();return}await browser.windows.create({url:browser.runtime.getURL("permission.html?action=background"),type:"popup",focused:!0,width:600,height:700}),window.close()});document.getElementById("continuous-toggle").addEventListener("click",async()=>{let e=await y("status");if(e.continuousAuthorization.enabled){await y("continuous-disable"),await h();return}if(e.continuousAuthorization.permissionGranted){await y("continuous-enable"),await h();return}await browser.windows.create({url:browser.runtime.getURL("permission.html?action=continuous"),type:"popup",focused:!0,width:600,height:700}),window.close()});browser.commands.getAll().then(e=>{let r=e.find(a=>a.name==="gazesight-select-target")?.shortcut;r&&g("shortcut",r)}).catch(()=>{});document.getElementById("settings").addEventListener("click",()=>void browser.runtime.openOptionsPage());h().catch(e=>g("feedback",String(e)));var ge=setInterval(()=>{S||h().catch(e=>g("feedback",String(e)))},2e3);window.addEventListener("pagehide",()=>clearInterval(ge),{once:!0});
|
package/dist/cli/index.js
CHANGED
|
@@ -102,7 +102,7 @@ function writeLocalConfig(path, value) {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
// packages/protocol/src/release.ts
|
|
105
|
-
var VERSION = "0.5.
|
|
105
|
+
var VERSION = "0.5.3";
|
|
106
106
|
|
|
107
107
|
// apps/cli/src/doctor.ts
|
|
108
108
|
import { z as z2 } from "zod";
|
|
@@ -120,18 +120,20 @@ function diagnosticRows(status, reachable = false, authenticated = false) {
|
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
name: "extension connected",
|
|
123
|
-
pass: !!status?.connected,
|
|
123
|
+
pass: !!status?.connected || Object.values(status?.connectedBrowsers ?? {}).some(Boolean),
|
|
124
124
|
action: status?.authorizedPairings ? "An extension is paired but disconnected. Start it and verify the configured bridge port." : "Open Firefox or Chrome, then click Connect to GazeSight in the extension."
|
|
125
125
|
},
|
|
126
126
|
{
|
|
127
127
|
name: "pairing",
|
|
128
|
-
|
|
128
|
+
// Pairing is durable authorization, while `paired` means a live
|
|
129
|
+
// WebSocket connection. An approved extension can be offline.
|
|
130
|
+
pass: authenticated && (status?.paired === true || (status?.authorizedPairings ?? 0) > 0),
|
|
129
131
|
action: "Run gazesight pair, click Connect to GazeSight, and approve the matching code."
|
|
130
132
|
},
|
|
131
133
|
{
|
|
132
134
|
name: "target selected",
|
|
133
135
|
pass: !!status && status.targetState !== "none",
|
|
134
|
-
action:
|
|
136
|
+
action: `Open your local preview in ${status?.activeTarget?.browser === "chrome" ? "Chrome" : "Firefox or Chrome"} and click the GazeSight icon.`
|
|
135
137
|
},
|
|
136
138
|
{
|
|
137
139
|
name: "capture permission",
|
|
@@ -165,7 +167,9 @@ var statusSchema = z2.object({
|
|
|
165
167
|
paired: z2.boolean(),
|
|
166
168
|
targetState: z2.enum(["none", "authorized", "reauthorization_required"]),
|
|
167
169
|
backgroundCapture: z2.object({ enabled: z2.boolean(), permissionGranted: z2.boolean() }).optional(),
|
|
168
|
-
authorizedPairings: z2.number().int().nonnegative().optional()
|
|
170
|
+
authorizedPairings: z2.number().int().nonnegative().optional(),
|
|
171
|
+
connectedBrowsers: z2.object({ firefox: z2.boolean().optional(), chrome: z2.boolean().optional() }).optional(),
|
|
172
|
+
activeTarget: z2.object({ browser: z2.enum(["firefox", "chrome"]).optional() }).nullable().optional()
|
|
169
173
|
});
|
|
170
174
|
|
|
171
175
|
// apps/cli/src/pair.ts
|
|
@@ -952,7 +956,7 @@ var PairingService = class {
|
|
|
952
956
|
}
|
|
953
957
|
listPending() {
|
|
954
958
|
this.expire();
|
|
955
|
-
return [...this.pending.values()].filter((item) => item.state === "pending").map(({ id, browser, extensionId, code, createdAt, expiresAt }) => ({ id, browser, extensionId, code, createdAt, expiresAt }));
|
|
959
|
+
return [...this.pending.values()].filter((item) => item.state === "pending").map(({ id, browser, extensionId, code, createdAt, expiresAt }) => ({ id, browser, extensionId, code, createdAt, expiresAt })).sort((a, b) => b.createdAt - a.createdAt);
|
|
956
960
|
}
|
|
957
961
|
listPairings() {
|
|
958
962
|
return this.pairings.map(({ id, browser, extensionId, origin, createdAt, revokedAt }) => ({ id, browser, extensionId, origin, createdAt, ...revokedAt ? { revokedAt } : {} }));
|
|
@@ -1420,7 +1424,10 @@ async function pairingFlow(config, configPath, revoke) {
|
|
|
1420
1424
|
const answer = (await rl.question("Approve this matching request? [y/N] ")).trim().toLowerCase();
|
|
1421
1425
|
const approved = answer === "y" || answer === "yes";
|
|
1422
1426
|
const result = await admin(config.port, config.token, approved ? "approve" : "reject", "POST", { id: request.id, code: request.code });
|
|
1423
|
-
if (!result.ok)
|
|
1427
|
+
if (!result.ok) {
|
|
1428
|
+
console.log("That request expired or was replaced. Checking for the latest request\u2026");
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1424
1431
|
if (approved) {
|
|
1425
1432
|
const deadline = Date.now() + 5e3;
|
|
1426
1433
|
let delivered = false;
|
|
@@ -1433,8 +1440,32 @@ async function pairingFlow(config, configPath, revoke) {
|
|
|
1433
1440
|
await new Promise((resolve3) => setTimeout(resolve3, 100));
|
|
1434
1441
|
}
|
|
1435
1442
|
if (!delivered) throw new Error("The approved credential was not delivered; keep the extension open and retry pairing.");
|
|
1436
|
-
console.log("Pairing approved and delivered.
|
|
1437
|
-
|
|
1443
|
+
console.log("Pairing approved and delivered.");
|
|
1444
|
+
console.log("Waiting for the extension to connect to this GazeSight bridge (up to 15 seconds)\u2026");
|
|
1445
|
+
const connectionDeadline = Date.now() + 15e3;
|
|
1446
|
+
let connected = false;
|
|
1447
|
+
while (Date.now() < connectionDeadline) {
|
|
1448
|
+
const status = await fetch(`http://127.0.0.1:${config.port}/gazesight/status`, {
|
|
1449
|
+
headers: headers(config.token),
|
|
1450
|
+
signal: AbortSignal.timeout(1500)
|
|
1451
|
+
}).catch(() => void 0);
|
|
1452
|
+
if (status?.ok) {
|
|
1453
|
+
const value = await status.json();
|
|
1454
|
+
if (value.connectedBrowsers?.[request.browser] === true) {
|
|
1455
|
+
connected = true;
|
|
1456
|
+
break;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
await new Promise((resolve3) => setTimeout(resolve3, 250));
|
|
1460
|
+
}
|
|
1461
|
+
if (connected)
|
|
1462
|
+
console.log("Extension connected. Pairing is ready.");
|
|
1463
|
+
else
|
|
1464
|
+
console.log(`Credential delivered, but ${request.browser} did not connect. Keep the extension installed and enabled, open its popup, verify its configured bridge port is ${config.port}, then click Connect to GazeSight again.`);
|
|
1465
|
+
} else {
|
|
1466
|
+
console.log("Pairing rejected. Waiting for another request\u2026");
|
|
1467
|
+
continue;
|
|
1468
|
+
}
|
|
1438
1469
|
return;
|
|
1439
1470
|
}
|
|
1440
1471
|
} finally {
|
|
@@ -1899,9 +1930,19 @@ Manual JSON import remains available under Advanced settings.`
|
|
|
1899
1930
|
if (args[0] === "doctor" && rows.some((row) => !row.pass))
|
|
1900
1931
|
process.exitCode = 1;
|
|
1901
1932
|
}
|
|
1902
|
-
} catch {
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1933
|
+
} catch (error) {
|
|
1934
|
+
const message = error instanceof Error ? error.message : "";
|
|
1935
|
+
if (args[0] === "pair" && [
|
|
1936
|
+
"Pairing administration unavailable.",
|
|
1937
|
+
"The pairing request expired or was already used.",
|
|
1938
|
+
"The approved credential was not delivered; keep the extension open and retry pairing."
|
|
1939
|
+
].includes(message)) {
|
|
1940
|
+
console.error(`Pairing failed \u2014 ${message}`);
|
|
1941
|
+
process.exitCode = 1;
|
|
1942
|
+
} else {
|
|
1943
|
+
console.error(
|
|
1944
|
+
"FAIL \u2014 Check the command/options, Node >=20, installed package, private configuration and port 1024\u201365535. Run gazesight --help. Secrets are redacted."
|
|
1945
|
+
);
|
|
1946
|
+
process.exitCode = 1;
|
|
1947
|
+
}
|
|
1907
1948
|
}
|