vite-plugin-ai-annotator 1.1.9 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/annotator-toolbar.js +22 -10
- package/dist/index.cjs +1 -1
- package/package.json +1 -1
|
@@ -7674,9 +7674,13 @@
|
|
|
7674
7674
|
document.addEventListener("keydown", this.handlePopoverKeydown);
|
|
7675
7675
|
this.updateComplete.then(() => {
|
|
7676
7676
|
const popoverEl = this.shadowRoot?.querySelector(".popover");
|
|
7677
|
-
const
|
|
7677
|
+
const textareaEl = this.shadowRoot?.querySelector(".popover-input");
|
|
7678
7678
|
if (!popoverEl || !element) return;
|
|
7679
|
-
|
|
7679
|
+
if (textareaEl) {
|
|
7680
|
+
textareaEl.focus();
|
|
7681
|
+
textareaEl.style.height = "auto";
|
|
7682
|
+
textareaEl.style.height = Math.min(textareaEl.scrollHeight, 120) + "px";
|
|
7683
|
+
}
|
|
7680
7684
|
this.popoverCleanup = autoUpdate(element, popoverEl, () => {
|
|
7681
7685
|
computePosition2(element, popoverEl, {
|
|
7682
7686
|
strategy: "fixed",
|
|
@@ -7696,7 +7700,7 @@
|
|
|
7696
7700
|
});
|
|
7697
7701
|
}
|
|
7698
7702
|
handlePopoverInputKeydown(e5) {
|
|
7699
|
-
if (e5.key === "Enter") {
|
|
7703
|
+
if (e5.key === "Enter" && (e5.metaKey || e5.ctrlKey)) {
|
|
7700
7704
|
e5.preventDefault();
|
|
7701
7705
|
this.hideCommentPopover();
|
|
7702
7706
|
} else if (e5.key === "Escape") {
|
|
@@ -7717,6 +7721,8 @@
|
|
|
7717
7721
|
const target = e5.target;
|
|
7718
7722
|
const comment = target.value;
|
|
7719
7723
|
const element = this.commentPopover.element;
|
|
7724
|
+
target.style.height = "auto";
|
|
7725
|
+
target.style.height = Math.min(target.scrollHeight, 120) + "px";
|
|
7720
7726
|
this.commentPopover = { ...this.commentPopover, comment };
|
|
7721
7727
|
if (element) {
|
|
7722
7728
|
const hasComment = comment.trim().length > 0;
|
|
@@ -7777,7 +7783,7 @@
|
|
|
7777
7783
|
this.showToast("No elements selected");
|
|
7778
7784
|
return;
|
|
7779
7785
|
}
|
|
7780
|
-
const text = `I have selected ${elements.length}
|
|
7786
|
+
const text = `I have selected ${elements.length} feedback item(s) in the browser. Use the \`annotator_get_feedback\` tool to retrieve them and modify the code.`;
|
|
7781
7787
|
try {
|
|
7782
7788
|
await navigator.clipboard.writeText(text);
|
|
7783
7789
|
this.showToast(`Copied ${elements.length} element(s)`);
|
|
@@ -7845,7 +7851,7 @@
|
|
|
7845
7851
|
this.showToast("No session ID");
|
|
7846
7852
|
return;
|
|
7847
7853
|
}
|
|
7848
|
-
const text = `I have
|
|
7854
|
+
const text = `I have feedback in the browser (session: ${this.sessionId}). Use the \`annotator_get_feedback\` tool to retrieve them.`;
|
|
7849
7855
|
try {
|
|
7850
7856
|
await navigator.clipboard.writeText(text);
|
|
7851
7857
|
this.showToast("Copied!");
|
|
@@ -7920,14 +7926,14 @@
|
|
|
7920
7926
|
|
|
7921
7927
|
${this.commentPopover.visible ? x`
|
|
7922
7928
|
<div class="popover">
|
|
7923
|
-
<
|
|
7924
|
-
type="text"
|
|
7929
|
+
<textarea
|
|
7925
7930
|
class="popover-input"
|
|
7926
|
-
placeholder="Add a note..."
|
|
7931
|
+
placeholder="Add a note... (⌘↵ to close)"
|
|
7927
7932
|
.value=${this.commentPopover.comment}
|
|
7928
7933
|
@input=${this.handlePopoverInput}
|
|
7929
7934
|
@keydown=${this.handlePopoverInputKeydown}
|
|
7930
|
-
|
|
7935
|
+
rows="1"
|
|
7936
|
+
></textarea>
|
|
7931
7937
|
<div class="popover-actions">
|
|
7932
7938
|
<button class="popover-btn danger" @click=${this.removeSelectedElement} title="Remove selection">
|
|
7933
7939
|
${this.renderTrashIcon()}
|
|
@@ -8053,8 +8059,9 @@
|
|
|
8053
8059
|
display: flex;
|
|
8054
8060
|
align-items: stretch;
|
|
8055
8061
|
background: #1a1a1a;
|
|
8062
|
+
border: 1px solid rgba(99, 102, 241, 0.5);
|
|
8056
8063
|
border-radius: 8px;
|
|
8057
|
-
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.
|
|
8064
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), 0 0 20px rgba(99, 102, 241, 0.3), 0 0 40px rgba(99, 102, 241, 0.1);
|
|
8058
8065
|
overflow: hidden;
|
|
8059
8066
|
animation: popover-in 0.15s ease-out;
|
|
8060
8067
|
}
|
|
@@ -8074,6 +8081,8 @@
|
|
|
8074
8081
|
flex: 1;
|
|
8075
8082
|
min-width: 180px;
|
|
8076
8083
|
max-width: 260px;
|
|
8084
|
+
min-height: 38px;
|
|
8085
|
+
max-height: 120px;
|
|
8077
8086
|
padding: 10px 12px;
|
|
8078
8087
|
border: none;
|
|
8079
8088
|
background: transparent;
|
|
@@ -8081,6 +8090,9 @@
|
|
|
8081
8090
|
font-size: 13px;
|
|
8082
8091
|
font-family: inherit;
|
|
8083
8092
|
outline: none;
|
|
8093
|
+
resize: none;
|
|
8094
|
+
overflow-y: auto;
|
|
8095
|
+
line-height: 1.4;
|
|
8084
8096
|
}
|
|
8085
8097
|
|
|
8086
8098
|
.popover-input::placeholder {
|
package/dist/index.cjs
CHANGED
|
@@ -111,7 +111,7 @@ const toolbar = document.createElement('annotator-toolbar');
|
|
|
111
111
|
toolbar.setAttribute('ws-endpoint', '${e.replace("http://","ws://").replace("https://","wss://")}');
|
|
112
112
|
toolbar.setAttribute('verbose', '${n}');
|
|
113
113
|
document.body.prepend(toolbar);
|
|
114
|
-
`;i.send(s+u)}catch(a){console.error("Error reading annotator-toolbar.js:",a),i.status(404).send("File not found")}}),t.get("/health",(r,i)=>{i.json({status:"ok",sessions:Hn.size})}),t.get("/api/sessions",(r,i)=>{i.json(Zp())})}function zce(t,e){t.on("connection",n=>{if(n.handshake.query.clientType==="mcp"){Rce(n,e);return}let i=Tce(),a={id:i,url:"",title:"",connectedAt:Date.now(),lastActivity:Date.now()},o=Qq(n);Hn.set(i,{socket:n,rpc:o,session:a}),e.log(`Browser connected: ${i} (total: ${Hn.size})`),o.handle.getSessions(async()=>Zp()),o.handle.ping(async()=>"pong"),o.handle.rpcError(s=>{e.error("RPC Error:",s)}),n.emit("connected",{sessionId:i}),n.on("pageContextChanged",s=>{a.url=s.url,a.title=s.title,a.lastActivity=Date.now()}),n.on("disconnect",()=>{o.dispose(),Hn.delete(i),e.log(`Browser disconnected: ${i} (total: ${Hn.size})`)})})}function Rce(t,e){e.log("MCP client connected"),t.on("mcp:listSessions",n=>{n({success:!0,data:Zp()})}),t.on("mcp:getPageContext",async(n,r)=>{let i=St(n);if("error"in i){r({success:!1,error:i.error});return}try{let a=await i.rpc.client.getPageContext(1e4);Ct(a)?r({success:!1,error:a.message}):r({success:!0,data:a})}catch(a){r({success:!1,error:a instanceof Error?a.message:String(a)})}}),t.on("mcp:triggerSelection",async(n,r,i,a,o)=>{let s=St(n);if("error"in s){o({success:!1,error:s.error});return}try{let c=await s.rpc.client.triggerSelection(r,i,a,1e4);Ct(c)?o({success:!1,error:c.message}):o({success:!0,data:c})}catch(c){o({success:!1,error:c instanceof Error?c.message:String(c)})}}),t.on("mcp:getSelectedElements",async(n,r)=>{let i=St(n);if("error"in i){r({success:!1,error:i.error});return}try{let a=await i.rpc.client.getSelectedElements(15e3);Ct(a)?r({success:!1,error:a.message}):r({success:!0,data:a})}catch(a){r({success:!1,error:a instanceof Error?a.message:String(a)})}}),t.on("mcp:captureScreenshot",async(n,r,i,a,o,s)=>{let c=St(n);if("error"in c){s({success:!1,error:c.error});return}try{let u=await c.rpc.client.captureScreenshot(r,i,a,o,3e4);Ct(u)?s({success:!1,error:u.message}):s({success:!0,data:u})}catch(u){s({success:!1,error:u instanceof Error?u.message:String(u)})}}),t.on("mcp:clearSelection",async(n,r)=>{let i=St(n);if("error"in i){r({success:!1,error:i.error});return}i.rpc.client.clearSelection(),r({success:!0})}),t.on("mcp:injectCSS",async(n,r,i)=>{let a=St(n);if("error"in a){i({success:!1,error:a.error});return}try{let o=await a.rpc.client.injectCSS(r,1e4);Ct(o)?i({success:!1,error:o.message}):i({success:!0,data:o})}catch(o){i({success:!1,error:o instanceof Error?o.message:String(o)})}}),t.on("mcp:injectJS",async(n,r,i)=>{let a=St(n);if("error"in a){i({success:!1,error:a.error});return}try{let o=await a.rpc.client.injectJS(r,15e3);Ct(o)?i({success:!1,error:o.message}):i({success:!0,data:o})}catch(o){i({success:!1,error:o instanceof Error?o.message:String(o)})}}),t.on("mcp:getConsole",async(n,r,i)=>{let a=St(n);if("error"in a){i({success:!1,error:a.error});return}try{let o=await a.rpc.client.getConsole(r,15e3);Ct(o)?i({success:!1,error:o.message}):i({success:!0,data:o})}catch(o){i({success:!1,error:o instanceof Error?o.message:String(o)})}}),t.on("disconnect",()=>{e.log("MCP client disconnected")})}function St(t){let e=jce(t);if(!e){let n=Zp();return n.length===0?{error:"No browser connected. Add the annotator script to your webpage."}:{error:`Multiple sessions available. Specify sessionId. Available: ${n.map(r=>r.id).join(", ")}`}}return{rpc:e.rpc,sessionId:e.sessionId}}function Cce(){let t=new As({name:"ai-annotator",version:"1.0.0"}),e=Pe.string().optional().describe("Browser session ID (optional if only one session)");function n(r){return{content:[{type:"text",text:r}]}}return t.tool("annotator_list_sessions","List all connected browser sessions",{},async()=>{let r=Zp();return n(r.length>0?JSON.stringify(r,null,2):"No browser sessions connected. Add the annotator script to your webpage.")}),t.tool("annotator_get_page_context","Get current page context from browser session (URL, title, selection count)",{sessionId:e},async({sessionId:r})=>{let i=St(r);if("error"in i)return n(i.error);let a=await i.rpc.client.getPageContext(1e4);return Ct(a)?n(`Error: ${a.message}`):n(JSON.stringify(a,null,2))}),t.tool("annotator_select_element","Enter element inspection mode or select element by CSS/XPath selector",{sessionId:e,mode:Pe.enum(["inspect","selector"]).default("inspect").describe("Selection mode"),selector:Pe.string().optional().describe('CSS or XPath selector (required when mode is "selector")'),selectorType:Pe.enum(["css","xpath"]).default("css").describe("Type of selector")},async({sessionId:r,mode:i,selector:a,selectorType:o})=>{let s=St(r);if("error"in s)return n(s.error);let c=await s.rpc.client.triggerSelection(i,a,o,1e4);return Ct(c)?n(`Error: ${c.message}`):n(c.success?`Selection triggered. ${c.count} element(s) selected.`:`Selection failed: ${c.error}`)}),t.tool("annotator_get_selected_elements","Get data about currently selected elements in the browser",{sessionId:e},async({sessionId:r})=>{let i=St(r);if("error"in i)return n(i.error);let a=await i.rpc.client.getSelectedElements(15e3);return Ct(a)?n(`Error: ${a.message}`):n(a.length>0?JSON.stringify(a,null,2):"No elements selected. Use annotator_select_element first.")}),t.tool("annotator_capture_screenshot","Capture a screenshot of the viewport or a specific element. Returns the file path where the screenshot is saved.",{sessionId:e,type:Pe.enum(["viewport","element"]).default("viewport").describe("Type of screenshot"),selector:Pe.string().optional().describe("CSS selector for element screenshot"),format:Pe.enum(["png","jpeg"]).default("png").describe("Image format"),quality:Pe.number().min(0).max(1).default(.8).describe("Image quality (0-1)")},async({sessionId:r,type:i,selector:a,format:o,quality:s})=>{let c=St(r);if("error"in c)return n(c.error);let u=await c.rpc.client.captureScreenshot(i,a,o,s,3e4);if(Ct(u))return n(`Error: ${u.message}`);if(u.success&&u.base64){let p=Oce(u.base64,o);return n(p)}return n(`Screenshot failed: ${u.error}`)}),t.tool("annotator_clear_selection","Clear all selected elements in the browser",{sessionId:e},async({sessionId:r})=>{let i=St(r);return"error"in i?n(i.error):(i.rpc.client.clearSelection(),n("Selection cleared."))}),t.tool("annotator_inject_css","Inject CSS styles into the page",{sessionId:e,css:Pe.string().describe("CSS code to inject into the page")},async({sessionId:r,css:i})=>{let a=St(r);if("error"in a)return n(a.error);let o=await a.rpc.client.injectCSS(i,1e4);return Ct(o)?n(`Error: ${o.message}`):n(o.success?"CSS injected successfully.":`CSS injection failed: ${o.error}`)}),t.tool("annotator_inject_js","Inject and execute JavaScript code in the page context",{sessionId:e,code:Pe.string().describe("JavaScript code to execute in the page")},async({sessionId:r,code:i})=>{let a=St(r);if("error"in a)return n(a.error);let o=await a.rpc.client.injectJS(i,15e3);return Ct(o)?n(`Error: ${o.message}`):o.success?n(o.result!==void 0?`Result: ${JSON.stringify(o.result,null,2)}`:"JavaScript executed successfully (no return value)."):n(`JavaScript execution failed: ${o.error}`)}),t.tool("annotator_get_console","Get console logs captured from the browser",{sessionId:e,clear:Pe.boolean().default(!1).describe("Clear the console buffer after reading")},async({sessionId:r,clear:i})=>{let a=St(r);if("error"in a)return n(a.error);let o=await a.rpc.client.getConsole(i,15e3);return Ct(o)?n(`Error: ${o.message}`):n(o.length>0?JSON.stringify(o,null,2):"No console logs captured.")}),t}function Ace(t,e){let n=Cce(),r=new Map;t.all("/mcp",async(i,a)=>{let o=i.headers["mcp-session-id"],s;o&&r.has(o)?s=r.get(o):(s=new Wv({sessionIdGenerator:()=>crypto.randomUUID()}),await n.connect(s),s.onclose=()=>{for(let[c,u]of r.entries())if(u===s){r.delete(c),e.log(`MCP session closed: ${c}`);break}});try{await s.handleRequest(i,a,i.body);let c=a.getHeader("mcp-session-id");c&&!r.has(c)&&(r.set(c,s),e.log(`MCP session created: ${c}`))}catch(c){e.error("MCP request error:",c),a.headersSent||a.status(500).json({error:"MCP request failed"})}}),t.get("/mcp/info",(i,a)=>{a.json({name:"ai-annotator",version:"1.0.0",capabilities:{tools:!0},endpoint:"/mcp"})})}async function r9(t,e,n,r=!1){let i=e9(r),a=(0,CS.default)();a.use((0,n9.default)({origin:"*",methods:["GET","POST","OPTIONS"],allowedHeaders:["Content-Type","Authorization"]})),a.use(CS.default.json({limit:"10mb"})),Ice(a,n,r),Ace(a,i);let o=await Nce(a,t,e),s=new zR(o,{cors:{origin:"*",methods:["GET","POST"]},path:"/socket.io"});return zce(s,i),{app:a,server:o,io:s,port:t,listenAddress:e,publicAddress:n,verbose:r}}async function i9(t){return new Promise((e,n)=>{let r=!1,i=!1,a=!1;function o(){r&&i&&!a&&e()}Hn.forEach(({rpc:s})=>{s.dispose()}),Hn.clear(),t.io.close(s=>{s&&!a&&t.verbose&&console.error("Error closing Socket.IO server:",s),r=!0,o()}),t.server.listening?t.server.close(s=>{s&&!a?(a=!0,n(s)):(i=!0,o())}):(i=!0,o())})}function Nce(t,e,n){return new Promise((r,i)=>{let a=t.listen(e,n,()=>r(a));a.on("error",o=>{i(o)})})}var pD=require("net"),pg=require("fs"),ug=require("path");function Sue(){let t=[(0,ug.join)(__dirname,"..","package.json"),(0,ug.join)(__dirname,"package.json"),(0,ug.join)(process.cwd(),"package.json")];for(let e of t)if((0,pg.existsSync)(e))try{let n=JSON.parse((0,pg.readFileSync)(e,"utf-8"));if(n.name==="vite-plugin-ai-annotator"&&n.version)return n.version}catch{continue}return"0.0.0"}var Eue=Sue(),Et=process.argv.slice(2),$ue=Et[0];$ue==="mcp"?Promise.resolve().then(()=>(uD(),kue)).catch(t=>{console.error("Failed to start MCP CLI:",t),process.exit(1)}):Tue();async function Tue(){let t=Et.includes("--help")||Et.includes("-h"),e=Et.includes("--version")||Et.includes("-v"),n=Et.includes("--verbose")||Et.includes("-V"),r=Et.findIndex(m=>m==="--port"||m==="-p"),i=Et.findIndex(m=>m==="--listen"||m==="-l"),a=Et.findIndex(m=>m==="--public-address"||m==="-a");t&&(console.log(`
|
|
114
|
+
`;i.send(s+u)}catch(a){console.error("Error reading annotator-toolbar.js:",a),i.status(404).send("File not found")}}),t.get("/health",(r,i)=>{i.json({status:"ok",sessions:Hn.size})}),t.get("/api/sessions",(r,i)=>{i.json(Zp())})}function zce(t,e){t.on("connection",n=>{if(n.handshake.query.clientType==="mcp"){Rce(n,e);return}let i=Tce(),a={id:i,url:"",title:"",connectedAt:Date.now(),lastActivity:Date.now()},o=Qq(n);Hn.set(i,{socket:n,rpc:o,session:a}),e.log(`Browser connected: ${i} (total: ${Hn.size})`),o.handle.getSessions(async()=>Zp()),o.handle.ping(async()=>"pong"),o.handle.rpcError(s=>{e.error("RPC Error:",s)}),n.emit("connected",{sessionId:i}),n.on("pageContextChanged",s=>{a.url=s.url,a.title=s.title,a.lastActivity=Date.now()}),n.on("disconnect",()=>{o.dispose(),Hn.delete(i),e.log(`Browser disconnected: ${i} (total: ${Hn.size})`)})})}function Rce(t,e){e.log("MCP client connected"),t.on("mcp:listSessions",n=>{n({success:!0,data:Zp()})}),t.on("mcp:getPageContext",async(n,r)=>{let i=St(n);if("error"in i){r({success:!1,error:i.error});return}try{let a=await i.rpc.client.getPageContext(1e4);Ct(a)?r({success:!1,error:a.message}):r({success:!0,data:a})}catch(a){r({success:!1,error:a instanceof Error?a.message:String(a)})}}),t.on("mcp:triggerSelection",async(n,r,i,a,o)=>{let s=St(n);if("error"in s){o({success:!1,error:s.error});return}try{let c=await s.rpc.client.triggerSelection(r,i,a,1e4);Ct(c)?o({success:!1,error:c.message}):o({success:!0,data:c})}catch(c){o({success:!1,error:c instanceof Error?c.message:String(c)})}}),t.on("mcp:getSelectedElements",async(n,r)=>{let i=St(n);if("error"in i){r({success:!1,error:i.error});return}try{let a=await i.rpc.client.getSelectedElements(15e3);Ct(a)?r({success:!1,error:a.message}):r({success:!0,data:a})}catch(a){r({success:!1,error:a instanceof Error?a.message:String(a)})}}),t.on("mcp:captureScreenshot",async(n,r,i,a,o,s)=>{let c=St(n);if("error"in c){s({success:!1,error:c.error});return}try{let u=await c.rpc.client.captureScreenshot(r,i,a,o,3e4);Ct(u)?s({success:!1,error:u.message}):s({success:!0,data:u})}catch(u){s({success:!1,error:u instanceof Error?u.message:String(u)})}}),t.on("mcp:clearSelection",async(n,r)=>{let i=St(n);if("error"in i){r({success:!1,error:i.error});return}i.rpc.client.clearSelection(),r({success:!0})}),t.on("mcp:injectCSS",async(n,r,i)=>{let a=St(n);if("error"in a){i({success:!1,error:a.error});return}try{let o=await a.rpc.client.injectCSS(r,1e4);Ct(o)?i({success:!1,error:o.message}):i({success:!0,data:o})}catch(o){i({success:!1,error:o instanceof Error?o.message:String(o)})}}),t.on("mcp:injectJS",async(n,r,i)=>{let a=St(n);if("error"in a){i({success:!1,error:a.error});return}try{let o=await a.rpc.client.injectJS(r,15e3);Ct(o)?i({success:!1,error:o.message}):i({success:!0,data:o})}catch(o){i({success:!1,error:o instanceof Error?o.message:String(o)})}}),t.on("mcp:getConsole",async(n,r,i)=>{let a=St(n);if("error"in a){i({success:!1,error:a.error});return}try{let o=await a.rpc.client.getConsole(r,15e3);Ct(o)?i({success:!1,error:o.message}):i({success:!0,data:o})}catch(o){i({success:!1,error:o instanceof Error?o.message:String(o)})}}),t.on("disconnect",()=>{e.log("MCP client disconnected")})}function St(t){let e=jce(t);if(!e){let n=Zp();return n.length===0?{error:"No browser connected. Add the annotator script to your webpage."}:{error:`Multiple sessions available. Specify sessionId. Available: ${n.map(r=>r.id).join(", ")}`}}return{rpc:e.rpc,sessionId:e.sessionId}}function Cce(){let t=new As({name:"ai-annotator",version:"1.0.0"}),e=Pe.string().optional().describe("Browser session ID (optional if only one session)");function n(r){return{content:[{type:"text",text:r}]}}return t.tool("annotator_list_sessions","List all connected browser sessions",{},async()=>{let r=Zp();return n(r.length>0?JSON.stringify(r,null,2):"No browser sessions connected. Add the annotator script to your webpage.")}),t.tool("annotator_get_page_context","Get current page context from browser session (URL, title, selection count)",{sessionId:e},async({sessionId:r})=>{let i=St(r);if("error"in i)return n(i.error);let a=await i.rpc.client.getPageContext(1e4);return Ct(a)?n(`Error: ${a.message}`):n(JSON.stringify(a,null,2))}),t.tool("annotator_select_feedback","Enter feedback inspection mode or select feedback by CSS/XPath selector. Use this to let users mark UI elements they want to provide feedback on.",{sessionId:e,mode:Pe.enum(["inspect","selector"]).default("inspect").describe("Feedback selection mode"),selector:Pe.string().optional().describe('CSS or XPath selector (required when mode is "selector")'),selectorType:Pe.enum(["css","xpath"]).default("css").describe("Type of selector")},async({sessionId:r,mode:i,selector:a,selectorType:o})=>{let s=St(r);if("error"in s)return n(s.error);let c=await s.rpc.client.triggerSelection(i,a,o,1e4);return Ct(c)?n(`Error: ${c.message}`):n(c.success?`Feedback selection triggered. ${c.count} feedback item(s) selected.`:`Feedback selection failed: ${c.error}`)}),t.tool("annotator_get_feedback","Get data about currently selected feedback items in the browser. Returns details of UI elements the user has marked for feedback.",{sessionId:e},async({sessionId:r})=>{let i=St(r);if("error"in i)return n(i.error);let a=await i.rpc.client.getSelectedElements(15e3);return Ct(a)?n(`Error: ${a.message}`):n(a.length>0?JSON.stringify(a,null,2):"No feedback selected. Use annotator_select_feedback first.")}),t.tool("annotator_capture_screenshot","Capture a screenshot of the viewport or a specific element. Returns the file path where the screenshot is saved.",{sessionId:e,type:Pe.enum(["viewport","element"]).default("viewport").describe("Type of screenshot"),selector:Pe.string().optional().describe("CSS selector for element screenshot"),format:Pe.enum(["png","jpeg"]).default("png").describe("Image format"),quality:Pe.number().min(0).max(1).default(.8).describe("Image quality (0-1)")},async({sessionId:r,type:i,selector:a,format:o,quality:s})=>{let c=St(r);if("error"in c)return n(c.error);let u=await c.rpc.client.captureScreenshot(i,a,o,s,3e4);if(Ct(u))return n(`Error: ${u.message}`);if(u.success&&u.base64){let p=Oce(u.base64,o);return n(p)}return n(`Screenshot failed: ${u.error}`)}),t.tool("annotator_clear_feedback","Clear all selected feedback items in the browser. Removes all UI element selections made for feedback.",{sessionId:e},async({sessionId:r})=>{let i=St(r);return"error"in i?n(i.error):(i.rpc.client.clearSelection(),n("Feedback cleared."))}),t.tool("annotator_inject_css","Inject CSS styles into the page",{sessionId:e,css:Pe.string().describe("CSS code to inject into the page")},async({sessionId:r,css:i})=>{let a=St(r);if("error"in a)return n(a.error);let o=await a.rpc.client.injectCSS(i,1e4);return Ct(o)?n(`Error: ${o.message}`):n(o.success?"CSS injected successfully.":`CSS injection failed: ${o.error}`)}),t.tool("annotator_inject_js","Inject and execute JavaScript code in the page context",{sessionId:e,code:Pe.string().describe("JavaScript code to execute in the page")},async({sessionId:r,code:i})=>{let a=St(r);if("error"in a)return n(a.error);let o=await a.rpc.client.injectJS(i,15e3);return Ct(o)?n(`Error: ${o.message}`):o.success?n(o.result!==void 0?`Result: ${JSON.stringify(o.result,null,2)}`:"JavaScript executed successfully (no return value)."):n(`JavaScript execution failed: ${o.error}`)}),t.tool("annotator_get_console","Get console logs captured from the browser",{sessionId:e,clear:Pe.boolean().default(!1).describe("Clear the console buffer after reading")},async({sessionId:r,clear:i})=>{let a=St(r);if("error"in a)return n(a.error);let o=await a.rpc.client.getConsole(i,15e3);return Ct(o)?n(`Error: ${o.message}`):n(o.length>0?JSON.stringify(o,null,2):"No console logs captured.")}),t}function Ace(t,e){let n=Cce(),r=new Map;t.all("/mcp",async(i,a)=>{let o=i.headers["mcp-session-id"],s;o&&r.has(o)?s=r.get(o):(s=new Wv({sessionIdGenerator:()=>crypto.randomUUID()}),await n.connect(s),s.onclose=()=>{for(let[c,u]of r.entries())if(u===s){r.delete(c),e.log(`MCP session closed: ${c}`);break}});try{await s.handleRequest(i,a,i.body);let c=a.getHeader("mcp-session-id");c&&!r.has(c)&&(r.set(c,s),e.log(`MCP session created: ${c}`))}catch(c){e.error("MCP request error:",c),a.headersSent||a.status(500).json({error:"MCP request failed"})}}),t.get("/mcp/info",(i,a)=>{a.json({name:"ai-annotator",version:"1.0.0",capabilities:{tools:!0},endpoint:"/mcp"})})}async function r9(t,e,n,r=!1){let i=e9(r),a=(0,CS.default)();a.use((0,n9.default)({origin:"*",methods:["GET","POST","OPTIONS"],allowedHeaders:["Content-Type","Authorization"]})),a.use(CS.default.json({limit:"10mb"})),Ice(a,n,r),Ace(a,i);let o=await Nce(a,t,e),s=new zR(o,{cors:{origin:"*",methods:["GET","POST"]},path:"/socket.io"});return zce(s,i),{app:a,server:o,io:s,port:t,listenAddress:e,publicAddress:n,verbose:r}}async function i9(t){return new Promise((e,n)=>{let r=!1,i=!1,a=!1;function o(){r&&i&&!a&&e()}Hn.forEach(({rpc:s})=>{s.dispose()}),Hn.clear(),t.io.close(s=>{s&&!a&&t.verbose&&console.error("Error closing Socket.IO server:",s),r=!0,o()}),t.server.listening?t.server.close(s=>{s&&!a?(a=!0,n(s)):(i=!0,o())}):(i=!0,o())})}function Nce(t,e,n){return new Promise((r,i)=>{let a=t.listen(e,n,()=>r(a));a.on("error",o=>{i(o)})})}var pD=require("net"),pg=require("fs"),ug=require("path");function Sue(){let t=[(0,ug.join)(__dirname,"..","package.json"),(0,ug.join)(__dirname,"package.json"),(0,ug.join)(process.cwd(),"package.json")];for(let e of t)if((0,pg.existsSync)(e))try{let n=JSON.parse((0,pg.readFileSync)(e,"utf-8"));if(n.name==="vite-plugin-ai-annotator"&&n.version)return n.version}catch{continue}return"0.0.0"}var Eue=Sue(),Et=process.argv.slice(2),$ue=Et[0];$ue==="mcp"?Promise.resolve().then(()=>(uD(),kue)).catch(t=>{console.error("Failed to start MCP CLI:",t),process.exit(1)}):Tue();async function Tue(){let t=Et.includes("--help")||Et.includes("-h"),e=Et.includes("--version")||Et.includes("-v"),n=Et.includes("--verbose")||Et.includes("-V"),r=Et.findIndex(m=>m==="--port"||m==="-p"),i=Et.findIndex(m=>m==="--listen"||m==="-l"),a=Et.findIndex(m=>m==="--public-address"||m==="-a");t&&(console.log(`
|
|
115
115
|
AI Annotator - AI-powered web inspection tool
|
|
116
116
|
|
|
117
117
|
Usage:
|
package/package.json
CHANGED