@ericmhalvorsen/aperture 0.2.1
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 +148 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +64 -0
- package/dist/client/handlers.d.ts +2 -0
- package/dist/client/handlers.js +171 -0
- package/dist/client/patches.d.ts +18 -0
- package/dist/client/patches.js +56 -0
- package/dist/client/storage.d.ts +5 -0
- package/dist/client/storage.js +31 -0
- package/dist/client/ui.d.ts +26 -0
- package/dist/client/ui.js +600 -0
- package/dist/client.d.ts +60 -0
- package/dist/client.js +435 -0
- package/dist/frameworks/next.d.ts +3 -0
- package/dist/frameworks/next.js +12 -0
- package/dist/frameworks/shared.d.ts +1 -0
- package/dist/frameworks/shared.js +61 -0
- package/dist/frameworks/vite.d.ts +10 -0
- package/dist/frameworks/vite.js +22 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +5 -0
- package/dist/mcp-server.d.ts +39 -0
- package/dist/mcp-server.js +237 -0
- package/dist/react.d.ts +8 -0
- package/dist/react.js +20 -0
- package/dist/register.d.ts +1 -0
- package/dist/register.js +2 -0
- package/dist/server.d.ts +25 -0
- package/dist/server.js +315 -0
- package/dist/tools.d.ts +165 -0
- package/dist/tools.js +161 -0
- package/dist/transports.d.ts +29 -0
- package/dist/transports.js +86 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +1 -0
- package/dist-browser/client.js +457 -0
- package/package.json +123 -0
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
var N=[],w=[];function V(){return N}function J(){return w}function Y(){let a=["log","warn","error","info","debug"];for(let e of a){let t=console[e];console[e]=(...r)=>{let i=r.map(o=>typeof o=="string"?o:JSON.stringify(o)).join(" ");N.push({level:e,message:i,timestamp:Date.now()}),N.length>500&&N.shift(),t(...r)}}}function K(){let a=window.fetch;window.fetch=async(...e)=>{let t={url:String(e[0]),method:"GET",start:Date.now(),end:0,status:0,responseText:""};e[1]&&(t.method=e[1].method||"GET");try{let r=await a(...e);return t.status=r.status,t.end=Date.now(),w.push(t),w.length>100&&w.shift(),r}catch(r){throw t.end=Date.now(),t.error=String(r),w.push(t),w.length>100&&w.shift(),r}}}var X={browser_dom_query:(a,{selector:e,includeHtml:t=!1})=>Array.from(document.querySelectorAll(String(e))).map(i=>({tag:i.tagName.toLowerCase(),text:i.textContent?.slice(0,200)||"",visible:!!i.offsetParent,attributes:Object.fromEntries(Array.from(i.attributes).map(o=>[o.name,o.value])),html:t?i.outerHTML.slice(0,500):void 0})),browser_network_requests:(a,{limit:e=20})=>J().slice(-Number(e)),browser_page_info:(a,{logLimit:e=20,logLevel:t="all"})=>{let r=V();return t!=="all"&&(r=r.filter(i=>i.level===t)),{url:window.location.href,title:document.title,width:window.innerWidth,height:window.innerHeight,scrollX:window.scrollX,scrollY:window.scrollY,userAgent:navigator.userAgent,logs:r.slice(-Number(e))}},browser_storage_get:(a,{type:e,key:t,prefix:r,name:i})=>{if(e==="localStorage"){let o={};if(t&&(o[String(t)]=localStorage.getItem(String(t))),r)for(let n=0;n<localStorage.length;n++){let l=localStorage.key(n);l?.startsWith(String(r))&&(o[l]=localStorage.getItem(l))}return o}if(e==="cookie"){let o={},n=document.cookie;if(n)for(let l of n.split(";")){let[s,p]=l.split("=").map(c=>c.trim());s&&(o[s]=decodeURIComponent(p||""))}if(i){let l=String(i);return{[l]:o[l]||null}}return o}return{error:`Unknown type: ${e}. Use 'localStorage' or 'cookie'.`}},browser_screenshot:async a=>{try{return{base64:(await a.captureScreenshotFromStream()).split(",")[1],format:"png"}}catch(e){return{error:e instanceof Error?e.message:String(e)}}},browser_evaluate:(a,{expression:e})=>{let t=window.eval(String(e));return{result:typeof t=="object"?JSON.stringify(t):String(t)}},browser_click:(a,{selector:e})=>{let t=document.querySelector(String(e));if(!t)return{error:`Element not found matching selector: ${e}`};t.focus();let r=["pointerdown","mousedown","pointerup","mouseup","click"];for(let i of r){let o=new MouseEvent(i,{bubbles:!0,cancelable:!0});t.dispatchEvent(o)}return{success:!0}},browser_type:(a,{selector:e,text:t})=>{let r=document.querySelector(String(e));if(!r)return{error:`Element not found matching selector: ${e}`};let i=r instanceof HTMLInputElement,o=r instanceof HTMLTextAreaElement;if(i||o){let n=i?HTMLInputElement.prototype:HTMLTextAreaElement.prototype,l=Object.getOwnPropertyDescriptor(n,"value")?.set;l?l.call(r,String(t)):r.value=String(t)}else if(r.isContentEditable)r.textContent=String(t);else return{error:"Element is not an input, textarea, or contenteditable."};return r.dispatchEvent(new Event("input",{bubbles:!0})),r.dispatchEvent(new Event("change",{bubbles:!0})),{success:!0}},browser_scroll:(a,{selector:e,x:t,y:r,scrollIntoView:i})=>{if(e){let o=document.querySelector(String(e));return o?i?(o.scrollIntoView({behavior:"smooth",block:"center",inline:"nearest"}),{success:!0}):(t!==void 0&&(o.scrollLeft=Number(t)),r!==void 0&&(o.scrollTop=Number(r)),{success:!0,scrollLeft:o.scrollLeft,scrollTop:o.scrollTop}):{error:`Element not found matching selector: ${e}`}}else{let o=t!==void 0?Number(t):window.scrollX,n=r!==void 0?Number(r):window.scrollY;return window.scrollTo({left:o,top:n,behavior:"smooth"}),{success:!0,scrollX:window.scrollX,scrollY:window.scrollY}}}};var u={get(a){if(typeof window>"u"||typeof localStorage>"u")return null;try{return localStorage.getItem(a)}catch{return null}},set(a,e){if(!(typeof window>"u"||typeof localStorage>"u"))try{localStorage.setItem(a,e)}catch{}},remove(a){if(!(typeof window>"u"||typeof localStorage>"u"))try{localStorage.removeItem(a)}catch{}}};var D=globalThis,Z=a=>a,P=D.trustedTypes,G=P?P.createPolicy("lit-html",{createHTML:a=>a}):void 0,ae="$lit$",v=`lit$${Math.random().toFixed(9).slice(2)}$`,oe="?"+v,ue=`<${oe}>`,_=D.document===void 0?{createTreeWalker:()=>({})}:document,k=()=>_.createComment(""),E=a=>a===null||typeof a!="object"&&typeof a!="function",j=Array.isArray,he=a=>j(a)||typeof a?.[Symbol.iterator]=="function",B=`[
|
|
2
|
+
\f\r]`,S=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Q=/-->/g,ee=/>/g,y=RegExp(`>|${B}(?:([^\\s"'>=/]+)(${B}*=${B}*(?:[^
|
|
3
|
+
\f\r"'\`<>=]|("|')|))|$)`,"g"),te=/'/g,re=/"/g,ne=/^(?:script|style|textarea|title)$/i,W=a=>(e,...t)=>({_$litType$:a,strings:e,values:t}),m=W(1),ye=W(2),xe=W(3),C=Symbol.for("lit-noChange"),h=Symbol.for("lit-nothing"),ie=new WeakMap,x=_.createTreeWalker(_,129);function se(a,e){if(!j(a)||!a.hasOwnProperty("raw"))throw Error("invalid template strings array");return G!==void 0?G.createHTML(e):e}var ge=(a,e)=>{let t=a.length-1,r=[],i,o=e===2?"<svg>":e===3?"<math>":"",n=S;for(let l=0;l<t;l++){let s=a[l],p,c,d=-1,f=0;for(;f<s.length&&(n.lastIndex=f,c=n.exec(s),c!==null);)f=n.lastIndex,n===S?c[1]==="!--"?n=Q:c[1]!==void 0?n=ee:c[2]!==void 0?(ne.test(c[2])&&(i=RegExp("</"+c[2],"g")),n=y):c[3]!==void 0&&(n=y):n===y?c[0]===">"?(n=i??S,d=-1):c[1]===void 0?d=-2:(d=n.lastIndex-c[2].length,p=c[1],n=c[3]===void 0?y:c[3]==='"'?re:te):n===re||n===te?n=y:n===Q||n===ee?n=S:(n=y,i=void 0);let b=n===y&&a[l+1].startsWith("/>")?" ":"";o+=n===S?s+ue:d>=0?(r.push(p),s.slice(0,d)+ae+s.slice(d)+v+b):s+v+(d===-2?l:b)}return[se(a,o+(a[t]||"<?>")+(e===2?"</svg>":e===3?"</math>":"")),r]},T=class a{constructor({strings:e,_$litType$:t},r){let i;this.parts=[];let o=0,n=0,l=e.length-1,s=this.parts,[p,c]=ge(e,t);if(this.el=a.createElement(p,r),x.currentNode=this.el.content,t===2||t===3){let d=this.el.content.firstChild;d.replaceWith(...d.childNodes)}for(;(i=x.nextNode())!==null&&s.length<l;){if(i.nodeType===1){if(i.hasAttributes())for(let d of i.getAttributeNames())if(d.endsWith(ae)){let f=c[n++],b=i.getAttribute(d).split(v),g=/([.?@])?(.*)/.exec(f);s.push({type:1,index:o,name:g[2],strings:b,ctor:g[1]==="."?I:g[1]==="?"?O:g[1]==="@"?U:$}),i.removeAttribute(d)}else d.startsWith(v)&&(s.push({type:6,index:o}),i.removeAttribute(d));if(ne.test(i.tagName)){let d=i.textContent.split(v),f=d.length-1;if(f>0){i.textContent=P?P.emptyScript:"";for(let b=0;b<f;b++)i.append(d[b],k()),x.nextNode(),s.push({type:2,index:++o});i.append(d[f],k())}}}else if(i.nodeType===8)if(i.data===oe)s.push({type:2,index:o});else{let d=-1;for(;(d=i.data.indexOf(v,d+1))!==-1;)s.push({type:7,index:o}),d+=v.length-1}o++}}static createElement(e,t){let r=_.createElement("template");return r.innerHTML=e,r}};function A(a,e,t=a,r){if(e===C)return e;let i=r!==void 0?t._$Co?.[r]:t._$Cl,o=E(e)?void 0:e._$litDirective$;return i?.constructor!==o&&(i?._$AO?.(!1),o===void 0?i=void 0:(i=new o(a),i._$AT(a,t,r)),r!==void 0?(t._$Co??=[])[r]=i:t._$Cl=i),i!==void 0&&(e=A(a,i._$AS(a,e.values),i,r)),e}var L=class{constructor(e,t){this._$AV=[],this._$AN=void 0,this._$AD=e,this._$AM=t}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(e){let{el:{content:t},parts:r}=this._$AD,i=(e?.creationScope??_).importNode(t,!0);x.currentNode=i;let o=x.nextNode(),n=0,l=0,s=r[0];for(;s!==void 0;){if(n===s.index){let p;s.type===2?p=new M(o,o.nextSibling,this,e):s.type===1?p=new s.ctor(o,s.name,s.strings,this,e):s.type===6&&(p=new q(o,this,e)),this._$AV.push(p),s=r[++l]}n!==s?.index&&(o=x.nextNode(),n++)}return x.currentNode=_,i}p(e){let t=0;for(let r of this._$AV)r!==void 0&&(r.strings!==void 0?(r._$AI(e,r,t),t+=r.strings.length-2):r._$AI(e[t])),t++}},M=class a{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(e,t,r,i){this.type=2,this._$AH=h,this._$AN=void 0,this._$AA=e,this._$AB=t,this._$AM=r,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let e=this._$AA.parentNode,t=this._$AM;return t!==void 0&&e?.nodeType===11&&(e=t.parentNode),e}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(e,t=this){e=A(this,e,t),E(e)?e===h||e==null||e===""?(this._$AH!==h&&this._$AR(),this._$AH=h):e!==this._$AH&&e!==C&&this._(e):e._$litType$!==void 0?this.$(e):e.nodeType!==void 0?this.T(e):he(e)?this.k(e):this._(e)}O(e){return this._$AA.parentNode.insertBefore(e,this._$AB)}T(e){this._$AH!==e&&(this._$AR(),this._$AH=this.O(e))}_(e){this._$AH!==h&&E(this._$AH)?this._$AA.nextSibling.data=e:this.T(_.createTextNode(e)),this._$AH=e}$(e){let{values:t,_$litType$:r}=e,i=typeof r=="number"?this._$AC(e):(r.el===void 0&&(r.el=T.createElement(se(r.h,r.h[0]),this.options)),r);if(this._$AH?._$AD===i)this._$AH.p(t);else{let o=new L(i,this),n=o.u(this.options);o.p(t),this.T(n),this._$AH=o}}_$AC(e){let t=ie.get(e.strings);return t===void 0&&ie.set(e.strings,t=new T(e)),t}k(e){j(this._$AH)||(this._$AH=[],this._$AR());let t=this._$AH,r,i=0;for(let o of e)i===t.length?t.push(r=new a(this.O(k()),this.O(k()),this,this.options)):r=t[i],r._$AI(o),i++;i<t.length&&(this._$AR(r&&r._$AB.nextSibling,i),t.length=i)}_$AR(e=this._$AA.nextSibling,t){for(this._$AP?.(!1,!0,t);e!==this._$AB;){let r=Z(e).nextSibling;Z(e).remove(),e=r}}setConnected(e){this._$AM===void 0&&(this._$Cv=e,this._$AP?.(e))}},$=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(e,t,r,i,o){this.type=1,this._$AH=h,this._$AN=void 0,this.element=e,this.name=t,this._$AM=i,this.options=o,r.length>2||r[0]!==""||r[1]!==""?(this._$AH=Array(r.length-1).fill(new String),this.strings=r):this._$AH=h}_$AI(e,t=this,r,i){let o=this.strings,n=!1;if(o===void 0)e=A(this,e,t,0),n=!E(e)||e!==this._$AH&&e!==C,n&&(this._$AH=e);else{let l=e,s,p;for(e=o[0],s=0;s<o.length-1;s++)p=A(this,l[r+s],t,s),p===C&&(p=this._$AH[s]),n||=!E(p)||p!==this._$AH[s],p===h?e=h:e!==h&&(e+=(p??"")+o[s+1]),this._$AH[s]=p}n&&!i&&this.j(e)}j(e){e===h?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,e??"")}},I=class extends ${constructor(){super(...arguments),this.type=3}j(e){this.element[this.name]=e===h?void 0:e}},O=class extends ${constructor(){super(...arguments),this.type=4}j(e){this.element.toggleAttribute(this.name,!!e&&e!==h)}},U=class extends ${constructor(e,t,r,i,o){super(e,t,r,i,o),this.type=5}_$AI(e,t=this){if((e=A(this,e,t,0)??h)===C)return;let r=this._$AH,i=e===h&&r!==h||e.capture!==r.capture||e.once!==r.once||e.passive!==r.passive,o=e!==h&&(r===h||i);i&&this.element.removeEventListener(this.name,this,r),o&&this.element.addEventListener(this.name,this,e),this._$AH=e}handleEvent(e){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,e):this._$AH.handleEvent(e)}},q=class{constructor(e,t,r){this.element=e,this.type=6,this._$AN=void 0,this._$AM=t,this.options=r}get _$AU(){return this._$AM._$AU}_$AI(e){A(this,e)}};var be=D.litHtmlPolyfillSupport;be?.(T,M),(D.litHtmlVersions??=[]).push("3.3.3");var z=(a,e,t)=>{let r=t?.renderBefore??e,i=r._$litPart$;if(i===void 0){let o=t?.renderBefore??null;r._$litPart$=i=new M(e.insertBefore(k(),o),o,void 0,t??{})}return i._$AI(a),i};function le(){if(typeof document>"u")return;let a="aperture-styles";if(document.getElementById(a))return;let e=document.createElement("style");e.id=a,e.textContent=`
|
|
4
|
+
:root {
|
|
5
|
+
--ap-bg: #0f0f10;
|
|
6
|
+
--ap-bg-glass: rgba(15, 15, 16, 0.92);
|
|
7
|
+
--ap-border: rgba(255, 255, 255, 0.10);
|
|
8
|
+
--ap-text: #f3f4f6;
|
|
9
|
+
--ap-text-secondary: #9ca3af;
|
|
10
|
+
--ap-text-muted: #6b7280;
|
|
11
|
+
--ap-accent: #6366f1;
|
|
12
|
+
--ap-accent-hover: #4f46e5;
|
|
13
|
+
--ap-btn-deny-bg: rgba(255, 255, 255, 0.06);
|
|
14
|
+
--ap-btn-deny-border: rgba(255, 255, 255, 0.12);
|
|
15
|
+
--ap-btn-deny-text: #d1d5db;
|
|
16
|
+
--ap-warning-bg: rgba(239, 68, 68, 0.10);
|
|
17
|
+
--ap-warning-border: rgba(239, 68, 68, 0.25);
|
|
18
|
+
--ap-warning-text: #fca5a5;
|
|
19
|
+
--ap-shadow: 0 24px 64px rgba(0, 0, 0, 0.50);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@media (prefers-color-scheme: light) {
|
|
23
|
+
:root {
|
|
24
|
+
--ap-bg: #ffffff;
|
|
25
|
+
--ap-bg-glass: rgba(255, 255, 255, 0.96);
|
|
26
|
+
--ap-border: rgba(0, 0, 0, 0.10);
|
|
27
|
+
--ap-text: #111827;
|
|
28
|
+
--ap-text-secondary: #4b5563;
|
|
29
|
+
--ap-text-muted: #9ca3af;
|
|
30
|
+
--ap-btn-deny-bg: rgba(0, 0, 0, 0.04);
|
|
31
|
+
--ap-btn-deny-border: rgba(0, 0, 0, 0.10);
|
|
32
|
+
--ap-btn-deny-text: #374151;
|
|
33
|
+
--ap-warning-bg: rgba(239, 68, 68, 0.06);
|
|
34
|
+
--ap-warning-border: rgba(239, 68, 68, 0.18);
|
|
35
|
+
--ap-warning-text: #b91c1c;
|
|
36
|
+
--ap-shadow: 0 24px 64px rgba(0, 0, 0, 0.15);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#aperture-badge,
|
|
41
|
+
#aperture-dialog-overlay,
|
|
42
|
+
#aperture-dialog,
|
|
43
|
+
#aperture-dialog .aperture-header,
|
|
44
|
+
#aperture-dialog .aperture-icon,
|
|
45
|
+
#aperture-dialog .aperture-title-container,
|
|
46
|
+
#aperture-dialog .aperture-title,
|
|
47
|
+
#aperture-dialog .aperture-subtitle,
|
|
48
|
+
#aperture-dialog .aperture-body,
|
|
49
|
+
#aperture-dialog .aperture-list,
|
|
50
|
+
#aperture-dialog .aperture-list li,
|
|
51
|
+
#aperture-dialog .aperture-options,
|
|
52
|
+
#aperture-dialog .aperture-checkbox-label,
|
|
53
|
+
#aperture-dialog .aperture-checkbox-label input,
|
|
54
|
+
#aperture-dialog .aperture-checkbox-desc,
|
|
55
|
+
#aperture-dialog .aperture-warning-box,
|
|
56
|
+
#aperture-dialog .aperture-footer,
|
|
57
|
+
#aperture-dialog .aperture-btn {
|
|
58
|
+
all: initial;
|
|
59
|
+
box-sizing: border-box;
|
|
60
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
#aperture-badge {
|
|
64
|
+
position: fixed;
|
|
65
|
+
bottom: 12px;
|
|
66
|
+
right: 12px;
|
|
67
|
+
z-index: 2147483646;
|
|
68
|
+
display: flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
gap: 8px;
|
|
71
|
+
padding: 6px 12px;
|
|
72
|
+
border-radius: 20px;
|
|
73
|
+
background: var(--ap-bg-glass);
|
|
74
|
+
backdrop-filter: blur(12px);
|
|
75
|
+
-webkit-backdrop-filter: blur(12px);
|
|
76
|
+
border: 1px solid var(--ap-border);
|
|
77
|
+
color: var(--ap-text);
|
|
78
|
+
font-size: 11px;
|
|
79
|
+
font-weight: 500;
|
|
80
|
+
box-shadow: var(--ap-shadow);
|
|
81
|
+
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
user-select: none;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#aperture-badge:hover {
|
|
87
|
+
transform: translateY(-2px);
|
|
88
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.30);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#aperture-badge .dot {
|
|
92
|
+
width: 8px;
|
|
93
|
+
height: 8px;
|
|
94
|
+
border-radius: 50%;
|
|
95
|
+
transition: background-color 0.3s ease;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#aperture-badge .dot.connected {
|
|
99
|
+
background-color: #10b981;
|
|
100
|
+
box-shadow: 0 0 8px #10b981;
|
|
101
|
+
animation: aperture-pulse 2s infinite;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
#aperture-badge .dot.connecting {
|
|
105
|
+
background-color: #f59e0b;
|
|
106
|
+
box-shadow: 0 0 8px #f59e0b;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
#aperture-badge .dot.disconnected {
|
|
110
|
+
background-color: #ef4444;
|
|
111
|
+
box-shadow: 0 0 8px #ef4444;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
@keyframes aperture-pulse {
|
|
115
|
+
0% { transform: scale(1); opacity: 1; }
|
|
116
|
+
50% { transform: scale(1.2); opacity: 0.7; }
|
|
117
|
+
100% { transform: scale(1); opacity: 1; }
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#aperture-dialog-overlay {
|
|
121
|
+
position: fixed;
|
|
122
|
+
inset: 0;
|
|
123
|
+
background: rgba(0, 0, 0, 0.45);
|
|
124
|
+
backdrop-filter: blur(6px);
|
|
125
|
+
-webkit-backdrop-filter: blur(6px);
|
|
126
|
+
z-index: 2147483647;
|
|
127
|
+
display: flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
opacity: 0;
|
|
131
|
+
transition: opacity 0.2s ease;
|
|
132
|
+
color-scheme: light dark;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
#aperture-dialog {
|
|
136
|
+
background: var(--ap-bg-glass);
|
|
137
|
+
backdrop-filter: blur(20px);
|
|
138
|
+
-webkit-backdrop-filter: blur(20px);
|
|
139
|
+
border: 1px solid var(--ap-border);
|
|
140
|
+
border-radius: 16px;
|
|
141
|
+
width: 400px;
|
|
142
|
+
max-width: 92vw;
|
|
143
|
+
max-height: 90vh;
|
|
144
|
+
overflow-y: auto;
|
|
145
|
+
box-shadow: var(--ap-shadow);
|
|
146
|
+
padding: 24px;
|
|
147
|
+
color: var(--ap-text);
|
|
148
|
+
transform: scale(0.96);
|
|
149
|
+
transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
|
|
150
|
+
line-height: 1.5;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
#aperture-dialog-overlay.active {
|
|
154
|
+
opacity: 1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
#aperture-dialog-overlay.active #aperture-dialog {
|
|
158
|
+
transform: scale(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
#aperture-dialog .aperture-header {
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
gap: 14px;
|
|
165
|
+
margin-bottom: 20px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
#aperture-dialog .aperture-icon {
|
|
169
|
+
width: 42px;
|
|
170
|
+
height: 42px;
|
|
171
|
+
border-radius: 12px;
|
|
172
|
+
background: linear-gradient(135deg, var(--ap-accent), var(--ap-accent-hover));
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
justify-content: center;
|
|
176
|
+
font-size: 20px;
|
|
177
|
+
line-height: 1;
|
|
178
|
+
flex-shrink: 0;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#aperture-dialog .aperture-title-container {
|
|
182
|
+
display: flex;
|
|
183
|
+
flex-direction: column;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
#aperture-dialog .aperture-title {
|
|
187
|
+
font-size: 16px;
|
|
188
|
+
font-weight: 600;
|
|
189
|
+
color: var(--ap-text);
|
|
190
|
+
margin: 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
#aperture-dialog .aperture-subtitle {
|
|
194
|
+
font-size: 12px;
|
|
195
|
+
color: var(--ap-text-secondary);
|
|
196
|
+
margin: 2px 0 0 0;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
#aperture-dialog .aperture-body {
|
|
200
|
+
display: block;
|
|
201
|
+
font-size: 13px;
|
|
202
|
+
color: var(--ap-text-secondary);
|
|
203
|
+
margin-bottom: 20px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
#aperture-dialog .aperture-list {
|
|
207
|
+
display: block;
|
|
208
|
+
margin: 12px 0 0 24px;
|
|
209
|
+
padding: 0;
|
|
210
|
+
color: var(--ap-text-secondary);
|
|
211
|
+
list-style-type: disc;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#aperture-dialog .aperture-list li {
|
|
215
|
+
display: list-item;
|
|
216
|
+
color: inherit;
|
|
217
|
+
margin-bottom: 6px;
|
|
218
|
+
font-size: 13px;
|
|
219
|
+
line-height: 1.4;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#aperture-dialog .aperture-options {
|
|
223
|
+
display: flex;
|
|
224
|
+
flex-direction: column;
|
|
225
|
+
gap: 14px;
|
|
226
|
+
margin-bottom: 20px;
|
|
227
|
+
border-top: 1px solid var(--ap-border);
|
|
228
|
+
border-bottom: 1px solid var(--ap-border);
|
|
229
|
+
padding: 16px 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
#aperture-dialog .aperture-checkbox-label {
|
|
233
|
+
display: flex;
|
|
234
|
+
align-items: flex-start;
|
|
235
|
+
gap: 10px;
|
|
236
|
+
font-size: 13px;
|
|
237
|
+
color: var(--ap-text);
|
|
238
|
+
cursor: pointer;
|
|
239
|
+
user-select: none;
|
|
240
|
+
line-height: 1.4;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#aperture-dialog .aperture-checkbox-label input[type="checkbox"] {
|
|
244
|
+
margin-top: 2px;
|
|
245
|
+
width: 16px;
|
|
246
|
+
height: 16px;
|
|
247
|
+
accent-color: var(--ap-accent);
|
|
248
|
+
cursor: pointer;
|
|
249
|
+
flex-shrink: 0;
|
|
250
|
+
appearance: auto;
|
|
251
|
+
-webkit-appearance: checkbox;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
#aperture-dialog .aperture-checkbox-desc {
|
|
255
|
+
font-size: 11px;
|
|
256
|
+
color: var(--ap-text-muted);
|
|
257
|
+
margin-top: 2px;
|
|
258
|
+
display: block;
|
|
259
|
+
line-height: 1.35;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#aperture-dialog .aperture-warning-box {
|
|
263
|
+
background: var(--ap-warning-bg);
|
|
264
|
+
border: 1px solid var(--ap-warning-border);
|
|
265
|
+
border-radius: 8px;
|
|
266
|
+
padding: 10px 12px;
|
|
267
|
+
margin-top: 6px;
|
|
268
|
+
margin-left: 26px;
|
|
269
|
+
font-size: 12px;
|
|
270
|
+
color: var(--ap-warning-text);
|
|
271
|
+
display: none;
|
|
272
|
+
line-height: 1.4;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
#aperture-dialog .aperture-warning-box.visible {
|
|
276
|
+
display: block;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
#aperture-dialog .aperture-footer {
|
|
280
|
+
display: flex;
|
|
281
|
+
gap: 10px;
|
|
282
|
+
justify-content: flex-end;
|
|
283
|
+
flex-wrap: wrap;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
#aperture-dialog .aperture-btn {
|
|
287
|
+
display: inline-block;
|
|
288
|
+
padding: 8px 14px;
|
|
289
|
+
font-size: 13px;
|
|
290
|
+
font-weight: 500;
|
|
291
|
+
border-radius: 8px;
|
|
292
|
+
cursor: pointer;
|
|
293
|
+
transition: all 0.15s ease;
|
|
294
|
+
border: 1px solid transparent;
|
|
295
|
+
white-space: nowrap;
|
|
296
|
+
line-height: 1;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
#aperture-dialog .aperture-btn-deny {
|
|
300
|
+
background: var(--ap-btn-deny-bg);
|
|
301
|
+
color: var(--ap-btn-deny-text);
|
|
302
|
+
border-color: var(--ap-btn-deny-border);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
#aperture-dialog .aperture-btn-deny:hover {
|
|
306
|
+
background: var(--ap-btn-deny-text);
|
|
307
|
+
color: var(--ap-bg);
|
|
308
|
+
border-color: var(--ap-btn-deny-text);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
#aperture-dialog .aperture-btn-allow {
|
|
312
|
+
background: linear-gradient(135deg, var(--ap-accent), var(--ap-accent-hover));
|
|
313
|
+
color: #fff;
|
|
314
|
+
border-color: transparent;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
#aperture-dialog .aperture-btn-allow:hover {
|
|
318
|
+
transform: translateY(-1px);
|
|
319
|
+
box-shadow: 0 4px 12px rgba(99, 102, 241, 0.35);
|
|
320
|
+
}
|
|
321
|
+
`,document.head.appendChild(e)}function de(a){let e=document.createElement("div");e.id="aperture-dialog-overlay",document.body.appendChild(e);let t=()=>{e.classList.remove("active"),setTimeout(()=>{e.remove()},300),document.removeEventListener("keydown",r)},r=n=>{n.key==="Escape"&&(t(),a?.())};document.addEventListener("keydown",r);let i=n=>{n.target===e&&(t(),a?.())};return e.addEventListener("click",i),{overlay:e,cleanup:t,activate:()=>{setTimeout(()=>{e.classList.add("active")},10)}}}async function F(){try{return await navigator.mediaDevices.getDisplayMedia({video:{displaySurface:"browser"},audio:!1})}catch(a){return console.warn("[Aperture] Failed to acquire screen share stream for screenshots:",a),null}}function pe(a,e){return new Promise(t=>{if(typeof document>"u"){t({approved:!1,capabilities:[]});return}let{overlay:r,cleanup:i,activate:o}=de(()=>{t({approved:!1,capabilities:[],dismissed:!0})}),n=!0,l=!0,s=!0,p=()=>{i(),t({approved:!1,capabilities:[],dismissed:!0})},c=()=>{i(),t({approved:!1,capabilities:[]})},d=async()=>{let b=s?864e5:36e5,g=["console","dom","network","storage"];if(l&&g.push("evaluate"),n){let H=await F();H&&(e({stream:H}),g.push("screenshot"))}i(),t({approved:!0,capabilities:g,ttlMs:b})};(()=>{let b=m`
|
|
322
|
+
<div id="aperture-dialog">
|
|
323
|
+
<div class="aperture-header">
|
|
324
|
+
<div class="aperture-icon">🔌</div>
|
|
325
|
+
<div class="aperture-title-container">
|
|
326
|
+
<h3 class="aperture-title">Agent Bridge</h3>
|
|
327
|
+
<p class="aperture-subtitle">${a} wants to access this tab</p>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
|
|
331
|
+
<div class="aperture-body">
|
|
332
|
+
By allowing, the agent will be able to:
|
|
333
|
+
<ul class="aperture-list">
|
|
334
|
+
<li>Read the current page URL, title, and visible text</li>
|
|
335
|
+
<li>Query the DOM and read element attributes / contents</li>
|
|
336
|
+
<li>View console logs (errors, warnings, info, debug)</li>
|
|
337
|
+
<li>Monitor network requests made by this page</li>
|
|
338
|
+
<li>Read localStorage and cookies for this origin</li>
|
|
339
|
+
${n?m`<li id="aperture-perm-screenshot">Capture screenshots of the page</li>`:""}
|
|
340
|
+
${l?m`<li id="aperture-perm-eval">Execute arbitrary JavaScript in this page</li>`:""}
|
|
341
|
+
</ul>
|
|
342
|
+
</div>
|
|
343
|
+
|
|
344
|
+
<div class="aperture-options">
|
|
345
|
+
<label class="aperture-checkbox-label">
|
|
346
|
+
<input
|
|
347
|
+
type="checkbox"
|
|
348
|
+
id="aperture-allow-screenshot"
|
|
349
|
+
.checked=${n}
|
|
350
|
+
@change=${g=>{n=g.target.checked}}
|
|
351
|
+
/>
|
|
352
|
+
<div>
|
|
353
|
+
<strong>Allow screenshot capture</strong>
|
|
354
|
+
<div class="aperture-checkbox-desc">Requests browser tab/screen sharing for live views</div>
|
|
355
|
+
</div>
|
|
356
|
+
</label>
|
|
357
|
+
|
|
358
|
+
<label class="aperture-checkbox-label">
|
|
359
|
+
<input
|
|
360
|
+
type="checkbox"
|
|
361
|
+
id="aperture-allow-eval"
|
|
362
|
+
.checked=${l}
|
|
363
|
+
@change=${g=>{l=g.target.checked}}
|
|
364
|
+
/>
|
|
365
|
+
<div>
|
|
366
|
+
<strong>Allow JavaScript evaluation</strong>
|
|
367
|
+
<div class="aperture-checkbox-desc">Enables arbitrary JS execution in this page (dangerous)</div>
|
|
368
|
+
</div>
|
|
369
|
+
</label>
|
|
370
|
+
|
|
371
|
+
<label class="aperture-checkbox-label">
|
|
372
|
+
<input
|
|
373
|
+
type="checkbox"
|
|
374
|
+
id="aperture-remember-24h"
|
|
375
|
+
.checked=${s}
|
|
376
|
+
@change=${g=>{s=g.target.checked}}
|
|
377
|
+
/>
|
|
378
|
+
<div>
|
|
379
|
+
<strong>Trust this device for 24 hours</strong>
|
|
380
|
+
<div class="aperture-checkbox-desc">Otherwise approval resets after 1 hour</div>
|
|
381
|
+
</div>
|
|
382
|
+
</label>
|
|
383
|
+
|
|
384
|
+
<div id="aperture-eval-warning" class="aperture-warning-box ${l?"visible":""}">
|
|
385
|
+
⚠️ Warning: Allowing evaluation lets the agent run any command or access any sensitive data on this origin.
|
|
386
|
+
</div>
|
|
387
|
+
</div>
|
|
388
|
+
|
|
389
|
+
<div class="aperture-footer">
|
|
390
|
+
<button id="aperture-btn-dismiss" class="aperture-btn aperture-btn-deny" @click=${p}>Dismiss</button>
|
|
391
|
+
<button id="aperture-btn-deny" class="aperture-btn aperture-btn-deny" @click=${c}>Deny</button>
|
|
392
|
+
<button id="aperture-btn-allow" class="aperture-btn aperture-btn-allow" @click=${d}>Allow for this session</button>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
`;z(b,r)})(),o()})}function ce(a){if(typeof document>"u"||document.getElementById("aperture-dialog-overlay"))return;let{overlay:e,cleanup:t}=de(),i=navigator.platform.toLowerCase().includes("mac")?"Cmd+Shift+A":"Ctrl+Shift+A",o=()=>t(),n=()=>{a.revokeApproval(),a.onApprovalStateChange({approved:!1,capabilities:[],stream:null}),t()},l=()=>{a.isBadgeHidden()?a.showBadge():a.hideBadgeFor24h(),t()};(()=>{let p=a.wsReadyState===WebSocket.OPEN?"Connected":"Disconnected",c=a.denied?"Denied":a.approved?"Approved":"Pending Approval",d=a.capabilities.includes("screenshot"),f=a.capabilities.includes("evaluate"),g=a.isBadgeHidden()?"Show badge":"Hide badge for 24 hours",H=m`
|
|
396
|
+
<div id="aperture-dialog">
|
|
397
|
+
<div class="aperture-header">
|
|
398
|
+
<div class="aperture-icon">⚙️</div>
|
|
399
|
+
<div class="aperture-title-container">
|
|
400
|
+
<h3 class="aperture-title">Agent Bridge</h3>
|
|
401
|
+
<p class="aperture-subtitle">${a.approved?"Session active":"Waiting for approval"}</p>
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
|
|
405
|
+
<div class="aperture-body">
|
|
406
|
+
<div style="margin-bottom: 12px; display: flex; justify-content: space-between; font-size: 13px;">
|
|
407
|
+
<span>Connection:</span>
|
|
408
|
+
<strong style="color: ${p==="Connected"?"#10b981":"#ef4444"};">${p}</strong>
|
|
409
|
+
</div>
|
|
410
|
+
<div style="margin-bottom: 12px; display: flex; justify-content: space-between; font-size: 13px;">
|
|
411
|
+
<span>Status:</span>
|
|
412
|
+
<strong style="color: ${c==="Approved"?"#10b981":c==="Denied"?"#ef4444":"#f59e0b"};">${c}</strong>
|
|
413
|
+
</div>
|
|
414
|
+
|
|
415
|
+
${a.approved?m`
|
|
416
|
+
<div style="margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--ap-border);">
|
|
417
|
+
<div style="font-size: 12px; color: var(--ap-text-muted); margin-bottom: 8px;">Enabled capabilities:</div>
|
|
418
|
+
<ul style="font-size: 13px; margin: 0; padding-left: 20px; color: var(--ap-text);">
|
|
419
|
+
<li>Console logs</li>
|
|
420
|
+
<li>DOM queries</li>
|
|
421
|
+
<li>Network requests</li>
|
|
422
|
+
<li>Storage access</li>
|
|
423
|
+
${d?m`<li>Screenshots</li>`:""}
|
|
424
|
+
${f?m`<li>JavaScript evaluation</li>`:""}
|
|
425
|
+
</ul>
|
|
426
|
+
</div>
|
|
427
|
+
`:""}
|
|
428
|
+
</div>
|
|
429
|
+
|
|
430
|
+
<div class="aperture-footer">
|
|
431
|
+
${a.approved?m`
|
|
432
|
+
<button id="aperture-status-btn-revoke" class="aperture-btn aperture-btn-deny" @click=${n}>Revoke</button>
|
|
433
|
+
<button id="aperture-status-btn-close" class="aperture-btn aperture-btn-allow" @click=${o}>Close</button>
|
|
434
|
+
`:m`
|
|
435
|
+
<div style="width: 100%; text-align: center; color: var(--ap-text-muted); font-size: 13px;">
|
|
436
|
+
Waiting for agent connection...
|
|
437
|
+
</div>
|
|
438
|
+
`}
|
|
439
|
+
</div>
|
|
440
|
+
|
|
441
|
+
<div style="margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--ap-border); text-align: center;">
|
|
442
|
+
<button id="aperture-status-btn-hide" class="aperture-btn aperture-btn-deny" style="width: 100%;" @click=${l}>${g}</button>
|
|
443
|
+
<div style="margin-top: 8px; font-size: 11px; color: var(--ap-text-muted);">
|
|
444
|
+
Re-open with <kbd style="font-family: monospace; background: var(--ap-btn-deny-bg); border: 1px solid var(--ap-btn-deny-border); border-radius: 4px; padding: 1px 4px; font-size: 10px;">${i}</kbd>
|
|
445
|
+
</div>
|
|
446
|
+
</div>
|
|
447
|
+
</div>
|
|
448
|
+
`;z(H,e)})(),setTimeout(()=>{e.classList.add("active")},10)}var R=class{ws=null;config;approved=!1;denied=!1;capabilities=[];screenCaptureStream=null;badgeElement=null;focusListenersAdded=!1;constructor(e){this.config=e,window.__apertureInstance__=this,le(),Y(),K(),this.loadCachedApproval(),this.registerKeyboardShortcut(),typeof window<"u"&&window.addEventListener("beforeunload",()=>{this.stopScreenCapture()})}registerKeyboardShortcut(){typeof document>"u"||document.addEventListener("keydown",e=>{(navigator.platform.toLowerCase().includes("mac")?e.metaKey:e.ctrlKey)&&e.shiftKey&&(e.key==="a"||e.key==="A")&&(e.preventDefault(),this.openStatusDialog())})}isBadgeHidden(){let e=u.get("aperture_badge_hidden_until");return e?Date.now()<Number(e):!1}hideBadgeFor24h(){let e=String(Date.now()+864e5);u.set("aperture_badge_hidden_until",e),this.badgeElement&&(this.badgeElement.remove(),this.badgeElement=null)}showBadge(){if(u.remove("aperture_badge_hidden_until"),this.ws){let e=this.ws.readyState===WebSocket.OPEN?"connected":"connecting";this.updateBadge(e)}}loadCachedApproval(){let e=u.get("aperture_approved"),t=u.get("aperture_approved_at"),r=u.get("aperture_ttl_ms"),i=3600*1e3,o=r?Number(r):i,n=t?Date.now()-Number(t)>o:!0;e==="true"&&!n?(this.approved=!0,this.denied=!1,this.capabilities=JSON.parse(u.get("aperture_capabilities")||"[]")):e==="false"&&(this.denied=!0,this.approved=!1),n&&(u.remove("aperture_approved"),u.remove("aperture_approved_at"),u.remove("aperture_capabilities"),u.remove("aperture_ttl_ms"))}saveApproval(e,t,r){e?(u.set("aperture_approved","true"),u.set("aperture_approved_at",String(Date.now())),u.set("aperture_capabilities",JSON.stringify(t)),r&&u.set("aperture_ttl_ms",String(r))):(u.set("aperture_approved","false"),u.remove("aperture_approved_at"),u.remove("aperture_capabilities"),u.remove("aperture_ttl_ms"))}revokeApproval(){u.remove("aperture_approved"),u.remove("aperture_approved_at"),u.remove("aperture_capabilities"),u.remove("aperture_ttl_ms"),this.approved=!1,this.denied=!1,this.capabilities=[]}connect(){let e=new URL("/mcp",this.config.serverUrl);e.searchParams.set("type","browser"),this.updateBadge("connecting"),this.ws=new WebSocket(e.toString()),this.ws.onopen=()=>{let t=this.config.customTools?Object.entries(this.config.customTools).map(([r,i])=>({name:r,description:i.description,inputSchema:i.inputSchema})):[];this.send({type:"register",url:window.location.href,title:document.title,customTools:t}),console.log("[Aperture] Connected to server"),this.updateBadge("connected"),this.approved&&this.send({type:"approval",approved:this.approved,capabilities:this.capabilities}),this.reportFocusState(),typeof window<"u"&&!this.focusListenersAdded&&(this.focusListenersAdded=!0,window.addEventListener("focus",()=>this.reportFocusState()),window.addEventListener("blur",()=>this.reportFocusState()))},this.ws.onmessage=async t=>{try{let r=JSON.parse(t.data);r.type==="tool_call"?await this.handleToolCall(r):r.type==="agent_connected"&&await this.getOrWaitApproval()}catch{}},this.ws.onclose=()=>{console.log("[Aperture] Disconnected. Retrying in 3s..."),this.updateBadge("disconnected"),this.stopScreenCapture(),setTimeout(()=>this.connect(),3e3)}}disconnect(){this.ws&&(this.ws.onclose=null,this.ws.close(),this.ws=null),this.stopScreenCapture(),this.badgeElement&&(this.badgeElement.remove(),this.badgeElement=null)}reportFocusState(){if(typeof document>"u")return;let e=document.hasFocus();this.send({type:"focus",focused:e})}send(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}updateBadge(e){if(typeof document>"u")return;if(this.isBadgeHidden()){this.badgeElement&&(this.badgeElement.remove(),this.badgeElement=null);return}if(!this.badgeElement){this.badgeElement=document.createElement("div"),this.badgeElement.id="aperture-badge",this.badgeElement.title="Manage Aperture session (Ctrl+Shift+A)";let r=document.createElement("span");r.className="dot",this.badgeElement.appendChild(r),this.badgeElement.addEventListener("click",()=>{this.openStatusDialog()}),document.body.appendChild(this.badgeElement)}let t=this.badgeElement.querySelector(".dot");t&&(t.className=`dot ${e}`)}async handleToolCall(e){if(this.denied){this.send({type:"result",requestId:e.requestId,result:{error:"User denied browser access"}});return}if(!this.approved&&(await this.getOrWaitApproval(),!this.approved)){this.send({type:"result",requestId:e.requestId,result:{error:this.denied?"User denied browser access":"User dismissed the approval request"}});return}let t=X[e.tool],r=this.config.customTools?.[e.tool]?.handler,i=t||r;if(!i){this.send({type:"result",requestId:e.requestId,result:{error:`Unknown tool: ${e.tool}`}});return}try{let o=await i(this,e.args);this.send({type:"result",requestId:e.requestId,result:o})}catch(o){this.send({type:"result",requestId:e.requestId,result:{error:o instanceof Error?o.message:String(o)}})}}approvalPendingPromise=null;getOrWaitApproval(){return this.approved||this.denied?Promise.resolve():this.approvalPendingPromise?this.approvalPendingPromise:(this.approvalPendingPromise=(async()=>{let e=await this.getApproval("MCP Agent");e.dismissed||(this.approved=e.approved,this.denied=!e.approved,this.capabilities=e.capabilities,this.saveApproval(this.approved,this.capabilities,e.ttlMs),this.send({type:"approval",approved:this.approved,capabilities:this.capabilities}))})(),this.approvalPendingPromise.finally(()=>{this.approvalPendingPromise=null}),this.approvalPendingPromise)}async getApproval(e){return this.config.onApprovalRequest?{...await this.config.onApprovalRequest(e),dismissed:!1}:pe(e,t=>{t.stream!==void 0&&(this.screenCaptureStream=t.stream)})}async captureScreenshotFromStream(){if(!this.screenCaptureStream?.active){if(!this.approved||!this.capabilities.includes("screenshot"))throw new Error("Screenshot access was not granted. Please approve the connection with screenshot capability enabled.");let n=await this.requestScreenCapture();if(!n)throw new Error("Failed to acquire screen capture. Please try again or re-approve the connection.");this.screenCaptureStream=n}if(!this.screenCaptureStream.getVideoTracks()[0])throw new Error("No video tracks found in screen capture stream.");let t=document.createElement("video");t.srcObject=this.screenCaptureStream,t.autoplay=!0,t.playsInline=!0,t.muted=!0,await new Promise(n=>{t.onloadedmetadata=()=>n(null)}),await t.play().catch(()=>null),await new Promise(n=>{typeof t.requestVideoFrameCallback=="function"?(t.requestVideoFrameCallback(()=>n()),setTimeout(()=>n(),1e3)):setTimeout(()=>n(),300)});let r=document.createElement("canvas");r.width=t.videoWidth||800,r.height=t.videoHeight||600;let i=r.getContext("2d");if(!i)throw new Error("Could not get 2D context from canvas");i.drawImage(t,0,0);let o=r.toDataURL("image/png");return t.srcObject=null,t.load(),o}stopScreenCapture(){if(this.screenCaptureStream){for(let e of this.screenCaptureStream.getTracks())e.stop();this.screenCaptureStream=null}}setMediaStream(e){this.screenCaptureStream=e}async requestScreenCapture(){return F()}openStatusDialog(){ce({wsReadyState:this.ws?.readyState??WebSocket.CLOSED,approved:this.approved,denied:this.denied,capabilities:this.capabilities,isBadgeHidden:()=>this.isBadgeHidden(),showBadge:()=>this.showBadge(),hideBadgeFor24h:()=>this.hideBadgeFor24h(),revokeApproval:()=>this.revokeApproval(),onApprovalStateChange:e=>{this.approved=e.approved,e.approved?this.denied=!1:this.denied=!0,this.capabilities=e.capabilities,e.stream!==void 0&&(e.stream===null?this.stopScreenCapture():this.screenCaptureStream=e.stream),this.saveApproval(this.approved,this.capabilities),this.send({type:"approval",approved:this.approved,capabilities:this.capabilities})}})}};function Te(a){if(typeof window>"u"||!(location.hostname==="localhost"||location.hostname==="127.0.0.1"||location.hostname.endsWith(".localhost")||!!window.__vite_inject__))return;let t=a?.port||window.__APERTURE_PORT__||3456,r=a?.serverUrl||`ws://localhost:${t}`,i=window.__apertureInstance__;i&&typeof i.disconnect=="function"&&i.disconnect();let o=new R({serverUrl:r,customTools:a?.customTools});return o.connect(),window.__apertureInstance__=o,o}typeof window<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"||location.hostname.endsWith(".localhost")||window.__vite_inject__)&&setTimeout(()=>{if(!window.__apertureInstance__){let e=window.__APERTURE_PORT__||3456,t=window.__APERTURE_URL__||`ws://localhost:${e}`;console.log("[Aperture] No manual initialization detected. Auto-connecting...");let r=new R({serverUrl:t});r.connect(),window.__apertureInstance__=r}},500);export{R as ApertureClient,Te as initAperture};
|
|
449
|
+
/*! Bundled license information:
|
|
450
|
+
|
|
451
|
+
lit-html/node/lit-html.js:
|
|
452
|
+
(**
|
|
453
|
+
* @license
|
|
454
|
+
* Copyright 2017 Google LLC
|
|
455
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
456
|
+
*)
|
|
457
|
+
*/
|
package/package.json
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ericmhalvorsen/aperture",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Browser-to-agent bridge for AI agents. Auto-connects your dev browser to any MCP-capable agent.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Eric M. Halvorsen",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ericmhalvorsen/aperture.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/ericmhalvorsen/aperture#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/ericmhalvorsen/aperture/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"browser",
|
|
18
|
+
"ai",
|
|
19
|
+
"agent",
|
|
20
|
+
"devtools",
|
|
21
|
+
"debugging",
|
|
22
|
+
"claude",
|
|
23
|
+
"cursor",
|
|
24
|
+
"opencode"
|
|
25
|
+
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18"
|
|
28
|
+
},
|
|
29
|
+
"type": "module",
|
|
30
|
+
"main": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./react": {
|
|
38
|
+
"types": "./dist/react.d.ts",
|
|
39
|
+
"default": "./dist/react.js"
|
|
40
|
+
},
|
|
41
|
+
"./client": {
|
|
42
|
+
"types": "./dist/client.d.ts",
|
|
43
|
+
"default": "./dist/client.js"
|
|
44
|
+
},
|
|
45
|
+
"./server": {
|
|
46
|
+
"types": "./dist/server.d.ts",
|
|
47
|
+
"default": "./dist/server.js"
|
|
48
|
+
},
|
|
49
|
+
"./register": {
|
|
50
|
+
"types": "./dist/register.d.ts",
|
|
51
|
+
"default": "./dist/register.js"
|
|
52
|
+
},
|
|
53
|
+
"./next": {
|
|
54
|
+
"types": "./dist/frameworks/next.d.ts",
|
|
55
|
+
"default": "./dist/frameworks/next.js"
|
|
56
|
+
},
|
|
57
|
+
"./vite": {
|
|
58
|
+
"types": "./dist/frameworks/vite.d.ts",
|
|
59
|
+
"default": "./dist/frameworks/vite.js"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"bin": {
|
|
63
|
+
"aperture": "./dist/bin.js"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"build": "tsc -p tsconfig.build.json && pnpm exec tsup --config tsup.browser.ts",
|
|
67
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
68
|
+
"typecheck": "tsc --noEmit",
|
|
69
|
+
"lint": "biome lint .",
|
|
70
|
+
"format": "biome format --write .",
|
|
71
|
+
"check": "biome check .",
|
|
72
|
+
"knip": "knip",
|
|
73
|
+
"audit:deps": "pnpm audit",
|
|
74
|
+
"test": "vitest run",
|
|
75
|
+
"test:e2e": "playwright test",
|
|
76
|
+
"test:watch": "vitest",
|
|
77
|
+
"test:coverage": "vitest run --coverage",
|
|
78
|
+
"changeset": "changeset",
|
|
79
|
+
"version-packages": "changeset version",
|
|
80
|
+
"release": "pnpm build && changeset publish",
|
|
81
|
+
"publint": "publint",
|
|
82
|
+
"example": "cd samples/next-aperture && pnpm run dev"
|
|
83
|
+
},
|
|
84
|
+
"dependencies": {
|
|
85
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
86
|
+
"lit-html": "^3.3.3",
|
|
87
|
+
"picocolors": "^1.1.1",
|
|
88
|
+
"ws": "^8"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@biomejs/biome": "^2.4.16",
|
|
92
|
+
"@changesets/cli": "^2.31.0",
|
|
93
|
+
"@playwright/test": "^1.60.0",
|
|
94
|
+
"@types/node": "^20",
|
|
95
|
+
"@types/react": "^19",
|
|
96
|
+
"@types/ws": "^8",
|
|
97
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
98
|
+
"jsdom": "^29.1.1",
|
|
99
|
+
"knip": "^6.14.2",
|
|
100
|
+
"publint": "^0.3.21",
|
|
101
|
+
"tsup": "^8.5.1",
|
|
102
|
+
"typescript": "^5",
|
|
103
|
+
"vitest": "^4.1.7"
|
|
104
|
+
},
|
|
105
|
+
"peerDependencies": {
|
|
106
|
+
"react": ">=18",
|
|
107
|
+
"react-dom": ">=18"
|
|
108
|
+
},
|
|
109
|
+
"peerDependenciesMeta": {
|
|
110
|
+
"react": { "optional": true },
|
|
111
|
+
"react-dom": { "optional": true }
|
|
112
|
+
},
|
|
113
|
+
"files": [
|
|
114
|
+
"dist",
|
|
115
|
+
"dist-browser",
|
|
116
|
+
"README.md"
|
|
117
|
+
],
|
|
118
|
+
"pnpm": {
|
|
119
|
+
"overrides": {
|
|
120
|
+
"postcss": "^8.5.10"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|