claude-review-tool 0.1.0
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/LICENSE +21 -0
- package/README.md +17 -0
- package/dist/args.js +28 -0
- package/dist/args.js.map +1 -0
- package/dist/capture-schema.js +265 -0
- package/dist/capture-schema.js.map +1 -0
- package/dist/captures.js +86 -0
- package/dist/captures.js.map +1 -0
- package/dist/cli.js +137 -0
- package/dist/cli.js.map +1 -0
- package/dist/early.js +1 -0
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -0
- package/dist/http.js +82 -0
- package/dist/http.js.map +1 -0
- package/dist/init.js +52 -0
- package/dist/init.js.map +1 -0
- package/dist/inject.js +104 -0
- package/dist/inject.js.map +1 -0
- package/dist/intake-message.js +130 -0
- package/dist/intake-message.js.map +1 -0
- package/dist/intake.md +35 -0
- package/dist/overlay.js +215 -0
- package/dist/permissions.js +96 -0
- package/dist/permissions.js.map +1 -0
- package/dist/project.js +19 -0
- package/dist/project.js.map +1 -0
- package/dist/proxy.js +242 -0
- package/dist/proxy.js.map +1 -0
- package/dist/serve.js +114 -0
- package/dist/serve.js.map +1 -0
- package/dist/session-events.js +8 -0
- package/dist/session-events.js.map +1 -0
- package/dist/session-stub.js +232 -0
- package/dist/session-stub.js.map +1 -0
- package/dist/session.js +404 -0
- package/dist/session.js.map +1 -0
- package/dist/sessions.js +293 -0
- package/dist/sessions.js.map +1 -0
- package/dist/target.js +72 -0
- package/dist/target.js.map +1 -0
- package/dist/tasks.js +573 -0
- package/dist/tasks.js.map +1 -0
- package/package.json +51 -0
package/dist/overlay.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";(()=>{var Et=Object.defineProperty;var kt=(t,e,n)=>e in t?Et(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var m=(t,e,n)=>kt(t,typeof e!="symbol"?e+"":e,n);function St(t){return!("tag"in t)&&!("return"in t)&&typeof t.name=="string"}var Ct=Symbol.for("react.forward_ref"),Tt=Symbol.for("react.memo");function Le(t){for(let e of Object.keys(t))if(e.startsWith("__reactFiber$")||e.startsWith("__reactInternalInstance$"))return t[e];return null}function I(t){if(typeof t=="function"){let e=t,n=e.displayName||e.name;return n?{name:n,kind:e.prototype&&e.prototype.isReactComponent?"class":"function"}:null}if(typeof t=="object"&&t!==null){let e=t;if(e.$$typeof===Ct){let n=I(e.render),o=e.displayName||n?.name;return o?{name:o,kind:"forward_ref"}:null}if(e.$$typeof===Tt){let n=I(e.type),o=e.displayName||n?.name;return o?{name:o,kind:"memo"}:null}}return null}function ye(t){let e=t._debugSource;if(e&&typeof e.fileName=="string")return{file:e.fileName,line:typeof e.lineNumber=="number"?e.lineNumber:null,column:typeof e.columnNumber=="number"?e.columnNumber:null,via:"debug_source"};let n=t._debugStack,o=typeof n=="string"?n:n&&typeof n.stack=="string"?n.stack:null;return o?$e(o):null}var _t=/node_modules(?:[\/%_]|%2F)(?:react|react-dom|react-jsx-runtime|react-jsx-dev-runtime|react-server-dom-[\w-]+|scheduler|next)(?:[\/%_@.-]|$)|react-stack-(?:top|bottom)-frame|node:internal|<anonymous>/;function $e(t){for(let e of t.split(`
|
|
2
|
+
`)){let n=e.trim();if(!n||/^Error\b/.test(n)||n==="react-stack-top-frame")continue;let o=/^at (?:.*? )?\(?(.+?):(\d+):(\d+)\)?$/.exec(n)??/^(?:.*?@)?(.+?):(\d+):(\d+)$/.exec(n);if(!o)continue;let r=o[1];if(!_t.test(r))return{file:At(r),line:Number(o[2]),column:Number(o[3]),via:"owner_stack"}}return null}function At(t){let e=t;return e=e.replace(/^about:\/\/React\/[A-Za-z]+\//,""),e=e.replace(/^webpack-internal:\/\/\/(?:\([^)]*\)\/)?/,""),e=e.replace(/^webpack:\/\/[^/]*\//,""),e=e.replace(/^file:\/\/\/?/,""),e=e.replace(/^\.\//,""),e=e.replace(/\?\d+$/,""),e}function Mt(t){let e=t,n=null;for(;e&&!n;)n=Le(e),e=e.parentElement;if(!n)return null;let o=null,r=[],s=n._debugOwner,i=new Set;for(o=ye(n);s&&r.length<5&&!i.has(s);)if(i.add(s),St(s))s.name&&r.push({name:s.name,kind:"server"}),!o&&s.debugStack?.stack&&(o=$e(s.debugStack.stack)),s=s.owner;else{let a=I(s.elementType??s.type)??I(s.type);a&&r.push(a),o||(o=ye(s)),s=s._debugOwner}if(r.length)return{framework:"react",components:r,source:o};for(let a=n;a;a=a.return){o||(o=ye(a));let l=I(a.elementType??a.type)??I(a.type);if(l&&r.length<5&&r.push(l),r.length>=5&&o)break}return{framework:"react",components:r,source:o}}function Lt(t){let e=t;for(;e;){let n=e.__vueParentComponent;if(n){let r=[],s=null;for(let i=n;i&&r.length<5;i=i.parent){let a=i.type?.name||i.type?.__name;a&&r.push({name:a,kind:"function"}),!s&&i.type?.__file&&(s={file:i.type.__file,line:null,column:null,via:"vue_file"})}return{framework:"vue",components:r,source:s}}let o=e.__vue__;if(o){let r=[],s=null;for(let i=o;i&&r.length<5;i=i.$parent){let a=i.$options?.name||i.$options?._componentTag;a&&r.push({name:a,kind:"function"}),!s&&i.$options?.__file&&(s={file:i.$options.__file,line:null,column:null,via:"vue_file"})}return{framework:"vue",components:r,source:s}}e=e.parentElement}return null}function O(t){try{return Mt(t)??Lt(t)??{framework:"unknown",components:[],source:null}}catch{return{framework:"unknown",components:[],source:null}}}function Ne(t){return O(t).components[0]?.name??null}function X(){let t=window,e=[],n="unknown",o=null,r=null,s="unknown",i=t.__NEXT_DATA__,a=t.next;if(i||a||document.getElementById("__next")||document.querySelector("script[src*='/_next/']"))n="next",i&&e.push("window.__NEXT_DATA__"),a&&e.push("window.next"),document.getElementById("__next")&&e.push("#__next"),typeof a?.version=="string"&&(o=a.version),typeof i?.page=="string"&&(r=i.page),s="webpack";else if($t())n="react",e.push("__reactFiber$ on DOM nodes");else if(t.__VUE__||document.querySelector("[data-v-app]")||Nt()){n="vue",t.__VUE__&&e.push("window.__VUE__");let l=document.querySelector("[data-v-app]")?.__vue_app__;l?.version&&(o=l.version),typeof t.Vue=="object"&&t.Vue&&typeof t.Vue.version=="string"&&(o=t.Vue.version)}else document.querySelector("[ng-version]")?(n="angular",o=document.querySelector("[ng-version]")?.getAttribute("ng-version")??null,e.push("[ng-version]")):(t.__svelte||document.querySelector("[class*='svelte-']"))&&(n="svelte",e.push(t.__svelte?"window.__svelte":"svelte- class prefix"));return document.querySelector("script[src*='/@vite/client']")||t.__vite_plugin_react_preamble_installed__?(s="vite",e.push("/@vite/client")):(t.webpackChunk_N_E||t.webpackJsonp||Object.keys(t).some(l=>l.startsWith("webpackChunk")))&&(s="webpack",e.push("webpackChunk global")),n==="unknown"&&(t.React||document.querySelector("[data-reactroot]"))&&(n="react",e.push(t.React?"window.React":"[data-reactroot]")),{name:n,version:o,bundler:s,route:r,hints:e}}function $t(){let t=document.body?document.body.querySelectorAll("*"):[],e=Math.min(t.length,200);for(let n=0;n<e;n++)if(Le(t[n]))return!0;return!1}function Nt(){let t=document.body?document.body.querySelectorAll("*"):[],e=Math.min(t.length,200);for(let n=0;n<e;n++){let o=t[n];if(o.__vueParentComponent||o.__vue__||o.__vue_app__)return!0}return!1}var It="crt-host",Re=t=>typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(t):t.replace(/([^\w-])/g,"\\$1");function Pe(t){return!!(/^[a-zA-Z_-]*[0-9a-f]{6,}$/i.test(t)||/^(css|sc|jss|svelte|ng)-[\w-]+$/i.test(t)||/^_[\w-]*\d{3,}/.test(t)||/\d{4,}/.test(t)||/^:r[0-9a-z]+:$/.test(t))}function Ie(t){let e=t.getAttribute("id");if(!e||Pe(e))return null;let n=`#${Re(e)}`;return xe(n)?n:null}function xe(t){try{return document.querySelectorAll(t).length===1}catch{return!1}}function Rt(t){let e=t.localName,n=t.parentElement,o=Array.from(t.classList).filter(r=>!Pe(r));if(n){let s=Array.from(n.children).filter(i=>i.localName===e);if(s.length===1)return e;for(let i of o)if(s.filter(a=>a.classList.contains(i)).length===1)return`${e}.${Re(i)}`;return`${e}:nth-of-type(${s.indexOf(t)+1})`}return e}function z(t){let e=Ie(t);if(e)return e;let n=[],o=t;for(;o&&o!==document.documentElement;){let s=Ie(o);if(s&&o!==t){n.unshift(s);break}n.unshift(Rt(o));let i=n.join(" > ");if(xe(i))return i;o=o.parentElement}let r=(o===document.documentElement?"html > ":"")+n.join(" > ");return xe(r)?r:n.join(" > ")}function V(t){let e=[],n=t;for(;n&&n.nodeType===Node.ELEMENT_NODE;){let o=n.parentElement,r=n.localName;if(!o){e.unshift(r);break}let s=Array.from(o.children).filter(i=>i.localName===r);e.unshift(s.length>1?`${r}[${s.indexOf(n)+1}]`:r),n=o}return"/"+e.join("/")}function A(t){return t instanceof Element&&t.id===It}var Pt=500,Oe=4096,Ot=["display","position","width","height","margin","padding","border","border-radius","font-family","font-size","font-weight","line-height","color","background-color","background-image","opacity","z-index","overflow","flex","grid-area"];function Ht(t){let e=t.getBoundingClientRect();return{x:W(e.left),y:W(e.top),width:W(e.width),height:W(e.height)}}function W(t){return Math.round(t*100)/100}function Y(t,e){return t.length>e?t.slice(0,e-1)+"\u2026":t}function N(t,e=!1){let n=getComputedStyle(t),o={};for(let d of Ot){let c=n.getPropertyValue(d);c&&c!=="none"&&c!=="normal"&&c!=="auto"&&(o[d]=c)}let r={};if(t instanceof HTMLElement||t instanceof SVGElement)for(let[d,c]of Object.entries(t.dataset))c!==void 0&&(r[d]=Y(c,200));let{framework:s,components:i,source:a}=O(t),l=t.parentElement;return{selector:z(t),xpath:V(t),tag:t.localName,id:t.id??"",classes:Array.from(t.classList),dataset:r,role:t.getAttribute("role"),ariaLabel:t.getAttribute("aria-label"),text:Y((t.textContent??"").replace(/\s+/g," ").trim(),Pt),rect:Ht(t),styles:o,components:i,source:a,componentFramework:s,outerHtml:Y(t.outerHTML,Oe),parentOuterHtml:l&&l!==document.documentElement?Y(l.outerHTML,Oe):"",detached:e}}function G(t){let e=t.localName;t.id&&(e+=`#${t.id}`);let n=Array.from(t.classList).slice(0,3);return n.length&&(e+="."+n.join(".")),t.classList.length>3&&(e+="\u2026"),e}var ve="crt.annotations.v1",Ft=10,J=class{constructor(){m(this,"items",[]);m(this,"listeners",new Set);this.restore()}all(){return this.items.slice()}get(e){return this.items.find(n=>n.n===e)}count(){return this.items.length}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}addSelect(e){let n=N(e);return this.push({kind:"select",pageRect:K(e.getBoundingClientRect()),point:null,element:e,elementInfo:n,elements:[]})}addBox(e){let n=Dt(e).map(o=>({el:o,info:N(o)}));return this.push({kind:"box",pageRect:K(e),point:null,element:null,elementInfo:null,elements:n})}addPin(e,n){return this.push({kind:"pin",pageRect:K({x:e,y:n,width:1,height:1}),point:{x:e+window.scrollX,y:n+window.scrollY},element:null,elementInfo:null,elements:[]})}setNote(e,n){let o=this.get(e);!o||o.note===n||(o.note=n,this.changed())}remove(e){let n=this.items.length;this.items=this.items.filter(o=>o.n!==e),this.items.length!==n&&(this.items.forEach((o,r)=>o.n=r+1),this.changed())}clear(){this.items.length&&(this.items=[],this.changed())}resolve(){for(let e of this.items){e.kind==="select"&&(e.element?.isConnected||(e.element=Q(e.elementInfo)),e.element&&(e.pageRect=K(e.element.getBoundingClientRect())));for(let n of e.elements)n.el?.isConnected||(n.el=Q(n.info))}return this.all()}push(e){let n={id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,n:this.items.length+1,note:"",...e};return this.items.push(n),this.changed(),n}changed(){this.persist();for(let e of this.listeners)e(this.all())}persist(){try{if(!this.items.length){sessionStorage.removeItem(ve);return}let e=this.items.map(({element:n,elements:o,...r})=>({...r,elements:o.map(s=>s.info)}));sessionStorage.setItem(ve,JSON.stringify(e))}catch{}}restore(){try{let e=sessionStorage.getItem(ve);if(!e)return;let n=JSON.parse(e);if(!Array.isArray(n))return;this.items=n.map((o,r)=>({...o,n:r+1,element:Q(o.elementInfo),elements:(o.elements??[]).map(s=>({el:Q(s),info:s}))})),this.resolve()}catch{this.items=[]}}};function Q(t){if(!t)return null;try{let e=document.querySelectorAll(t.selector);return e.length===1?e[0]:null}catch{return null}}function K(t){let e=t.left??t.x??0,n=t.top??t.y??0;return{x:e+window.scrollX,y:n+window.scrollY,width:t.width,height:t.height}}function Z(t){return{x:t.x-window.scrollX,y:t.y-window.scrollY,width:t.width,height:t.height}}function Dt(t){let e=t.x+t.width,n=t.y+t.height,o=[],r=document.body?document.body.querySelectorAll("*"):[];for(let i of Array.from(r)){if(A(i)||i.closest("#crt-host")||i instanceof HTMLScriptElement||i instanceof HTMLStyleElement)continue;let a=i.getBoundingClientRect(),l=a.width*a.height;if(l<=0)continue;let d=Math.max(0,Math.min(a.right,e)-Math.max(a.left,t.x)),c=Math.max(0,Math.min(a.bottom,n)-Math.max(a.top,t.y));d*c>=l*.5&&o.push({el:i,area:l})}if(o.sort((i,a)=>a.area-i.area),o.length)return o.slice(0,Ft).map(i=>i.el);let s=document.elementsFromPoint(t.x+t.width/2,t.y+t.height/2).find(i=>!A(i)&&i!==document.documentElement&&i!==document.body);return s?[s]:[]}function qt(){try{let t=document.currentScript;if(!(t instanceof HTMLScriptElement)||!t.src)return"";let e=new URL(t.src,location.href).origin;return e===location.origin?"":e}catch{return""}}var ee=qt(),He=ee!=="";function k(t){return ee+t}function ne(){let t=window,e=t.__crt??(t.__crt={});return e.__console??(e.__console={entries:[],installed:!1})}function Bt(t){let{entries:e}=ne();e.push(t),e.length>50&&e.splice(0,e.length-50)}function te(t){if(typeof t=="string")return t;if(t instanceof Error)return`${t.name}: ${t.message}`;try{let e=JSON.stringify(t);return e===void 0?String(t):e}catch{return String(t)}}function Ut(t){if(t.length===0)return"";let[e,...n]=t;if(typeof e=="string"&&/%[sdifoOc]/.test(e)){let o=0;return[e.replace(/%[sdifoOc]/g,s=>s==="%c"?(o++,""):o<n.length?te(n[o++]):s),...n.slice(o).map(te)].join(" ")}return t.map(te).join(" ")}function Ee(t,e,n){let o=n instanceof Error?n:e.find(r=>r instanceof Error);Bt({level:t,message:Ut(e).slice(0,2e3),stack:o?.stack?o.stack.slice(0,4e3):null,timestamp:new Date().toISOString(),url:location.href})}function Fe(){let t=ne();if(!t.installed){t.installed=!0;for(let e of["error","warn"]){let n=console[e];console[e]=function(...o){try{Ee(e,o)}catch{}return n.apply(this===void 0?console:this,o)}}window.addEventListener("error",e=>{let n=e.error instanceof Error?e.error.message:e.message||"Uncaught error",o=e.filename?` (${e.filename}:${e.lineno}:${e.colno})`:"";Ee("uncaught",[n+o],e.error)}),window.addEventListener("unhandledrejection",e=>{let n=e.reason,o=n instanceof Error?n.message:te(n);Ee("unhandledrejection",[`Unhandled promise rejection: ${o}`],n)})}}function oe(){return ne().entries.slice()}function De(){ne().entries.length=0}function se(){let t=window,e=t.__crt??(t.__crt={});return e.__network??(e.__network={entries:[],installed:!1})}function qe(t){if(/\/__crt\//.test(t.url)||/^(data|blob):/i.test(t.url))return;let{entries:e}=se();e.push(t),e.length>50&&e.splice(0,e.length-50)}function re(t,e,n,o,r,s){qe({method:e.toUpperCase(),url:String(n).slice(0,2e3),status:o,error:r==null?null:jt(r),via:t,durationMs:s===null?null:Math.round(performance.now()-s),timestamp:new Date().toISOString()})}function jt(t){return(t instanceof Error?`${t.name}: ${t.message}`:String(t)).slice(0,500)}function Xt(t,e){return typeof t=="string"?{method:e?.method??"GET",url:t}:t instanceof URL?{method:e?.method??"GET",url:t.href}:{method:e?.method??t.method??"GET",url:t.url}}function Be(){let t=se();if(!t.installed){if(t.installed=!0,typeof window.fetch=="function"){let e=window.fetch;window.fetch=function(n,o){let r=performance.now(),s={method:"GET",url:""};try{s=Xt(n,o)}catch{}let i=e.call(this===void 0?window:this,n,o);return i.then(a=>{a.status>=400&&re("fetch",s.method,s.url,a.status,null,r)},a=>re("fetch",s.method,s.url,null,a,r)),i}}if(typeof XMLHttpRequest=="function"){let e=XMLHttpRequest.prototype,n=e.open,o=e.send,r=new WeakMap;e.open=function(s,i,...a){return r.set(this,{method:String(s),url:String(i),started:0}),n.apply(this,[s,i,...a])},e.send=function(s){let i=r.get(this);return i&&(i.started=performance.now(),this.addEventListener("loadend",()=>{try{this.status>=400?re("xhr",i.method,i.url,this.status,null,i.started):this.status===0&&re("xhr",i.method,i.url,null,"request failed (no response: network error, CORS or abort)",i.started)}catch{}},{once:!0})),o.call(this,s)}}if(typeof PerformanceObserver=="function")try{new PerformanceObserver(n=>{for(let o of n.getEntries()){let r=o.responseStatus;typeof r!="number"||r<400||o.initiatorType==="fetch"||o.initiatorType==="xmlhttprequest"||qe({method:"GET",url:o.name.slice(0,2e3),status:r,error:null,via:"resource",durationMs:Math.round(o.duration),timestamp:new Date().toISOString()})}}).observe({type:"resource",buffered:!0})}catch{}}}function ie(){return se().entries.slice()}function Ue(){se().entries.length=0}var Ge="[modern-screenshot]",$=typeof window<"u",zt=$&&"Worker"in window,Po=$&&"atob"in window,Oo=$&&"btoa"in window,Ce=$?window.navigator?.userAgent:"",Qe=Ce.includes("Chrome"),ae=Ce.includes("AppleWebKit")&&!Qe,Te=Ce.includes("Firefox"),Vt=t=>t&&"__CONTEXT__"in t,Wt=t=>t.constructor.name==="CSSFontFaceRule",Yt=t=>t.constructor.name==="CSSImportRule",Gt=t=>t.constructor.name==="CSSLayerBlockRule",S=t=>t.nodeType===1,q=t=>typeof t.className=="object",Ke=t=>t.tagName==="image",Qt=t=>t.tagName==="use",H=t=>S(t)&&typeof t.style<"u"&&!q(t),Kt=t=>t.nodeType===8,Jt=t=>t.nodeType===3,P=t=>t.tagName==="IMG",le=t=>t.tagName==="VIDEO",Zt=t=>t.tagName==="CANVAS",en=t=>t.tagName==="TEXTAREA",tn=t=>t.tagName==="INPUT",nn=t=>t.tagName==="STYLE",on=t=>t.tagName==="SCRIPT",rn=t=>t.tagName==="SELECT",sn=t=>t.tagName==="SLOT",an=t=>t.tagName==="IFRAME",ln=(...t)=>console.warn(Ge,...t);function cn(t){let e=t?.createElement?.("canvas");return e&&(e.height=e.width=1),!!e&&"toDataURL"in e&&!!e.toDataURL("image/webp").includes("image/webp")}var ke=t=>t.startsWith("data:");function Je(t,e){if(t.match(/^[a-z]+:\/\//i))return t;if($&&t.match(/^\/\//))return window.location.protocol+t;if(t.match(/^[a-z]+:/i)||!$)return t;let n=ce().implementation.createHTMLDocument(),o=n.createElement("base"),r=n.createElement("a");return n.head.appendChild(o),n.body.appendChild(r),e&&(o.href=e),r.href=t,r.href}function ce(t){return(t&&S(t)?t?.ownerDocument:t)??window.document}var de="http://www.w3.org/2000/svg";function dn(t,e,n){let o=ce(n).createElementNS(de,"svg");return o.setAttributeNS(null,"width",t.toString()),o.setAttributeNS(null,"height",e.toString()),o.setAttributeNS(null,"viewBox",`0 0 ${t} ${e}`),o}function un(t,e){let n=new XMLSerializer().serializeToString(t);return e&&(n=n.replace(/[\u0000-\u0008\v\f\u000E-\u001F\uD800-\uDFFF\uFFFE\uFFFF]/gu,"")),`data:image/svg+xml;charset=utf-8,${encodeURIComponent(n)}`}function hn(t,e){return new Promise((n,o)=>{let r=new FileReader;r.onload=()=>n(r.result),r.onerror=()=>o(r.error),r.onabort=()=>o(new Error(`Failed read blob to ${e}`)),e==="dataUrl"?r.readAsDataURL(t):e==="arrayBuffer"&&r.readAsArrayBuffer(t)})}var pn=t=>hn(t,"dataUrl");function R(t,e){let n=ce(e).createElement("img");return n.decoding="sync",n.loading="eager",n.src=t,n}function F(t,e){return new Promise(n=>{let{timeout:o,ownerDocument:r,onError:s,onWarn:i}=e??{},a=typeof t=="string"?R(t,ce(r)):t,l=null,d=null;function c(){n(a),l&&clearTimeout(l),d?.()}if(o&&(l=setTimeout(c,o)),le(a)){let p=a.currentSrc||a.src;if(!p)return a.poster?F(a.poster,e).then(n):c();if(a.readyState>=2)return c();let u=c,f=g=>{i?.("Failed video load",p,g),s?.(g),c()};d=()=>{a.removeEventListener("loadeddata",u),a.removeEventListener("error",f)},a.addEventListener("loadeddata",u,{once:!0}),a.addEventListener("error",f,{once:!0})}else{let p=Ke(a)?a.href.baseVal:a.currentSrc||a.src;if(!p)return c();let u=async()=>{if(P(a)&&"decode"in a)try{await a.decode()}catch(g){i?.("Failed to decode image, trying to render anyway",a.dataset.originalSrc||p,g)}c()},f=g=>{i?.("Failed image load",a.dataset.originalSrc||p,g),c()};if(P(a)&&a.complete)return u();d=()=>{a.removeEventListener("load",u),a.removeEventListener("error",f)},a.addEventListener("load",u,{once:!0}),a.addEventListener("error",f,{once:!0})}})}async function fn(t,e){H(t)&&(P(t)||le(t)?await F(t,e):await Promise.all(["img","video"].flatMap(n=>Array.from(t.querySelectorAll(n)).map(o=>F(o,e)))))}var Ze=(function(){let e=0,n=()=>`0000${(Math.random()*36**4<<0).toString(36)}`.slice(-4);return()=>(e+=1,`u${n()}${e}`)})();function et(t){return t?.split(",").map(e=>e.trim().replace(/"|'/g,"").toLowerCase()).filter(Boolean)}var je=0;function mn(t){let e=`${Ge}[#${je}]`;return je++,{time:n=>t&&console.time(`${e} ${n}`),timeEnd:n=>t&&console.timeEnd(`${e} ${n}`),warn:(...n)=>t&&ln(...n)}}function gn(t){return{cache:t?"no-cache":"force-cache"}}async function tt(t,e){return Vt(t)?t:bn(t,{...e,autoDestruct:!0})}async function bn(t,e){let{scale:n=1,workerUrl:o,workerNumber:r=1}=e||{},s=!!e?.debug,i=e?.features??!0,a=t.ownerDocument??($?window.document:void 0),l=t.ownerDocument?.defaultView??($?window:void 0),d=new Map,c={width:0,height:0,quality:1,type:"image/png",scale:n,backgroundColor:null,style:null,filter:null,maximumCanvasSize:0,timeout:3e4,progress:null,debug:s,fetch:{requestInit:gn(e?.fetch?.bypassingCache),placeholderImage:"data:image/png;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",bypassingCache:!1,...e?.fetch},fetchFn:null,font:{},drawImageInterval:100,workerUrl:null,workerNumber:r,onCloneEachNode:null,onCloneNode:null,onEmbedNode:null,onCreateForeignObjectSvg:null,includeStyleProperties:null,autoDestruct:!1,...e,__CONTEXT__:!0,log:mn(s),node:t,ownerDocument:a,ownerWindow:l,dpi:n===1?null:96*n,svgStyleElement:nt(a),svgDefsElement:a?.createElementNS(de,"defs"),svgStyles:new Map,defaultComputedStyles:new Map,workers:[...Array.from({length:zt&&o&&r?r:0})].map(()=>{try{let f=new Worker(o);return f.onmessage=async g=>{let{url:h,result:b}=g.data;b?d.get(h)?.resolve?.(b):d.get(h)?.reject?.(new Error(`Error receiving message from worker: ${h}`))},f.onmessageerror=g=>{let{url:h}=g.data;d.get(h)?.reject?.(new Error(`Error receiving message from worker: ${h}`))},f}catch(f){return c.log.warn("Failed to new Worker",f),null}}).filter(Boolean),fontFamilies:new Map,fontCssTexts:new Map,acceptOfImage:`${[cn(a)&&"image/webp","image/svg+xml","image/*","*/*"].filter(Boolean).join(",")};q=0.8`,requests:d,drawImageCount:0,tasks:[],features:i,isEnable:f=>f==="restoreScrollPosition"?typeof i=="boolean"?!1:i[f]??!1:typeof i=="boolean"?i:i[f]??!0,shadowRoots:[]};c.log.time("wait until load"),await fn(t,{timeout:c.timeout,onWarn:c.log.warn}),c.log.timeEnd("wait until load");let{width:p,height:u}=wn(t,c);return c.width=p,c.height=u,c}function nt(t){if(!t)return;let e=t.createElement("style"),n=e.ownerDocument.createTextNode(`
|
|
3
|
+
.______background-clip--text {
|
|
4
|
+
background-clip: text;
|
|
5
|
+
-webkit-background-clip: text;
|
|
6
|
+
}
|
|
7
|
+
`);return e.appendChild(n),e}function wn(t,e){let{width:n,height:o}=e;if(S(t)&&(!n||!o)){let r=t.getBoundingClientRect();n=n||r.width||Number(t.getAttribute("width"))||0,o=o||r.height||Number(t.getAttribute("height"))||0}return{width:n,height:o}}async function yn(t,e){let{log:n,timeout:o,drawImageCount:r,drawImageInterval:s}=e;n.time("image to canvas");let i=await F(t,{timeout:o,onWarn:e.log.warn}),{canvas:a,context2d:l}=xn(t.ownerDocument,e),d=()=>{try{l?.drawImage(i,0,0,a.width,a.height)}catch(c){e.log.warn("Failed to drawImage",c)}};if(d(),e.isEnable("fixSvgXmlDecode"))for(let c=0;c<r;c++)await new Promise(p=>{setTimeout(()=>{l?.clearRect(0,0,a.width,a.height),d(),p()},c+s)});return e.drawImageCount=0,n.timeEnd("image to canvas"),a}function xn(t,e){let{width:n,height:o,scale:r,backgroundColor:s,maximumCanvasSize:i}=e,a=t.createElement("canvas");a.width=Math.floor(n*r),a.height=Math.floor(o*r),a.style.width=`${n}px`,a.style.height=`${o}px`,i&&(a.width>i||a.height>i)&&(a.width>i&&a.height>i?a.width>a.height?(a.height*=i/a.width,a.width=i):(a.width*=i/a.height,a.height=i):a.width>i?(a.height*=i/a.width,a.width=i):(a.width*=i/a.height,a.height=i));let l=a.getContext("2d");return l&&s&&(l.fillStyle=s,l.fillRect(0,0,a.width,a.height)),{canvas:a,context2d:l}}function ot(t,e){if(t.ownerDocument)try{let s=t.toDataURL();if(s!=="data:,")return R(s,t.ownerDocument)}catch(s){e.log.warn("Failed to clone canvas",s)}let n=t.cloneNode(!1),o=t.getContext("2d"),r=n.getContext("2d");try{return o&&r&&r.putImageData(o.getImageData(0,0,t.width,t.height),0,0),n}catch(s){e.log.warn("Failed to clone canvas",s)}return n}function vn(t,e){try{if(t?.contentDocument?.documentElement)return _e(t.contentDocument.documentElement,e)}catch(n){e.log.warn("Failed to clone iframe",n)}return t.cloneNode(!1)}function En(t){let e=t.cloneNode(!1);return t.currentSrc&&t.currentSrc!==t.src&&(e.src=t.currentSrc,e.srcset=""),e.loading==="lazy"&&(e.loading="eager"),e}async function kn(t,e){if(t.ownerDocument&&!t.currentSrc&&t.poster)return R(t.poster,t.ownerDocument);let n=t.cloneNode(!1);n.crossOrigin="anonymous",t.currentSrc&&t.currentSrc!==t.src&&(n.src=t.currentSrc);let o=n.ownerDocument;if(o){let r=!0;if(await F(n,{onError:()=>r=!1,onWarn:e.log.warn}),!r)return t.poster?R(t.poster,t.ownerDocument):n;n.currentTime=t.currentTime,await new Promise(i=>{n.addEventListener("seeked",i,{once:!0})});let s=o.createElement("canvas");s.width=t.offsetWidth,s.height=t.offsetHeight;try{let i=s.getContext("2d");i&&i.drawImage(n,0,0,s.width,s.height)}catch(i){return e.log.warn("Failed to clone video",i),t.poster?R(t.poster,t.ownerDocument):n}return ot(s,e)}return n}function Sn(t,e){return Zt(t)?ot(t,e):an(t)?vn(t,e):P(t)?En(t):le(t)?kn(t,e):t.cloneNode(!1)}function Cn(t){let e=t.sandbox;if(!e){let{ownerDocument:n}=t;try{n&&(e=n.createElement("iframe"),e.id=`__SANDBOX__${Ze()}`,e.width="0",e.height="0",e.style.visibility="hidden",e.style.position="fixed",n.body.appendChild(e),e.srcdoc='<!DOCTYPE html><meta charset="UTF-8"><title></title><body>',t.sandbox=e)}catch(o){t.log.warn("Failed to getSandBox",o)}}return e}var Tn=["width","height","-webkit-text-fill-color"],_n=["stroke","fill"];function rt(t,e,n){let{defaultComputedStyles:o}=n,r=t.nodeName.toLowerCase(),s=q(t)&&r!=="svg",i=s?_n.map(h=>[h,t.getAttribute(h)]).filter(([,h])=>h!==null):[],a=[s&&"svg",r,i.map((h,b)=>`${h}=${b}`).join(","),e].filter(Boolean).join(":");if(o.has(a))return o.get(a);let d=Cn(n)?.contentWindow;if(!d)return new Map;let c=d?.document,p,u;s?(p=c.createElementNS(de,"svg"),u=p.ownerDocument.createElementNS(p.namespaceURI,r),i.forEach(([h,b])=>{u.setAttributeNS(null,h,b)}),p.appendChild(u)):p=u=c.createElement(r),u.textContent=" ",c.body.appendChild(p);let f=d.getComputedStyle(u,e),g=new Map;for(let h=f.length,b=0;b<h;b++){let w=f.item(b);Tn.includes(w)||g.set(w,f.getPropertyValue(w))}return c.body.removeChild(p),o.set(a,g),g}function st(t,e,n){let o=new Map,r=[],s=new Map;if(n)for(let a of n)i(a);else for(let a=t.length,l=0;l<a;l++){let d=t.item(l);i(d)}for(let a=r.length,l=0;l<a;l++)s.get(r[l])?.forEach((d,c)=>o.set(c,d));function i(a){let l=t.getPropertyValue(a),d=t.getPropertyPriority(a),c=a.lastIndexOf("-"),p=c>-1?a.substring(0,c):void 0;if(p){let u=s.get(p);u||(u=new Map,s.set(p,u)),u.set(a,[l,d])}e.get(a)===l&&!d||(p?r.push(p):o.set(a,[l,d]))}return o}function An(t,e,n,o){let{ownerWindow:r,includeStyleProperties:s,currentParentNodeStyle:i}=o,a=e.style,l=r.getComputedStyle(t),d=rt(t,null,o);i?.forEach((p,u)=>{d.delete(u)});let c=st(l,d,s);c.delete("transition-property"),c.delete("all"),c.delete("d"),c.delete("content"),n&&(c.delete("position"),c.delete("margin-top"),c.delete("margin-right"),c.delete("margin-bottom"),c.delete("margin-left"),c.delete("margin-block-start"),c.delete("margin-block-end"),c.delete("margin-inline-start"),c.delete("margin-inline-end"),c.set("box-sizing",["border-box",""])),c.get("background-clip")?.[0]==="text"&&e.classList.add("______background-clip--text"),Qe&&(c.has("font-kerning")||c.set("font-kerning",["normal",""]),(c.get("overflow-x")?.[0]==="hidden"||c.get("overflow-y")?.[0]==="hidden")&&c.get("text-overflow")?.[0]==="ellipsis"&&t.scrollWidth===t.clientWidth&&c.set("text-overflow",["clip",""]));for(let p=a.length,u=0;u<p;u++)a.removeProperty(a.item(u));return c.forEach(([p,u],f)=>{a.setProperty(f,p,u)}),c}function Mn(t,e){(en(t)||tn(t)||rn(t))&&e.setAttribute("value",t.value)}var Ln=["::before","::after"],$n=["::-webkit-scrollbar","::-webkit-scrollbar-button","::-webkit-scrollbar-thumb","::-webkit-scrollbar-track","::-webkit-scrollbar-track-piece","::-webkit-scrollbar-corner","::-webkit-resizer"];function Nn(t,e,n,o,r){let{ownerWindow:s,svgStyleElement:i,svgStyles:a,currentNodeStyle:l}=o;if(!i||!s)return;function d(c){let p=s.getComputedStyle(t,c),u=p.getPropertyValue("content");if(!u||u==="none")return;r?.(u),u=u.replace(/(')|(")|(counter\(.+\))/g,"");let f=[Ze()],g=rt(t,c,o);l?.forEach((v,E)=>{g.delete(E)});let h=st(p,g,o.includeStyleProperties);h.delete("content"),h.delete("-webkit-locale"),h.get("background-clip")?.[0]==="text"&&e.classList.add("______background-clip--text");let b=[`content: '${u}';`];if(h.forEach(([v,E],L)=>{b.push(`${L}: ${v}${E?" !important":""};`)}),b.length===1)return;try{e.className=[e.className,...f].join(" ")}catch(v){o.log.warn("Failed to copyPseudoClass",v);return}let w=b.join(`
|
|
8
|
+
`),y=a.get(w);y||(y=[],a.set(w,y)),y.push(`.${f[0]}${c}`)}Ln.forEach(d),n&&$n.forEach(d)}var Xe=new Set(["symbol"]);async function ze(t,e,n,o,r){if(S(n)&&(nn(n)||on(n))||o.filter&&!o.filter(n))return;Xe.has(e.nodeName)||Xe.has(n.nodeName)?o.currentParentNodeStyle=void 0:o.currentParentNodeStyle=o.currentNodeStyle;let s=await _e(n,o,!1,r);o.isEnable("restoreScrollPosition")&&In(t,s),e.appendChild(s)}async function Ve(t,e,n,o){let r=t.firstChild;S(t)&&t.shadowRoot&&(r=t.shadowRoot?.firstChild,n.shadowRoots.push(t.shadowRoot));for(let s=r;s;s=s.nextSibling)if(!Kt(s))if(S(s)&&sn(s)&&typeof s.assignedNodes=="function"){let i=s.assignedNodes();for(let a=0;a<i.length;a++)await ze(t,e,i[a],n,o)}else await ze(t,e,s,n,o)}function In(t,e){if(!H(t)||!H(e))return;let{scrollTop:n,scrollLeft:o}=t;if(!n&&!o)return;let{transform:r}=e.style,s=new DOMMatrix(r),{a:i,b:a,c:l,d}=s;s.a=1,s.b=0,s.c=0,s.d=1,s.translateSelf(-o,-n),s.a=i,s.b=a,s.c=l,s.d=d,e.style.transform=s.toString()}function Rn(t,e){let{backgroundColor:n,width:o,height:r,style:s}=e,i=t.style;if(n&&i.setProperty("background-color",n,"important"),o&&i.setProperty("width",`${o}px`,"important"),r&&i.setProperty("height",`${r}px`,"important"),s)for(let a in s)i[a]=s[a]}var Pn=/^[\w-:]+$/;async function _e(t,e,n=!1,o){let{ownerDocument:r,ownerWindow:s,fontFamilies:i,onCloneEachNode:a}=e;if(r&&Jt(t))return o&&/\S/.test(t.data)&&o(t.data),r.createTextNode(t.data);if(r&&s&&S(t)&&(H(t)||q(t))){let d=await Sn(t,e);if(e.isEnable("removeAbnormalAttributes")){let h=d.getAttributeNames();for(let b=h.length,w=0;w<b;w++){let y=h[w];Pn.test(y)||d.removeAttribute(y)}}let c=e.currentNodeStyle=An(t,d,n,e);n&&Rn(d,e);let p=!1;if(e.isEnable("copyScrollbar")){let h=[c.get("overflow-x")?.[0],c.get("overflow-y")?.[0]];p=h.includes("scroll")||(h.includes("auto")||h.includes("overlay"))&&(t.scrollHeight>t.clientHeight||t.scrollWidth>t.clientWidth)}let u=c.get("text-transform")?.[0],f=et(c.get("font-family")?.[0]),g=f?h=>{u==="uppercase"?h=h.toUpperCase():u==="lowercase"?h=h.toLowerCase():u==="capitalize"&&(h=h[0].toUpperCase()+h.substring(1)),f.forEach(b=>{let w=i.get(b);w||i.set(b,w=new Set),h.split("").forEach(y=>w.add(y))})}:void 0;return Nn(t,d,p,e,g),Mn(t,d),le(t)||await Ve(t,d,e,g),await a?.(d),d}let l=t.cloneNode(!1);return await Ve(t,l,e),await a?.(l),l}function On(t){if(t.ownerDocument=void 0,t.ownerWindow=void 0,t.svgStyleElement=void 0,t.svgDefsElement=void 0,t.svgStyles.clear(),t.defaultComputedStyles.clear(),t.sandbox){try{t.sandbox.remove()}catch(e){t.log.warn("Failed to destroyContext",e)}t.sandbox=void 0}t.workers=[],t.fontFamilies.clear(),t.fontCssTexts.clear(),t.requests.clear(),t.tasks=[],t.shadowRoots=[]}function Hn(t){let{url:e,timeout:n,responseType:o,...r}=t,s=new AbortController,i=n?setTimeout(()=>s.abort(),n):void 0;return fetch(e,{signal:s.signal,...r}).then(a=>{if(!a.ok)throw new Error("Failed fetch, not 2xx response",{cause:a});switch(o){case"arrayBuffer":return a.arrayBuffer();case"dataUrl":return a.blob().then(pn);case"text":default:return a.text()}}).finally(()=>clearTimeout(i))}function D(t,e){let{url:n,requestType:o="text",responseType:r="text",imageDom:s}=e,i=n,{timeout:a,acceptOfImage:l,requests:d,fetchFn:c,fetch:{requestInit:p,bypassingCache:u,placeholderImage:f},font:g,workers:h,fontFamilies:b}=t;o==="image"&&(ae||Te)&&t.drawImageCount++;let w=d.get(n);if(!w){u&&u instanceof RegExp&&u.test(i)&&(i+=(/\?/.test(i)?"&":"?")+new Date().getTime());let y=o.startsWith("font")&&g&&g.minify,v=new Set;y&&o.split(";")[1].split(",").forEach(j=>{b.has(j)&&b.get(j).forEach(Me=>v.add(Me))});let E=y&&v.size,L={url:i,timeout:a,responseType:E?"arrayBuffer":r,headers:o==="image"?{accept:l}:void 0,...p};w={type:o,resolve:void 0,reject:void 0,response:null},w.response=(async()=>{if(c&&o==="image"){let _=await c(n);if(_)return _}return!ae&&n.startsWith("http")&&h.length?new Promise((_,j)=>{h[d.size&h.length-1].postMessage({rawUrl:n,...L}),w.resolve=_,w.reject=j}):Hn(L)})().catch(_=>{if(d.delete(n),o==="image"&&f)return t.log.warn("Failed to fetch image base64, trying to use placeholder image",i),typeof f=="string"?f:f(s);throw _}),d.set(n,w)}return w.response}async function it(t,e,n,o){if(!at(t))return t;for(let[r,s]of Fn(t,e))try{let i=await D(n,{url:s,requestType:o?"image":"text",responseType:"dataUrl"});t=t.replace(Dn(r),`$1${i}$3`)}catch(i){n.log.warn("Failed to fetch css data url",r,i)}return t}function at(t){return/url\((['"]?)([^'"]+?)\1\)/.test(t)}var lt=/url\((['"]?)([^'"]+?)\1\)/g;function Fn(t,e){let n=[];return t.replace(lt,(o,r,s)=>(n.push([s,Je(s,e)]),o)),n.filter(([o])=>!ke(o))}function Dn(t){let e=t.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1");return new RegExp(`(url\\(['"]?)(${e})(['"]?\\))`,"g")}var qn=["background-image","border-image-source","-webkit-border-image","-webkit-mask-image","list-style-image"];function Bn(t,e){return qn.map(n=>{let o=t.getPropertyValue(n);return!o||o==="none"?null:((ae||Te)&&e.drawImageCount++,it(o,null,e,!0).then(r=>{!r||o===r||t.setProperty(n,r,t.getPropertyPriority(n))}))}).filter(Boolean)}function Un(t,e){if(P(t)){let n=t.currentSrc||t.src;if(!ke(n))return[D(e,{url:n,imageDom:t,requestType:"image",responseType:"dataUrl"}).then(o=>{o&&(t.srcset="",t.dataset.originalSrc=n,t.src=o||"")})];(ae||Te)&&e.drawImageCount++}else if(q(t)&&!ke(t.href.baseVal)){let n=t.href.baseVal;return[D(e,{url:n,imageDom:t,requestType:"image",responseType:"dataUrl"}).then(o=>{o&&(t.dataset.originalSrc=n,t.href.baseVal=o||"")})]}return[]}function jn(t,e){let{ownerDocument:n,svgDefsElement:o}=e,r=t.getAttribute("href")??t.getAttribute("xlink:href");if(!r)return[];let[s,i]=r.split("#");if(i){let a=`#${i}`,l=e.shadowRoots.reduce((d,c)=>d??c.querySelector(`svg ${a}`),n?.querySelector(`svg ${a}`));if(s&&t.setAttribute("href",a),o?.querySelector(a))return[];if(l)return o?.appendChild(l.cloneNode(!0)),[];if(s)return[D(e,{url:s,responseType:"text"}).then(d=>{o?.insertAdjacentHTML("beforeend",d)})]}return[]}function ct(t,e){let{tasks:n}=e;S(t)&&((P(t)||Ke(t))&&n.push(...Un(t,e)),Qt(t)&&n.push(...jn(t,e))),H(t)&&n.push(...Bn(t.style,e)),t.childNodes.forEach(o=>{ct(o,e)})}async function Xn(t,e){let{ownerDocument:n,svgStyleElement:o,fontFamilies:r,fontCssTexts:s,tasks:i,font:a}=e;if(!(!n||!o||!r.size))if(a&&a.cssText){let l=Ye(a.cssText,e);o.appendChild(n.createTextNode(`${l}
|
|
9
|
+
`))}else{let l=Array.from(n.styleSheets).filter(f=>{try{return"cssRules"in f&&!!f.cssRules.length}catch(g){return e.log.warn(`Error while reading CSS rules from ${f.href}`,g),!1}}),d=n.implementation.createHTMLDocument(""),c=d.createElement("style");d.head.appendChild(c);let p=c.sheet;await Promise.all(l.flatMap(f=>Array.from(f.cssRules).map(async g=>{if(Yt(g)){let h=g.href,b="";try{b=await D(e,{url:h,requestType:"text",responseType:"text"})}catch(y){e.log.warn(`Error fetch remote css import from ${h}`,y)}let w=b.replace(lt,(y,v,E)=>y.replace(E,Je(E,h)));for(let y of Vn(w))try{p.insertRule(y,p.cssRules.length)}catch(v){e.log.warn("Error inserting rule from remote css import",{rule:y,error:v})}}}))),p.cssRules.length&&l.push(p);let u=[];l.forEach(f=>{Se(f.cssRules,u)}),u.filter(f=>Wt(f)&&at(f.style.getPropertyValue("src"))&&et(f.style.getPropertyValue("font-family"))?.some(g=>r.has(g))).forEach(f=>{let g=f,h=s.get(g.cssText);h?o.appendChild(n.createTextNode(`${h}
|
|
10
|
+
`)):i.push(it(g.cssText,g.parentStyleSheet?g.parentStyleSheet.href:null,e).then(b=>{b=Ye(b,e),s.set(g.cssText,b),o.appendChild(n.createTextNode(`${b}
|
|
11
|
+
`))}))})}}var zn=/(\/\*[\s\S]*?\*\/)/g,We=/((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi;function Vn(t){if(t==null)return[];let e=[],n=t.replace(zn,"");for(;;){let s=We.exec(n);if(!s)break;e.push(s[0])}n=n.replace(We,"");let o=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,r=new RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})","gi");for(;;){let s=o.exec(n);if(s)r.lastIndex=o.lastIndex;else if(s=r.exec(n),s)o.lastIndex=r.lastIndex;else break;e.push(s[0])}return e}var Wn=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,Yn=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;function Ye(t,e){let{font:n}=e,o=n?n?.preferredFormat:void 0;return o?t.replace(Yn,r=>{for(;;){let[s,,i]=Wn.exec(r)||[];if(!i)return"";if(i===o)return`src: ${s};`}}):t}function Se(t,e=[]){for(let n of Array.from(t))Gt(n)?e.push(...Se(n.cssRules)):"cssRules"in n?Se(n.cssRules,e):e.push(n);return e}var Gn=/\bx?link:?href\s*=\s*["'](?!data:)[^"']+["']/i;function Qn(t){return Gn.test(t.innerHTML)}async function Kn(t,e){let n=await tt(t,e);if(S(n.node)&&q(n.node)&&!Qn(n.node))return n.node;let{ownerDocument:o,log:r,tasks:s,svgStyleElement:i,svgDefsElement:a,svgStyles:l,font:d,progress:c,autoDestruct:p,onCloneNode:u,onEmbedNode:f,onCreateForeignObjectSvg:g}=n;r.time("clone node");let h=await _e(n.node,n,!0);if(i&&o){let E="";l.forEach((L,_)=>{E+=`${L.join(`,
|
|
12
|
+
`)} {
|
|
13
|
+
${_}
|
|
14
|
+
}
|
|
15
|
+
`}),i.appendChild(o.createTextNode(E))}r.timeEnd("clone node"),await u?.(h),d!==!1&&S(h)&&(r.time("embed web font"),await Xn(h,n),r.timeEnd("embed web font")),r.time("embed node"),ct(h,n);let b=s.length,w=0,y=async()=>{for(;;){let E=s.pop();if(!E)break;try{await E}catch(L){n.log.warn("Failed to run task",L)}c?.(++w,b)}};c?.(w,b),await Promise.all([...Array.from({length:4})].map(y)),r.timeEnd("embed node"),await f?.(h);let v=Jn(h,n);return a&&v.insertBefore(a,v.children[0]),i&&v.insertBefore(i,v.children[0]),p&&On(n),await g?.(v),v}function Jn(t,e){let{width:n,height:o}=e,r=dn(n,o,t.ownerDocument),s=r.ownerDocument.createElementNS(r.namespaceURI,"foreignObject");return s.setAttributeNS(null,"x","0%"),s.setAttributeNS(null,"y","0%"),s.setAttributeNS(null,"width","100%"),s.setAttributeNS(null,"height","100%"),s.append(t),r.appendChild(s),r}async function dt(t,e){let n=await tt(t,e),o=await Kn(n),r=un(o,n.isEnable("removeControlCharacter"));n.autoDestruct||(n.svgStyleElement=nt(n.ownerDocument),n.svgDefsElement=n.ownerDocument?.createElementNS(de,"defs"),n.svgStyles.clear());let s=R(r,o.ownerDocument);return await yn(s,n)}var x="#ff3d71",ue=24,he=160,B="data-crt-fixed";async function ht(t){let e={images:{},viewport:null,annotated:null,crops:new Map,error:null},n;try{n=await Zn()}catch(i){return e.error=`rasterisation failed: ${i instanceof Error?i.message:String(i)}`,e}let o=n.width/window.innerWidth||1;e.images["viewport.png"]=Ae(n),e.viewport="viewport.png";let r=document.createElement("canvas");r.width=n.width,r.height=n.height;let s=r.getContext("2d");s.drawImage(n,0,0),s.scale(o,o);for(let i of t)ro(s,i);e.images["viewport-annotated.png"]=Ae(r),e.annotated="viewport-annotated.png";for(let i of t){let a=so(i);if(a.width<1||a.height<1)continue;let l=document.createElement("canvas");l.width=Math.round(a.width*o),l.height=Math.round(a.height*o),l.getContext("2d").drawImage(r,a.x*o,a.y*o,l.width,l.height,0,0,l.width,l.height);let d=`ann-${i.n}.png`;e.images[d]=Ae(l),e.crops.set(i.n,d)}return e}async function Zn(){let t=window.scrollX,e=window.scrollY,n=t||e?oo():[],o=await eo();try{return await dt(document.documentElement,{width:window.innerWidth,height:window.innerHeight,scale:Math.min(window.devicePixelRatio||1,2),backgroundColor:"#fff",filter:r=>!A(r),features:{restoreScrollPosition:!0},timeout:8e3,onCloneNode:r=>{if(r instanceof Element)for(let s of Array.from(r.querySelectorAll(`[${B}]`))){let[i,a]=(s.getAttribute(B)??"0,0").split(",").map(Number);s.style.position="absolute",s.style.top=`${(i??0)+e}px`,s.style.left=`${(a??0)+t}px`,s.style.bottom="auto",s.style.right="auto",s.style.margin="0",s.removeAttribute(B)}}})}finally{for(let r of n)r.removeAttribute(B);o?.remove()}}var ut=new Map;async function eo(){let t=new Set;try{document.fonts.forEach(r=>{r.status==="loaded"&&t.add(r.family.replace(/^["']|["']$/g,""))})}catch{return null}if(!t.size)return null;let e=Array.from(t).sort().join("|"),n=[];for(let r of Array.from(document.styleSheets)){let s=r.href;if(!s)continue;try{r.cssRules;continue}catch{}let i=`${s}
|
|
16
|
+
${e}`,a=ut.get(i);if(a===void 0){try{let l=await(await fetch(s,{mode:"cors"})).text();a=await to(l,s,t)}catch{a=""}ut.set(i,a)}a&&n.push(a)}if(!n.length)return null;let o=document.createElement("style");return o.setAttribute("data-crt-fonts",""),o.textContent=n.join(`
|
|
17
|
+
`),document.head.appendChild(o),o}async function to(t,e,n){let o=[];for(let r of t.match(/@font-face\s*\{[^}]*\}/g)??[]){let s=/font-family\s*:\s*["']?([^;"']+)/.exec(r)?.[1]?.trim();if(!s||!n.has(s))continue;let i=r;for(let a of Array.from(r.matchAll(/url\((["']?)([^)"']+)\1\)/g))){let l=a[2];if(!l.startsWith("data:"))try{let d=await(await fetch(new URL(l,e).href,{mode:"cors"})).blob();i=i.replace(a[0],`url(${await no(d)})`)}catch{}}o.push(i)}return o.join(`
|
|
18
|
+
`)}function no(t){return new Promise((e,n)=>{let o=new FileReader;o.onload=()=>e(String(o.result)),o.onerror=()=>n(o.error),o.readAsDataURL(t)})}function oo(){let t=[];for(let e of Array.from(document.body?.querySelectorAll("*")??[])){if(A(e)||getComputedStyle(e).position!=="fixed")continue;let n=e.getBoundingClientRect();e.setAttribute(B,`${n.top},${n.left}`),t.push(e)}return t}function ro(t,e){t.save(),t.strokeStyle=x,t.fillStyle=x,t.lineWidth=2;let n,o;if(e.kind==="pin"&&e.point){let{x:s,y:i}=e.point;t.beginPath(),t.arc(s,i,6,0,Math.PI*2),t.fill(),t.beginPath(),t.arc(s,i,11,0,Math.PI*2),t.stroke(),n=s+14,o=i-14}else{let{x:s,y:i,width:a,height:l}=e.rect;e.kind==="box"&&t.setLineDash([6,4]),t.strokeRect(s,i,a,l),t.setLineDash([]),n=s,o=i}let r=11;t.beginPath(),t.arc(n,o,r,0,Math.PI*2),t.fill(),t.fillStyle="#fff",t.font="bold 13px system-ui, sans-serif",t.textAlign="center",t.textBaseline="middle",t.fillText(String(e.n),n,o+.5),t.restore()}function so(t){let e=window.innerWidth,n=window.innerHeight,o,r,s,i;t.kind==="pin"&&t.point?(o=t.point.x-he/2,r=t.point.y-he/2,s=he,i=he):(o=t.rect.x-ue,r=t.rect.y-ue,s=t.rect.width+ue*2,i=t.rect.height+ue*2);let a=Math.max(0,Math.floor(o)),l=Math.max(0,Math.floor(r)),d=Math.min(e,Math.ceil(o+s)),c=Math.min(n,Math.ceil(r+i));return{x:a,y:l,width:Math.max(0,d-a),height:Math.max(0,c-l)}}function Ae(t){return t.toDataURL("image/png").replace(/^data:image\/png;base64,/,"")}var io="/__crt/captures";function ao(t=new Date){return{url:location.href,pathname:location.pathname,query:location.search,hash:location.hash,title:document.title,viewport:{width:window.innerWidth,height:window.innerHeight},devicePixelRatio:window.devicePixelRatio||1,userAgent:navigator.userAgent,timestamp:t.toISOString(),scroll:{x:window.scrollX,y:window.scrollY}}}function pt(t,e){return t?.isConnected?N(t):e?{...e,detached:!0}:null}function lo(t){let e=t.element?.isConnected?co(t.element):Z(t.pageRect);return{n:t.n,kind:t.kind,rect:e,point:t.point?{x:t.point.x-window.scrollX,y:t.point.y-window.scrollY}:null}}function co(t){let e=t.getBoundingClientRect();return{x:e.left,y:e.top,width:e.width,height:e.height}}async function pe(t){let e=new Date,n=oe(),o=ie(),r=t.resolve(),s=r.map(lo),i=await ht(s),a=r.map((d,c)=>{let p=s[c];return{n:d.n,kind:d.kind,note:d.note,rect:p.rect,point:p.point,element:d.kind==="select"?pt(d.element,d.elementInfo):null,elements:d.kind==="box"?d.elements.map(u=>pt(u.el,u.info)).filter(uo):[],image:i.crops.get(d.n)??null}});return{bundle:{version:1,id:"",page:ao(e),framework:X(),annotations:a,console:n,network:o,screenshots:{viewport:i.viewport,annotated:i.annotated,error:i.error}},images:i.images}}function uo(t){return t!==null}async function ft(t){let e={bundle:t.bundle,images:t.images},n=await fetch(k(io),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)}),o=await n.json().catch(()=>({}));if(!n.ok||!o.ok||!o.id||!o.dir)throw new Error(o.error??`CRT server answered ${n.status}`);return{id:o.id,dir:o.dir,files:o.files??[]}}var C="/__crt/sessions",fe="crt.session.v1",mt=`
|
|
19
|
+
.chat { display: flex; flex-direction: column; width: 100%; height: min(72vh, 680px); border-radius: 12px; background: #fff;
|
|
20
|
+
box-shadow: 0 8px 28px rgba(0,0,0,.22); border: 1px solid rgba(0,0,0,.08); overflow: hidden; }
|
|
21
|
+
.chat[hidden] { display: none; }
|
|
22
|
+
.chat-head { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid rgba(0,0,0,.08); background: #fafafa; }
|
|
23
|
+
.chat-head .title { font-weight: 600; }
|
|
24
|
+
.chat-head .state { font-size: 11px; padding: 2px 8px; border-radius: 999px; background: #eee; color: #555; }
|
|
25
|
+
.chat-head .state[data-state="running"], .chat-head .state[data-state="starting"] { background: #fff3cd; color: #7a5a00; }
|
|
26
|
+
.chat-head .state[data-state="waiting"] { background: ${x}; color: #fff; }
|
|
27
|
+
.chat-head .state[data-state="idle"] { background: #d9f5e3; color: #0a5b2b; }
|
|
28
|
+
.chat-head .state[data-state="error"] { background: #fde2e2; color: #8b0000; }
|
|
29
|
+
.chat-head .spacer { flex: 1; }
|
|
30
|
+
.chat-head button { padding: 4px 8px; border-radius: 6px; font-size: 12px; }
|
|
31
|
+
.chat-head button:hover { background: #eee; }
|
|
32
|
+
.chat-head button:disabled { opacity: .4; cursor: default; }
|
|
33
|
+
.chat-log { flex: 1; overflow: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; scroll-behavior: smooth; }
|
|
34
|
+
.msg { max-width: 92%; padding: 8px 10px; border-radius: 10px; line-height: 1.45; word-wrap: break-word; overflow-wrap: anywhere; }
|
|
35
|
+
.msg.user { align-self: flex-end; background: #111; color: #fff; white-space: pre-wrap; }
|
|
36
|
+
.msg.user .imgs { display: block; margin-top: 4px; font-size: 11px; opacity: .75; }
|
|
37
|
+
.msg.assistant { align-self: flex-start; background: #f3f3f5; }
|
|
38
|
+
.msg.assistant p { margin: 0 0 6px; } .msg.assistant p:last-child { margin-bottom: 0; }
|
|
39
|
+
.msg.assistant ul, .msg.assistant ol { margin: 4px 0 6px; padding-left: 20px; }
|
|
40
|
+
.msg.assistant li { margin: 2px 0; }
|
|
41
|
+
.msg.assistant li.task { list-style: none; margin-left: -18px; }
|
|
42
|
+
.msg.assistant code { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; background: rgba(0,0,0,.06); padding: 0 4px; border-radius: 4px; }
|
|
43
|
+
.msg.assistant pre { margin: 6px 0; padding: 8px; border-radius: 8px; background: #1e1e24; color: #eee; overflow: auto; }
|
|
44
|
+
.msg.assistant pre code { background: none; padding: 0; color: inherit; }
|
|
45
|
+
.msg.assistant h1, .msg.assistant h2, .msg.assistant h3 { font-size: 13px; margin: 8px 0 4px; }
|
|
46
|
+
.msg.assistant.streaming::after { content: "\u258D"; color: ${x}; animation: crt-blink 1s steps(2) infinite; }
|
|
47
|
+
@keyframes crt-blink { to { opacity: 0; } }
|
|
48
|
+
.tool { align-self: stretch; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; color: #555; }
|
|
49
|
+
.tool summary { cursor: pointer; list-style: none; display: flex; gap: 6px; align-items: center; padding: 2px 4px; border-radius: 6px; }
|
|
50
|
+
.tool summary::before { content: "\u25B8"; color: #999; } .tool[open] summary::before { content: "\u25BE"; }
|
|
51
|
+
.tool summary:hover { background: #f3f3f5; }
|
|
52
|
+
.tool .dot { width: 6px; height: 6px; border-radius: 3px; background: #ccc; flex: none; }
|
|
53
|
+
.tool.done .dot { background: #2e9e5b; } .tool.error .dot { background: #c00; }
|
|
54
|
+
.tool .out { padding: 4px 4px 4px 18px; white-space: pre-wrap; color: #777; }
|
|
55
|
+
.perm { align-self: stretch; border: 1px solid ${x}; border-radius: 10px; padding: 8px 10px; background: #fff5f8; }
|
|
56
|
+
.perm .t { font-weight: 600; margin-bottom: 4px; }
|
|
57
|
+
.perm pre { margin: 0 0 8px; padding: 6px 8px; border-radius: 6px; background: #fff; border: 1px solid rgba(0,0,0,.08);
|
|
58
|
+
font-size: 12px; white-space: pre-wrap; max-height: 120px; overflow: auto; }
|
|
59
|
+
.perm .btns { display: flex; gap: 6px; }
|
|
60
|
+
.perm button { padding: 5px 12px; border-radius: 8px; font-weight: 600; }
|
|
61
|
+
.perm button.allow { background: #111; color: #fff; }
|
|
62
|
+
.perm button.deny { background: #eee; }
|
|
63
|
+
.perm .done { font-size: 12px; color: #555; }
|
|
64
|
+
.perm.resolved { border-color: rgba(0,0,0,.12); background: #fafafa; }
|
|
65
|
+
.sys { align-self: center; font-size: 11px; color: #888; text-align: center; }
|
|
66
|
+
.thinking { align-self: flex-start; font-size: 12px; color: #888; padding: 2px 10px; }
|
|
67
|
+
.thinking::after { content: "\u2026"; animation: crt-blink 1s steps(2) infinite; }
|
|
68
|
+
.sys.error { color: #b00020; font-weight: 600; align-self: stretch; text-align: left; padding: 6px 10px; background: #fde2e2; border-radius: 8px; }
|
|
69
|
+
.chat-task { padding: 8px 10px; background: #d9f5e3; color: #0a5b2b; font-size: 12px; border-top: 1px solid rgba(0,0,0,.06); }
|
|
70
|
+
.chat-task[hidden] { display: none; }
|
|
71
|
+
.chat-task code { font-family: ui-monospace, Menlo, Consolas, monospace; user-select: all; }
|
|
72
|
+
.chat-input { display: flex; gap: 6px; padding: 8px; border-top: 1px solid rgba(0,0,0,.08); }
|
|
73
|
+
.chat-input textarea { flex: 1; min-height: 38px; max-height: 120px; resize: vertical; font: inherit; padding: 8px; border-radius: 8px;
|
|
74
|
+
border: 1px solid rgba(0,0,0,.15); background: #fafafa; }
|
|
75
|
+
.chat-input textarea:focus { outline: 2px solid ${x}; outline-offset: -1px; background: #fff; }
|
|
76
|
+
.chat-input button { padding: 0 14px; border-radius: 8px; background: ${x}; color: #fff; font-weight: 600; }
|
|
77
|
+
.chat-input button:disabled { opacity: .5; cursor: default; }
|
|
78
|
+
.chat-foot { padding: 6px 10px; font-size: 11px; color: #777; border-top: 1px solid rgba(0,0,0,.06); background: #fafafa;
|
|
79
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
80
|
+
.chat-foot code { font-family: ui-monospace, Menlo, Consolas, monospace; user-select: all; color: #333; }
|
|
81
|
+
`,be=class{constructor(e,n){m(this,"el");m(this,"log");m(this,"stateEl");m(this,"taskEl");m(this,"input");m(this,"sendBtn");m(this,"stopBtn");m(this,"foot");m(this,"source",null);m(this,"sessionId",null);m(this,"state",null);m(this,"taskId",null);m(this,"events",[]);m(this,"texts",new Map);m(this,"thinking",null);m(this,"lastSeq",0);m(this,"quiet",!1);m(this,"callbacks");this.callbacks=n,this.el=document.createElement("div"),this.el.className="chat",this.el.hidden=!0,this.el.innerHTML=`
|
|
82
|
+
<div class="chat-head">
|
|
83
|
+
<span class="title">Claude</span>
|
|
84
|
+
<span class="state" data-state="starting">starting</span>
|
|
85
|
+
<span class="spacer"></span>
|
|
86
|
+
<button type="button" data-chat="interrupt" title="Interrupt the current turn (F-29)">Stop</button>
|
|
87
|
+
<button type="button" data-chat="new" title="Discard this session and go back to annotating (F-29)">New session</button>
|
|
88
|
+
<button type="button" data-chat="hide" title="Hide the chat (the session keeps running)">\xD7</button>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="chat-log" role="log" aria-live="polite"></div>
|
|
91
|
+
<div class="chat-task" hidden></div>
|
|
92
|
+
<div class="chat-input">
|
|
93
|
+
<textarea rows="1" placeholder="Reply to Claude\u2026 (Enter to send, Shift+Enter for a new line)"></textarea>
|
|
94
|
+
<button type="button" data-chat="send">Send</button>
|
|
95
|
+
</div>
|
|
96
|
+
<div class="chat-foot"></div>
|
|
97
|
+
`,e.prepend(this.el);let o=r=>this.el.querySelector(r);this.log=o(".chat-log"),this.stateEl=o(".chat-head .state"),this.taskEl=o(".chat-task"),this.input=o("textarea"),this.sendBtn=o("[data-chat=send]"),this.stopBtn=o("[data-chat=interrupt]"),this.foot=o(".chat-foot"),this.wire()}snapshot(){return{sessionId:this.sessionId,state:this.state,taskId:this.taskId,quiet:this.quiet,events:this.events.slice()}}isOpen(){return!this.el.hidden}async startFromCapture(e,n={}){let o=await this.createSession(e,n.quick===!0);return n.quick?this.follow(o):this.open(o),o}warmStart(e={}){return this.createSession(null,e.quick===!0)}async attachCapture(e,n,o={}){let r=await fetch(k(`${C}/${e}/capture`),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({captureId:n})}),s=await r.json().catch(()=>({}));if(!r.ok||!s.ok)throw new Error(s.error??`CRT server answered ${r.status}`);o.quick?this.follow(e):this.open(e)}async abandon(e){await fetch(k(`${C}/${e}`),{method:"DELETE"}).catch(()=>{})}async listSessions(){let e=await fetch(k(C)),n=await e.json().catch(()=>({}));if(!e.ok||!n.ok||!n.sessions)throw new Error(n.error??`CRT server answered ${e.status}`);return n.sessions}async createSession(e,n){let o=await fetch(k(C),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({...e?{captureId:e}:{},...n?{quick:n}:{}})}),r=await o.json().catch(()=>({}));if(!o.ok||!r.ok||!r.id)throw new Error(r.error??`CRT server answered ${o.status}`);return r.id}open(e){this.attach(e),this.quiet=!1,this.show(!0)}follow(e){this.attach(e),this.quiet=!0,this.show(!1)}attach(e){if(this.sessionId!==e){this.detach(),this.sessionId=e,this.state="starting",this.taskId=null,this.events=[],this.texts.clear(),this.lastSeq=0,this.log.replaceChildren(),this.thinking=null,this.taskEl.hidden=!0,this.renderFoot(),this.renderState(),this.connect();try{sessionStorage.setItem(fe,e)}catch{}}}async restore(){let e=null;try{e=sessionStorage.getItem(fe)}catch{return!1}if(!e)return!1;if(!await fetch(k(`${C}/${e}`)).then(o=>o.ok).catch(()=>!1)){try{sessionStorage.removeItem(fe)}catch{}return!1}return this.open(e),!0}show(e){this.el.hidden=!e,this.callbacks.onVisibility(e),e&&(this.scrollToEnd(),this.state==="idle"&&this.input.focus())}async send(e){if(!this.sessionId||!e.trim())return;let n=await fetch(k(`${C}/${this.sessionId}/messages`),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({text:e})});n.ok||this.system(`Could not send (${n.status})`,!0)}async interrupt(){this.sessionId&&await fetch(k(`${C}/${this.sessionId}/interrupt`),{method:"POST"})}async respond(e,n){this.sessionId&&await fetch(k(`${C}/${this.sessionId}/permission`),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({id:e,behavior:n})})}async discard(){let e=this.sessionId;this.detach(),this.sessionId=null,this.state=null,this.taskId=null,this.quiet=!1,this.events=[],this.texts.clear(),this.log.replaceChildren(),this.thinking=null;try{sessionStorage.removeItem(fe)}catch{}this.show(!1),e&&await fetch(k(`${C}/${e}`),{method:"DELETE"}).catch(()=>{})}connect(){if(!this.sessionId)return;let e=new EventSource(k(`${C}/${this.sessionId}/events?after=${this.lastSeq}`));this.source=e,e.onmessage=n=>{let o=Number(n.lastEventId);if(o&&o<=this.lastSeq)return;o&&(this.lastSeq=o);let r;try{r=JSON.parse(n.data)}catch{return}this.handle(r)},e.onerror=()=>{e.readyState===EventSource.CLOSED&&this.state!=="ended"&&this.state!=="error"&&this.system("Lost the connection to the CRT server",!0)}}detach(){this.source?.close(),this.source=null}handle(e){switch(this.events.push(e),e.type){case"state":this.state=e.state,this.renderState(),(e.state==="ended"||e.state==="error")&&this.detach(),e.state==="ended"&&this.system("Session ended"),e.state==="idle"&&this.isOpen()&&this.input.focus(),this.quiet&&e.state==="idle"&&!this.taskId?this.attention("Claude has a question"):this.quiet&&e.state==="error"?this.attention(e.detail??"the session failed"):this.quiet&&e.state==="ended"&&!this.taskId&&this.attention("the session ended without writing a task");break;case"init":this.renderFoot(e.model,e.claudeCodeVersion);break;case"user":this.append(ho(e.text,e.images));break;case"assistant_start":this.texts.set(e.messageId,""),this.showThinking();break;case"text":{this.hideThinking();let n=(this.texts.get(e.messageId)??"")+e.text;this.texts.set(e.messageId,n);let o=this.log.querySelector(`.msg.assistant[data-mid="${ge(e.messageId)}"]`);o||(o=this.append(po(e.messageId))),o.innerHTML=go(n),this.scrollToEnd();break}case"assistant_end":this.log.querySelector(`.msg.assistant[data-mid="${ge(e.messageId)}"]`)?.classList.remove("streaming");break;case"tool_use":this.hideThinking(),this.append(fo(e.id,e.label));break;case"tool_result":{let n=this.log.querySelector(`.tool[data-tid="${ge(e.id)}"]`);n&&(n.classList.add(e.isError?"error":"done"),n.querySelector(".out").textContent=e.summary||(e.isError?"error":"done"));break}case"permission":this.append(mo(e.id,e.title,e.detail)),this.quiet?this.attention("Claude needs a permission"):this.show(!0);break;case"permission_resolved":{let n=this.log.querySelector(`.perm[data-pid="${ge(e.id)}"]`);if(n){n.classList.add("resolved");let o=e.by==="timeout"?" (no answer within 5 minutes)":e.by==="session"?" (session ended)":"";n.querySelector(".btns").innerHTML=`<span class="done">${e.behavior==="allow"?"Allowed":"Denied"}${o}</span>`}break}case"result":this.hideThinking(),e.ok||this.system(e.errors.join("; ")||"The turn failed",!/interrupt/i.test(e.errors.join(" ")));for(let n of Array.from(this.log.querySelectorAll(".msg.assistant.streaming")))n.classList.remove("streaming");break;case"task_written":this.taskId=e.id,this.taskEl.innerHTML=`Task <b>${M(e.id)}</b> written to <code>${M(e.path)}</code>`,this.taskEl.hidden=!1,this.quiet&&(this.quiet=!1,this.callbacks.onQuiet({kind:"task",id:e.id,path:e.path}));break;case"error":this.system(e.message,!0);break}}attention(e){this.quiet=!1,this.show(!0),this.callbacks.onQuiet({kind:"attention",reason:e})}showThinking(){if(this.thinking)return;let e=document.createElement("div");e.className="thinking",e.textContent="thinking",this.thinking=this.append(e)}hideThinking(){this.thinking?.remove(),this.thinking=null}append(e){return this.log.appendChild(e),this.scrollToEnd(),e}system(e,n=!1){let o=document.createElement("div");o.className=n?"sys error":"sys",o.textContent=e,this.append(o)}renderState(){let e=this.state??"starting";this.stateEl.dataset.state=e,this.stateEl.textContent={starting:"starting",running:"thinking\u2026",waiting:"needs permission",idle:"your turn",ended:"ended",error:"error"}[e];let n=e==="ended"||e==="error";this.input.disabled=n,this.sendBtn.disabled=n,this.stopBtn.disabled=e!=="running"&&e!=="waiting"}renderFoot(e,n){let o=this.sessionId??"";this.foot.innerHTML=`session <code>${M(o)}</code>${e?` \xB7 ${M(e)}`:""}${n?` \xB7 Claude Code ${M(n)}`:""} \xB7 continue in a terminal: <code>claude --resume ${M(o)}</code>`,this.foot.title=`claude --resume ${o}`}scrollToEnd(){this.log.scrollTop=this.log.scrollHeight}wire(){this.el.addEventListener("click",e=>{let n=e.target.closest("button");if(!n)return;let o=n.closest(".perm");if(o&&n.dataset.behavior){this.respond(o.dataset.pid,n.dataset.behavior);return}switch(n.dataset.chat){case"send":this.submit();break;case"interrupt":this.interrupt();break;case"new":this.discard();break;case"hide":this.show(!1);break}}),this.input.addEventListener("keydown",e=>{e.key==="Enter"&&!e.shiftKey&&(e.preventDefault(),this.submit())})}submit(){let e=this.input.value.trim();!e||this.input.disabled||(this.input.value="",this.send(e))}};function ho(t,e){let n=document.createElement("div");if(n.className="msg user",n.textContent=t,e.length){let o=document.createElement("span");o.className="imgs",o.textContent=`\u{1F4CE} ${e.join(", ")}`,n.appendChild(o)}return n}function po(t){let e=document.createElement("div");return e.className="msg assistant streaming",e.dataset.mid=t,e}function fo(t,e){let n=document.createElement("details");return n.className="tool",n.dataset.tid=t,n.innerHTML='<summary><span class="dot"></span><span class="label"></span></summary><div class="out">\u2026</div>',n.querySelector(".label").textContent=e,n}function mo(t,e,n){let o=document.createElement("div");return o.className="perm",o.dataset.pid=t,o.innerHTML='<div class="t"></div><pre></pre><div class="btns"><button type="button" class="allow" data-behavior="allow">Allow</button><button type="button" class="deny" data-behavior="deny">Deny</button></div>',o.querySelector(".t").textContent=e,o.querySelector("pre").textContent=n,o}function go(t){let e=[],n=t.split(`
|
|
98
|
+
`),o=0,r=[],s=null,i=()=>{r.length&&e.push(`<p>${r.map(me).join("<br>")}</p>`),r=[]},a=()=>{s&&e.push(`<${s.tag}>${s.items.join("")}</${s.tag}>`),s=null};for(;o<n.length;){let l=n[o];if(/^\s*```/.exec(l)){i(),a();let u=[];for(o++;o<n.length&&!/^\s*```/.test(n[o]);)u.push(n[o++]);o++,e.push(`<pre><code>${M(u.join(`
|
|
99
|
+
`))}</code></pre>`);continue}let c=/^(#{1,3})\s+(.*)$/.exec(l);if(c){i(),a(),e.push(`<h${c[1].length}>${me(c[2])}</h${c[1].length}>`),o++;continue}let p=/^\s*(?:([-*+])|(\d+)[.)])\s+(.*)$/.exec(l);if(p){i();let u=p[1]?"ul":"ol";(!s||s.tag!==u)&&(a(),s={tag:u,items:[]});let f=/^\[([ xX])\]\s+(.*)$/.exec(p[3]);s.items.push(f?`<li class="task"><input type="checkbox" disabled${f[1]!==" "?" checked":""}> ${me(f[2])}</li>`:`<li>${me(p[3])}</li>`),o++;continue}if(!l.trim()){i(),a(),o++;continue}a(),r.push(l),o++}return i(),a(),e.join("")}function me(t){return t.split(/(`[^`]*`)/).map((n,o)=>o%2===1?`<code>${M(n.slice(1,-1))}</code>`:M(n).replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>").replace(/(^|[\s(])_([^_]+)_(?=[\s).,;:!?]|$)/g,"$1<em>$2</em>").replace(/(^|[\s(])\*([^*]+)\*(?=[\s).,;:!?]|$)/g,"$1<em>$2</em>")).join("")}function M(t){return t.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}function ge(t){return typeof CSS<"u"&&CSS.escape?CSS.escape(t):t.replace(/["\\]/g,"\\$&")}var gt="crt.launcher.v1",bt=16,bo=`
|
|
100
|
+
:host { all: initial; position: fixed; inset: 0; z-index: 2147483647; pointer-events: none;
|
|
101
|
+
font: 13px/1.4 system-ui, -apple-system, "Segoe UI", sans-serif; color: #111; display: block; }
|
|
102
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
103
|
+
button { font: inherit; cursor: pointer; border: 0; background: none; color: inherit; padding: 0; }
|
|
104
|
+
.launcher { position: fixed; pointer-events: auto; user-select: none; touch-action: none;
|
|
105
|
+
display: inline-flex; align-items: center; gap: 6px; padding: 10px 14px; border-radius: 999px;
|
|
106
|
+
background: #111; color: #fff; font-weight: 600; box-shadow: 0 4px 16px rgba(0,0,0,.25); cursor: grab; }
|
|
107
|
+
.launcher:active { cursor: grabbing; }
|
|
108
|
+
.launcher .count { display: none; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
|
|
109
|
+
background: ${x}; color: #fff; font-size: 11px; line-height: 18px; text-align: center; }
|
|
110
|
+
.launcher .count.on { display: inline-block; }
|
|
111
|
+
.dock { position: fixed; pointer-events: auto; display: flex; flex-direction: column; gap: 8px; align-items: flex-end;
|
|
112
|
+
width: min(360px, calc(100vw - 32px)); }
|
|
113
|
+
.dock[hidden] { display: none; }
|
|
114
|
+
.dock.chat-open { width: min(520px, calc(100vw - 32px)); }
|
|
115
|
+
.toolbar { display: flex; gap: 4px; align-items: center; padding: 6px; border-radius: 12px; background: #fff;
|
|
116
|
+
box-shadow: 0 8px 28px rgba(0,0,0,.22); border: 1px solid rgba(0,0,0,.08); }
|
|
117
|
+
.toolbar button { padding: 6px 10px; border-radius: 8px; font-weight: 500; }
|
|
118
|
+
.toolbar button:hover { background: #f0f0f0; }
|
|
119
|
+
.toolbar button.active { background: #111; color: #fff; }
|
|
120
|
+
.toolbar button.primary { background: ${x}; color: #fff; font-weight: 600; }
|
|
121
|
+
.toolbar button.primary:hover { background: #e62e63; }
|
|
122
|
+
.toolbar button:disabled { opacity: .5; cursor: default; }
|
|
123
|
+
.toolbar .sep { width: 1px; height: 20px; background: rgba(0,0,0,.1); margin: 0 2px; }
|
|
124
|
+
.toolbar .badge { min-width: 20px; padding: 0 6px; border-radius: 10px; background: #eee; text-align: center;
|
|
125
|
+
font-size: 11px; font-weight: 600; line-height: 20px; }
|
|
126
|
+
.panel { width: 100%; max-height: 50vh; overflow: auto; border-radius: 12px; background: #fff;
|
|
127
|
+
box-shadow: 0 8px 28px rgba(0,0,0,.22); border: 1px solid rgba(0,0,0,.08); padding: 6px; }
|
|
128
|
+
.panel[hidden] { display: none; }
|
|
129
|
+
.item { display: grid; grid-template-columns: 22px 1fr 22px; gap: 6px 8px; padding: 6px; border-radius: 8px; }
|
|
130
|
+
.item + .item { border-top: 1px solid rgba(0,0,0,.06); }
|
|
131
|
+
.item .num { width: 22px; height: 22px; border-radius: 11px; background: ${x}; color: #fff; font-weight: 700;
|
|
132
|
+
font-size: 12px; line-height: 22px; text-align: center; }
|
|
133
|
+
.item .label { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 11px; color: #555;
|
|
134
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 22px; }
|
|
135
|
+
.item .del { width: 22px; height: 22px; border-radius: 11px; color: #888; font-size: 16px; line-height: 22px; }
|
|
136
|
+
.item .del:hover { background: #fee; color: #c00; }
|
|
137
|
+
.item textarea { grid-column: 2 / 4; width: 100%; min-height: 40px; resize: vertical; font: inherit; padding: 6px 8px;
|
|
138
|
+
border: 1px solid rgba(0,0,0,.15); border-radius: 8px; background: #fafafa; }
|
|
139
|
+
.item textarea:focus { outline: 2px solid ${x}; outline-offset: -1px; background: #fff; }
|
|
140
|
+
.empty { padding: 10px; color: #777; text-align: center; }
|
|
141
|
+
.status { width: 100%; padding: 8px 10px; border-radius: 10px; background: #111; color: #fff; font-size: 12px;
|
|
142
|
+
word-break: break-all; }
|
|
143
|
+
.status[hidden] { display: none; }
|
|
144
|
+
.status.error { background: #b00020; }
|
|
145
|
+
.status code { font-family: ui-monospace, Menlo, Consolas, monospace; user-select: all; }
|
|
146
|
+
.status button { color: #ffd166; text-decoration: underline; margin-left: 6px; }
|
|
147
|
+
.sessions { width: 100%; max-height: 40vh; overflow: auto; border-radius: 12px; background: #fff;
|
|
148
|
+
box-shadow: 0 8px 28px rgba(0,0,0,.22); border: 1px solid rgba(0,0,0,.08); padding: 6px; }
|
|
149
|
+
.sessions[hidden] { display: none; }
|
|
150
|
+
.sessions .head { display: flex; align-items: center; gap: 8px; padding: 4px 6px 6px; font-weight: 600; }
|
|
151
|
+
.sessions .head .spacer { flex: 1; }
|
|
152
|
+
.sessions .head button { padding: 2px 8px; border-radius: 6px; font-size: 12px; color: #555; }
|
|
153
|
+
.sessions .head button:hover { background: #f0f0f0; }
|
|
154
|
+
.session { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; width: 100%; text-align: left; padding: 6px 8px;
|
|
155
|
+
border-radius: 8px; }
|
|
156
|
+
.session:hover { background: #f3f3f5; }
|
|
157
|
+
.session.current { background: #fff5f8; }
|
|
158
|
+
.session .sum { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
159
|
+
.session .meta { grid-column: 1 / 3; font-size: 11px; color: #777; font-family: ui-monospace, Menlo, Consolas, monospace;
|
|
160
|
+
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
161
|
+
.session .pill { font-size: 11px; padding: 1px 7px; border-radius: 999px; background: #eee; color: #555; white-space: nowrap; }
|
|
162
|
+
.session .pill[data-state="running"], .session .pill[data-state="starting"] { background: #fff3cd; color: #7a5a00; }
|
|
163
|
+
.session .pill[data-state="waiting"] { background: ${x}; color: #fff; }
|
|
164
|
+
.session .pill[data-state="idle"] { background: #d9f5e3; color: #0a5b2b; }
|
|
165
|
+
.session .pill[data-state="error"] { background: #fde2e2; color: #8b0000; }
|
|
166
|
+
.layer { position: fixed; inset: 0; pointer-events: auto; cursor: crosshair; touch-action: none; }
|
|
167
|
+
.layer[hidden] { display: none; }
|
|
168
|
+
.hover { position: fixed; pointer-events: none; border: 2px solid ${x}; background: rgba(255,61,113,.08);
|
|
169
|
+
border-radius: 2px; display: none; }
|
|
170
|
+
.hover-label { position: fixed; pointer-events: none; display: none; padding: 3px 7px; border-radius: 6px;
|
|
171
|
+
background: #111; color: #fff; font-size: 11px; font-family: ui-monospace, Menlo, Consolas, monospace;
|
|
172
|
+
max-width: 60vw; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
173
|
+
.hover-label b { color: #ffd166; font-weight: 600; }
|
|
174
|
+
.drag { position: fixed; pointer-events: none; border: 2px dashed ${x}; background: rgba(255,61,113,.08); display: none; }
|
|
175
|
+
.markers { position: fixed; inset: 0; pointer-events: none; }
|
|
176
|
+
.mark { position: fixed; border: 2px solid ${x}; border-radius: 2px; }
|
|
177
|
+
.mark.box { border-style: dashed; }
|
|
178
|
+
.mark.pin { width: 14px; height: 14px; border-radius: 7px; background: ${x}; border: 2px solid #fff;
|
|
179
|
+
box-shadow: 0 0 0 2px ${x}; }
|
|
180
|
+
.mark.detached { opacity: .4; }
|
|
181
|
+
.num-badge { position: fixed; pointer-events: auto; cursor: pointer; width: 22px; height: 22px; border-radius: 11px;
|
|
182
|
+
background: ${x}; color: #fff; font-weight: 700; font-size: 12px; line-height: 22px; text-align: center;
|
|
183
|
+
box-shadow: 0 2px 6px rgba(0,0,0,.3); transform: translate(-50%, -50%); }
|
|
184
|
+
.hint { position: fixed; left: 50%; top: 12px; transform: translateX(-50%); pointer-events: none; padding: 6px 12px;
|
|
185
|
+
border-radius: 999px; background: rgba(17,17,17,.9); color: #fff; font-size: 12px; }
|
|
186
|
+
.hint[hidden] { display: none; }
|
|
187
|
+
${mt}
|
|
188
|
+
`,wo={select:"Select: click an element \xB7 \u2191 parent \xB7 \u2193 child \xB7 Esc cancel",box:"Box: drag a rectangle \xB7 Esc cancel",pin:"Pin: click a point \xB7 Esc cancel"},we=class{constructor(e){m(this,"host");m(this,"root");m(this,"store");m(this,"tool",null);m(this,"busy",!1);m(this,"open",!1);m(this,"candidate",null);m(this,"candidateLocked",!1);m(this,"dragStart",null);m(this,"raf",0);m(this,"launcherPos",{right:bt,bottom:bt});m(this,"launcher");m(this,"count");m(this,"dock");m(this,"toolbar");m(this,"panel");m(this,"sessions");m(this,"status");m(this,"layer");m(this,"hover");m(this,"hoverLabel");m(this,"drag");m(this,"markers");m(this,"hint");m(this,"chat");m(this,"tick",()=>{this.positionMarkers(),this.raf=requestAnimationFrame(this.tick)});this.store=e,this.host=document.createElement("div"),this.host.id="crt-host",this.host.setAttribute("data-crt",""),this.root=this.host.attachShadow({mode:"open"}),this.root.innerHTML=`
|
|
189
|
+
<style>${bo}</style>
|
|
190
|
+
<div class="markers" part="markers"></div>
|
|
191
|
+
<div class="layer" hidden>
|
|
192
|
+
<div class="hover"></div><div class="hover-label"></div><div class="drag"></div>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="hint" hidden></div>
|
|
195
|
+
<div class="dock" hidden>
|
|
196
|
+
<div class="status" hidden></div>
|
|
197
|
+
<div class="sessions" hidden></div>
|
|
198
|
+
<div class="panel" hidden></div>
|
|
199
|
+
<div class="toolbar" role="toolbar" aria-label="CRT tools">
|
|
200
|
+
<button type="button" data-tool="select" title="Select an element (F-8)">Select</button>
|
|
201
|
+
<button type="button" data-tool="box" title="Draw a box (F-9)">Box</button>
|
|
202
|
+
<button type="button" data-tool="pin" title="Drop a pin (F-10)">Pin</button>
|
|
203
|
+
<span class="sep"></span>
|
|
204
|
+
<span class="badge" data-count>0</span>
|
|
205
|
+
<button type="button" data-action="clear" title="Remove all annotations">Clear</button>
|
|
206
|
+
<button type="button" data-action="sessions" title="Recent intake sessions (F-30)">Sessions</button>
|
|
207
|
+
<span class="sep"></span>
|
|
208
|
+
<button type="button" data-action="quick" title="Quick note: Claude writes the task from your notes without a chat (F-14). Needs a note on every annotation.">Quick note</button>
|
|
209
|
+
<button type="button" class="primary" data-action="send" title="Capture and send to Claude (F-13)">Send to Claude</button>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
<button type="button" class="launcher" aria-label="Toggle Claude Review Tool (Ctrl/Cmd+Shift+.)">
|
|
213
|
+
CRT <span class="count">0</span>
|
|
214
|
+
</button>
|
|
215
|
+
`;let n=o=>this.root.querySelector(o);this.launcher=n(".launcher"),this.count=n(".launcher .count"),this.dock=n(".dock"),this.toolbar=n(".toolbar"),this.panel=n(".panel"),this.sessions=n(".sessions"),this.status=n(".status"),this.layer=n(".layer"),this.hover=n(".hover"),this.hoverLabel=n(".hover-label"),this.drag=n(".drag"),this.markers=n(".markers"),this.hint=n(".hint"),this.chat=new be(this.dock,{onVisibility:o=>{this.dock.classList.toggle("chat-open",o),o&&(this.sessions.hidden=!0,this.open||this.toggle(!0)),this.render()},onQuiet:o=>this.onQuiet(o)}),this.restoreLauncher(),this.wireLauncher(),this.wireToolbar(),this.wireLayer(),this.wireKeyboard(),this.store.subscribe(()=>this.render()),document.documentElement.appendChild(this.host),this.placeLauncher(),this.render(),this.chat.restore()}isOpen(){return this.open}toggle(e){this.open=e??!this.open,this.dock.hidden=!this.open,this.open||this.setTool(null),this.render()}currentTool(){return this.tool}setTool(e){if(!this.busy){this.tool=e,this.candidate=null,this.candidateLocked=!1,this.dragStart=null,this.layer.hidden=e===null,this.hover.style.display="none",this.hoverLabel.style.display="none",this.drag.style.display="none",this.hint.hidden=e===null,e&&(this.hint.textContent=wo[e],this.open||this.toggle(!0));for(let n of Array.from(this.toolbar.querySelectorAll("[data-tool]")))n.classList.toggle("active",n.dataset.tool===e)}}hoverAt(e,n){let o=this.elementAt(e,n);return this.setCandidate(o),o}async sendToClaude(e={}){let n=e.quick===!0;if(this.busy)throw new Error("already sending");if(!this.store.count())throw new Error("nothing to send: add an annotation first");if(n&&!this.canQuickNote())throw new Error("quick note needs a note on every annotation");this.busy=!0,this.setTool(null),this.sessions.hidden=!0,this.showStatus("Capturing page\u2026"),this.render();let o=this.chat.warmStart({quick:n}).catch(()=>null);try{let r=await pe(this.store);this.showStatus("Sending to Claude\u2026");let s=await ft(r);this.store.clear(),this.showStatus(`Capture saved: <code>${T(s.dir)}</code>`,!1,!n);try{let i=await o;i?await this.chat.attachCapture(i,s.id,{quick:n}):await this.chat.startFromCapture(s.id,{quick:n}),n&&this.showStatus(`Quick note sent \u2014 Claude is writing the task\u2026${wt()}`)}catch(i){this.showStatus(`Capture saved: <code>${T(s.dir)}</code> \u2014 but Claude did not start: ${T(i instanceof Error?i.message:String(i))}`,!0)}return s}catch(r){throw o.then(s=>s?this.chat.abandon(s):void 0),this.showStatus(`Send failed: ${T(r instanceof Error?r.message:String(r))}`,!0),r}finally{this.busy=!1,this.render()}}canQuickNote(){let e=this.store.all();return e.length>0&&e.every(n=>n.note.trim()!=="")}onQuiet(e){e.kind==="task"?this.showStatus(`Task <b>${T(e.id)}</b> written to <code>${T(e.path)}</code>${wt()}`):this.showStatus(`Claude needs you: ${T(e.reason)}`,!1,!0)}async toggleSessions(e){if(!(e??this.sessions.hidden)){this.sessions.hidden=!0;return}this.sessions.innerHTML='<div class="head"><span>Sessions</span><span class="spacer"></span><button type="button" data-sessions="close">\xD7</button></div><div class="empty">Loading\u2026</div>',this.sessions.hidden=!1,this.chat.isOpen()&&this.chat.show(!1),this.render();let o;try{o=await this.chat.listSessions()}catch(r){this.sessions.querySelector(".empty").textContent=`Could not list sessions: ${r instanceof Error?r.message:String(r)}`;return}this.renderSessions(o)}renderSessions(e){let n=this.chat.snapshot().sessionId,o=e.map(s=>{let i=document.createElement("button");i.type="button",i.className=`session${s.id===n?" current":""}`,i.dataset.session=s.id;let a=new Date(s.startedAt),l=Number.isNaN(a.getTime())?s.startedAt:a.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});i.innerHTML='<span class="sum"></span><span class="pill"></span><span class="meta"></span>',i.querySelector(".sum").textContent=s.summary??(s.captureId?`capture ${s.captureId}`:"warming up");let d=i.querySelector(".pill");return d.dataset.state=s.state,d.textContent=s.taskId??yo[s.state],i.querySelector(".meta").textContent=`${l}${s.quick?" \xB7 quick note":""}${s.url?` \xB7 ${xo(s.url)}`:""} \xB7 ${s.id.slice(0,8)}`,i}),r=this.sessions.querySelector(".head");if(this.sessions.replaceChildren(r,...o),!o.length){let s=document.createElement("div");s.className="empty",s.textContent="No sessions yet \u2014 annotate something and Send to Claude.",this.sessions.appendChild(s)}}restoreLauncher(){try{let e=localStorage.getItem(gt);if(e){let n=JSON.parse(e);Number.isFinite(n.right)&&Number.isFinite(n.bottom)&&(this.launcherPos=n)}}catch{}this.placeLauncher(),window.addEventListener("resize",()=>this.placeLauncher())}placeLauncher(){let e=xt(this.launcherPos.right,0,Math.max(0,window.innerWidth-60)),n=xt(this.launcherPos.bottom,0,Math.max(0,window.innerHeight-40));this.launcherPos={right:e,bottom:n},this.launcher.style.right=`${e}px`,this.launcher.style.bottom=`${n}px`,this.dock.style.right=`${e}px`,this.dock.style.bottom=`${n+this.launcher.offsetHeight+8}px`}wireLauncher(){let e=null,n=!1;this.launcher.addEventListener("pointerdown",r=>{r.button===0&&(e={x:r.clientX,y:r.clientY,...this.launcherPos},n=!1,this.launcher.setPointerCapture(r.pointerId))}),this.launcher.addEventListener("pointermove",r=>{if(!e)return;let s=r.clientX-e.x,i=r.clientY-e.y;!n&&Math.hypot(s,i)<4||(n=!0,this.launcherPos={right:e.right-s,bottom:e.bottom-i},this.placeLauncher())});let o=r=>{if(e)if(e=null,this.launcher.hasPointerCapture(r.pointerId)&&this.launcher.releasePointerCapture(r.pointerId),n)try{localStorage.setItem(gt,JSON.stringify(this.launcherPos))}catch{}else this.toggle()};this.launcher.addEventListener("pointerup",o),this.launcher.addEventListener("pointercancel",o),this.launcher.addEventListener("keydown",r=>{(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),this.toggle())})}wireToolbar(){this.toolbar.addEventListener("click",e=>{let n=e.target.closest("button");if(!n)return;let o=n.dataset.tool;if(o){this.setTool(this.tool===o?null:o);return}n.dataset.action==="clear"?(this.store.clear(),this.status.hidden=!0):n.dataset.action==="send"?this.sendToClaude().catch(()=>{}):n.dataset.action==="quick"?this.sendToClaude({quick:!0}).catch(()=>{}):n.dataset.action==="sessions"&&this.toggleSessions()}),this.sessions.addEventListener("click",e=>{let n=e.target.closest("button");n&&(n.dataset.sessions==="close"?this.sessions.hidden=!0:n.dataset.session&&this.chat.open(n.dataset.session))}),this.status.addEventListener("click",e=>{e.target.closest("button")?.dataset.status==="chat"&&this.chat.show(!0)}),this.panel.addEventListener("input",e=>{let n=e.target,o=Number(n.closest(".item")?.dataset.n);n.tagName==="TEXTAREA"&&o&&this.store.setNote(o,n.value)}),this.panel.addEventListener("click",e=>{let n=e.target.closest("button.del");if(!n)return;let o=Number(n.closest(".item")?.dataset.n);o&&this.store.remove(o)});for(let e of["keydown","keyup","keypress"])this.dock.addEventListener(e,n=>n.stopPropagation())}render(){let e=this.store.all(),n=e.length;this.count.textContent=String(n),this.count.classList.toggle("on",n>0),this.toolbar.querySelector("[data-count]").textContent=String(n);for(let o of Array.from(this.toolbar.querySelectorAll("button")))o.disabled=this.busy;this.toolbar.querySelector("[data-action=send]").disabled=this.busy||n===0,this.toolbar.querySelector("[data-action=quick]").disabled=this.busy||!this.canQuickNote(),this.toolbar.querySelector("[data-action=clear]").disabled=this.busy||n===0,this.toolbar.querySelector("[data-action=sessions]").classList.toggle("active",!this.sessions.hidden),this.renderPanel(e),this.renderMarkers(e),n>0&&!this.raf&&this.tick(),n===0&&this.raf&&(cancelAnimationFrame(this.raf),this.raf=0)}renderPanel(e){this.panel.hidden=!this.open||e.length===0||this.chat.isOpen()||!this.sessions.hidden;let o=this.root.activeElement?.closest(".item")?.dataset.n,r=new Map;for(let i of Array.from(this.panel.querySelectorAll(".item")))r.set(i.dataset.id,i);let s=document.createDocumentFragment();for(let i of e){let a=r.get(i.id);a||(a=document.createElement("div"),a.className="item",a.dataset.id=i.id,a.innerHTML=`<span class="num"></span><span class="label"></span><button type="button" class="del" title="Delete">\xD7</button><textarea rows="2" placeholder="What's wrong or wanted here?"></textarea>`),a.dataset.n=String(i.n),a.querySelector(".num").textContent=String(i.n),a.querySelector(".label").textContent=vo(i);let l=a.querySelector("textarea");l.value!==i.note&&o!==String(i.n)&&(l.value=i.note),s.appendChild(a)}this.panel.replaceChildren(s)}renderMarkers(e){let n=document.createDocumentFragment();for(let o of e){let r=document.createElement("div");r.className=`mark ${o.kind}`,r.dataset.n=String(o.n);let s=document.createElement("button");s.type="button",s.className="num-badge",s.dataset.n=String(o.n),s.textContent=String(o.n),s.title=o.note||`Annotation ${o.n}`,s.addEventListener("click",()=>this.focusNote(o.n)),n.append(r,s)}this.markers.replaceChildren(n),this.positionMarkers()}positionMarkers(){let e=this.store.all(),n=this.markers.querySelectorAll(".mark"),o=this.markers.querySelectorAll(".num-badge");e.forEach((r,s)=>{let i=n[s],a=o[s];if(!i||!a)return;let l=Z(r.pageRect),d=!1;if(r.kind==="select")if(r.element?.isConnected){let c=r.element.getBoundingClientRect();l={x:c.left,y:c.top,width:c.width,height:c.height}}else d=!0;i.classList.toggle("detached",d),r.kind==="pin"?(i.style.left=`${l.x-7}px`,i.style.top=`${l.y-7}px`,a.style.left=`${l.x+16}px`,a.style.top=`${l.y-14}px`):(i.style.left=`${l.x}px`,i.style.top=`${l.y}px`,i.style.width=`${l.width}px`,i.style.height=`${l.height}px`,a.style.left=`${l.x}px`,a.style.top=`${l.y}px`)})}focusNote(e){this.open||this.toggle(!0),this.render(),this.panel.querySelector(`.item[data-n="${e}"] textarea`)?.focus()}showStatus(e,n=!1,o=!1){this.status.innerHTML=e,this.status.classList.toggle("error",n),this.status.hidden=!1,this.open||this.toggle(!0),o&&setTimeout(()=>this.status.hidden=!0,15e3)}elementAt(e,n){let o=document.elementsFromPoint(e,n).find(r=>!A(r)&&!r.closest("#crt-host"));return o&&o!==document.documentElement?o:null}setCandidate(e){if(this.candidate=e,!e){this.hover.style.display="none",this.hoverLabel.style.display="none";return}let n=e.getBoundingClientRect();Object.assign(this.hover.style,{display:"block",left:`${n.left}px`,top:`${n.top}px`,width:`${n.width}px`,height:`${n.height}px`});let o=Ne(e);this.hoverLabel.innerHTML=o?`<b>${T(o)}</b> ${T(G(e))}`:T(G(e));let r=n.top>28?n.top-26:n.bottom+4;Object.assign(this.hoverLabel.style,{display:"block",left:`${Math.max(4,Math.min(n.left,window.innerWidth-200))}px`,top:`${Math.min(r,window.innerHeight-24)}px`})}wireLayer(){this.layer.addEventListener("pointermove",e=>{if(this.tool==="select"){if(this.candidateLocked){if(Math.hypot(e.movementX,e.movementY)<3)return;this.candidateLocked=!1}this.setCandidate(this.elementAt(e.clientX,e.clientY))}else if(this.tool==="box"&&this.dragStart){let n=yt(this.dragStart,{x:e.clientX,y:e.clientY});Object.assign(this.drag.style,{display:"block",left:`${n.x}px`,top:`${n.y}px`,width:`${n.width}px`,height:`${n.height}px`})}}),this.layer.addEventListener("pointerdown",e=>{e.button===0&&(e.preventDefault(),this.tool==="box"&&(this.dragStart={x:e.clientX,y:e.clientY},this.layer.setPointerCapture(e.pointerId)))}),this.layer.addEventListener("pointerup",e=>{if(e.button===0){if(e.preventDefault(),this.tool==="select"){let n=this.candidate??this.elementAt(e.clientX,e.clientY);n&&this.commitSelect(n)}else if(this.tool==="pin")this.commitPin(e.clientX,e.clientY);else if(this.tool==="box"&&this.dragStart){let n=yt(this.dragStart,{x:e.clientX,y:e.clientY});this.dragStart=null,this.drag.style.display="none",n.width>=4&&n.height>=4&&this.commitBox(n)}}}),this.layer.addEventListener("pointerleave",()=>{this.tool==="select"&&!this.candidateLocked&&this.setCandidate(null)}),this.layer.addEventListener("contextmenu",e=>e.preventDefault())}wireKeyboard(){document.addEventListener("keydown",e=>{if((e.ctrlKey||e.metaKey)&&e.shiftKey&&(e.code==="Period"||e.key==="."||e.key===">")){e.preventDefault(),e.stopPropagation(),this.toggle();return}if(this.tool){if(e.key==="Escape"){e.preventDefault(),e.stopPropagation(),this.setTool(null);return}if(this.tool==="select"&&(e.key==="ArrowUp"||e.key==="ArrowDown"||e.key==="Enter")){if(e.preventDefault(),e.stopPropagation(),e.key==="Enter"){this.candidate&&this.commitSelect(this.candidate);return}let n=this.candidate;if(!n)return;let o=e.key==="ArrowUp"?n.parentElement&&n.parentElement!==document.documentElement?n.parentElement:null:Array.from(n.children).find(r=>!A(r))??null;o&&(this.candidateLocked=!0,this.setCandidate(o))}}},!0)}commitSelect(e){let n=this.store.addSelect(e);this.setTool(null),this.focusNote(n.n)}commitBox(e){let n=this.store.addBox(e);this.setTool(null),this.focusNote(n.n)}commitPin(e,n){let o=this.store.addPin(e,n);this.setTool(null),this.focusNote(o.n)}},yo={starting:"starting",running:"thinking\u2026",waiting:"needs permission",idle:"your turn",ended:"ended",error:"error"};function wt(){return'<button type="button" data-status="chat">open chat</button>'}function xo(t){try{let e=new URL(t);return e.pathname+e.search}catch{return t}}function vo(t){if(t.kind==="select"){let e=t.elementInfo,n=e?.components[0]?.name,o=t.element?G(t.element):e?.selector??"element";return n?`${n} \xB7 ${o}`:o}if(t.kind==="box"){let e=t.elements[0]?.info,n=e?`${e.tag}${e.id?"#"+e.id:""}`:"region";return`Box ${Math.round(t.pageRect.width)}\xD7${Math.round(t.pageRect.height)} \xB7 ${t.elements.length} element${t.elements.length===1?"":"s"} (${n})`}return`Pin at ${Math.round(t.pageRect.x)}, ${Math.round(t.pageRect.y)}`}function yt(t,e){return{x:Math.min(t.x,e.x),y:Math.min(t.y,e.y),width:Math.abs(t.x-e.x),height:Math.abs(t.y-e.y)}}function xt(t,e,n){return Math.max(e,Math.min(n,t))}function T(t){return t.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}Fe();Be();function U(t){if(typeof t!="string")return t;let e=document.querySelector(t);if(!e)throw new Error(`__crt: no element matches ${t}`);return e}function vt(){if(document.getElementById("crt-host"))return;let t=new J,e=new we(t),n=r=>({n:r.n,kind:r.kind,note:r.note,label:r.elementInfo?.selector??null,detached:r.kind==="select"?!r.element?.isConnected:!1}),o={version:1,toggle:r=>e.toggle(r),isOpen:()=>e.isOpen(),setTool:r=>e.setTool(r),currentTool:()=>e.currentTool(),hoverAt:(r,s)=>e.hoverAt(r,s),annotations:()=>t.all().map(n),addSelect:r=>t.addSelect(U(r)).n,addBox:r=>t.addBox(r).n,addPin:(r,s)=>t.addPin(r,s).n,setNote:(r,s)=>t.setNote(r,s),remove:r=>t.remove(r),clear:()=>t.clear(),capture:async()=>{let r=await pe(t);return{bundle:r.bundle,imageNames:Object.keys(r.images)}},send:r=>e.sendToClaude(r),canQuickNote:()=>e.canQuickNote(),selectorFor:r=>z(U(r)),xpathFor:r=>V(U(r)),describe:r=>N(U(r)),componentsFor:r=>O(U(r)),framework:()=>X(),consoleEntries:()=>oe(),clearConsole:()=>De(),networkEntries:()=>ie(),clearNetwork:()=>Ue(),crtOrigin:()=>ee,scriptTagMode:()=>He,sessions:{toggle:r=>e.toggleSessions(r),list:()=>e.chat.listSessions()},chat:{snapshot:()=>e.chat.snapshot(),isOpen:()=>e.chat.isOpen(),open:r=>e.chat.open(r),show:r=>e.chat.show(r),send:r=>e.chat.send(r),respond:(r,s)=>e.chat.respond(r,s),interrupt:()=>e.chat.interrupt(),discard:()=>e.chat.discard()}};Object.assign(window.__crt,o)}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",vt,{once:!0}):vt();})();
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intake permission policy (PRD F-26, N-4, N-5). Pure: given a tool call, say whether the server
|
|
3
|
+
* allows it silently, denies it, or asks the developer in the panel. The session runs in Claude
|
|
4
|
+
* Code's `default` permission mode, so this only sees calls the CLI would otherwise prompt for.
|
|
5
|
+
*
|
|
6
|
+
* • Read / Glob / Grep / other read-only built-ins → allow
|
|
7
|
+
* • Bash with a read-only git command (status, log, diff, show, …) and no shell operators → allow
|
|
8
|
+
* • Write / Edit / NotebookEdit whose path resolves under `<root>/.crt/` → allow (N-5)
|
|
9
|
+
* • CRT's own MCP tool (`mcp__crt__*`) → allow
|
|
10
|
+
* • WebFetch / WebSearch → deny (nothing leaves the machine, N-4)
|
|
11
|
+
* • everything else → ask (Allow / Deny card in the panel; 5-minute timeout defaults to deny)
|
|
12
|
+
*/
|
|
13
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
14
|
+
export const PERMISSION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
15
|
+
const READ_ONLY_TOOLS = new Set(["Read", "Glob", "Grep", "LS", "TodoWrite", "TodoRead", "ToolSearch", "Skill", "Task", "Agent"]);
|
|
16
|
+
const OFF_TOOLS = new Set(["WebFetch", "WebSearch"]);
|
|
17
|
+
const FILE_WRITE_TOOLS = new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
18
|
+
const CRT_MCP_PREFIX = "mcp__crt__";
|
|
19
|
+
/** git subcommands that never change the working tree, index or refs. */
|
|
20
|
+
const GIT_READ_ONLY = new Set([
|
|
21
|
+
"status",
|
|
22
|
+
"log",
|
|
23
|
+
"diff",
|
|
24
|
+
"show",
|
|
25
|
+
"blame",
|
|
26
|
+
"branch",
|
|
27
|
+
"rev-parse",
|
|
28
|
+
"ls-files",
|
|
29
|
+
"ls-tree",
|
|
30
|
+
"describe",
|
|
31
|
+
"tag",
|
|
32
|
+
"remote",
|
|
33
|
+
"shortlog",
|
|
34
|
+
"grep",
|
|
35
|
+
"cat-file",
|
|
36
|
+
"reflog",
|
|
37
|
+
"stash list",
|
|
38
|
+
"worktree list",
|
|
39
|
+
"config --get",
|
|
40
|
+
"config --list",
|
|
41
|
+
"config -l",
|
|
42
|
+
]);
|
|
43
|
+
/** `git branch` / `git tag` only list when every argument is one of these (positionals need a listing flag). */
|
|
44
|
+
const BRANCH_LIST_FLAGS = /^(-[arvli]+|-n\d*|--(list|all|remotes|verbose|show-current|contains|no-contains|merged|no-merged|points-at|sort|format|column|no-column|ignore-case)(=.*)?)$/;
|
|
45
|
+
const TAG_LIST_FLAGS = /^(-[li]+|-n\d*|--(list|contains|no-contains|merged|no-merged|points-at|sort|format|column|no-column|ignore-case)(=.*)?)$/;
|
|
46
|
+
const SHELL_OPERATORS = /[|;&<>`$]|\n/;
|
|
47
|
+
export function decidePermission(toolName, input, projectRoot) {
|
|
48
|
+
if (READ_ONLY_TOOLS.has(toolName) || toolName.startsWith(CRT_MCP_PREFIX))
|
|
49
|
+
return { kind: "allow" };
|
|
50
|
+
if (OFF_TOOLS.has(toolName))
|
|
51
|
+
return { kind: "deny", reason: `${toolName} is disabled during CRT intake (nothing leaves the machine)` };
|
|
52
|
+
if (toolName === "Bash") {
|
|
53
|
+
const command = typeof input.command === "string" ? input.command : "";
|
|
54
|
+
return isReadOnlyGit(command) ? { kind: "allow" } : { kind: "ask" };
|
|
55
|
+
}
|
|
56
|
+
if (FILE_WRITE_TOOLS.has(toolName)) {
|
|
57
|
+
const target = typeof input.file_path === "string" ? input.file_path : typeof input.notebook_path === "string" ? input.notebook_path : "";
|
|
58
|
+
return target && isUnderCrtDir(target, projectRoot) ? { kind: "allow" } : { kind: "ask" };
|
|
59
|
+
}
|
|
60
|
+
return { kind: "ask" };
|
|
61
|
+
}
|
|
62
|
+
/** `git <read-only subcommand> …` with no pipes, redirects, chaining or substitution. */
|
|
63
|
+
export function isReadOnlyGit(command) {
|
|
64
|
+
const c = command.trim();
|
|
65
|
+
if (!c || SHELL_OPERATORS.test(c))
|
|
66
|
+
return false;
|
|
67
|
+
const m = /^git\s+(?:(?:-C\s+\S+|--no-pager|-c\s+\S+)\s+)*(\S+)(?:\s+(.*))?$/.exec(c);
|
|
68
|
+
if (!m)
|
|
69
|
+
return false;
|
|
70
|
+
const sub = m[1];
|
|
71
|
+
const args = (m[2] ?? "").split(/\s+/).filter(Boolean);
|
|
72
|
+
const two = args[0] ? `${sub} ${args[0]}` : "";
|
|
73
|
+
if (!GIT_READ_ONLY.has(sub) && !GIT_READ_ONLY.has(two))
|
|
74
|
+
return false;
|
|
75
|
+
if (sub === "stash" || sub === "worktree" || sub === "config")
|
|
76
|
+
return GIT_READ_ONLY.has(two);
|
|
77
|
+
if (sub === "branch" || sub === "tag") {
|
|
78
|
+
const flag = sub === "branch" ? BRANCH_LIST_FLAGS : TAG_LIST_FLAGS;
|
|
79
|
+
const listing = args.some((a) => flag.test(a));
|
|
80
|
+
return args.every((a) => flag.test(a) || (listing && !a.startsWith("-")));
|
|
81
|
+
}
|
|
82
|
+
if (sub === "remote")
|
|
83
|
+
return args.length === 0 || ["-v", "--verbose", "show", "get-url"].includes(args[0]);
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
/** True when `target` (absolute or relative to the root) resolves inside `<root>/.crt/`. */
|
|
87
|
+
export function isUnderCrtDir(target, projectRoot) {
|
|
88
|
+
const root = resolve(projectRoot);
|
|
89
|
+
const abs = isAbsolute(target) ? resolve(target) : resolve(root, target);
|
|
90
|
+
const crt = resolve(root, ".crt");
|
|
91
|
+
const rel = relative(crt, abs);
|
|
92
|
+
if (rel === "" || isAbsolute(rel))
|
|
93
|
+
return false;
|
|
94
|
+
return rel !== ".." && !rel.startsWith(`..${sep}`);
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAK/D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnD,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACjI,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AACrD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;AACjF,MAAM,cAAc,GAAG,YAAY,CAAC;AAEpC,yEAAyE;AACzE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,QAAQ;IACR,KAAK;IACL,MAAM;IACN,MAAM;IACN,OAAO;IACP,QAAQ;IACR,WAAW;IACX,UAAU;IACV,SAAS;IACT,UAAU;IACV,KAAK;IACL,QAAQ;IACR,UAAU;IACV,MAAM;IACN,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,eAAe;IACf,cAAc;IACd,eAAe;IACf,WAAW;CACZ,CAAC,CAAC;AACH,gHAAgH;AAChH,MAAM,iBAAiB,GAAG,8JAA8J,CAAC;AACzL,MAAM,cAAc,GAAG,0HAA0H,CAAC;AAClJ,MAAM,eAAe,GAAG,cAAc,CAAC;AAEvC,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,KAA8B,EAAE,WAAmB;IACpG,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACnG,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,6DAA6D,EAAE,CAAC;IACvI,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IACtE,CAAC;IACD,IAAI,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1I,OAAO,MAAM,IAAI,aAAa,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC5F,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,CAAC,GAAG,mEAAmE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtF,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;IAClB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACrE,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7F,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,cAAc,CAAC;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;IAC5G,OAAO,IAAI,CAAC;AACd,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,aAAa,CAAC,MAAc,EAAE,WAAmB;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzE,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,IAAI,GAAG,KAAK,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAChD,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;AACrD,CAAC"}
|
package/dist/project.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project root detection (PRD §5.1, F-4 /__crt/health, N-5).
|
|
3
|
+
* The root is the nearest ancestor of the launch directory that contains `.git`
|
|
4
|
+
* (a directory, or a file for worktrees); fallback is the launch directory itself.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { dirname, join, resolve } from "node:path";
|
|
8
|
+
export function findProjectRoot(start = process.cwd()) {
|
|
9
|
+
let dir = resolve(start);
|
|
10
|
+
for (;;) {
|
|
11
|
+
if (existsSync(join(dir, ".git")))
|
|
12
|
+
return dir;
|
|
13
|
+
const parent = dirname(dir);
|
|
14
|
+
if (parent === dir)
|
|
15
|
+
return resolve(start);
|
|
16
|
+
dir = parent;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,UAAU,eAAe,CAAC,QAAgB,OAAO,CAAC,GAAG,EAAE;IAC3D,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACzB,SAAS,CAAC;QACR,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,KAAK,GAAG;YAAE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1C,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
|