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.
@@ -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 inputEl = this.shadowRoot?.querySelector(".popover-input");
7677
+ const textareaEl = this.shadowRoot?.querySelector(".popover-input");
7678
7678
  if (!popoverEl || !element) return;
7679
- inputEl?.focus();
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} element(s) in the browser. Use the \`annotator_get_selected_elements\` tool to retrieve them and modify the code.`;
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 selected elements in the browser (session: ${this.sessionId}). Use the \`annotator_get_selected_elements\` tool to retrieve them and modify the code.`;
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
- <input
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.4), 0 0 0 1px rgba(255, 255, 255, 0.08);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-ai-annotator",
3
- "version": "1.1.9",
3
+ "version": "1.1.10",
4
4
  "description": "AI-powered element annotator for Vite - Pick elements and get instant AI code modifications",
5
5
  "type": "module",
6
6
  "main": "dist/vite-plugin.js",