@on-panda/serve 0.6.1 → 0.6.2
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/package.json +1 -1
- package/web/assets/{AudioPlugin-B9D2vg7i.js → AudioPlugin-CipdNRwL.js} +1 -1
- package/web/assets/{ImagePlugin-D-lN3l8G.js → ImagePlugin-DYc-WgIF.js} +1 -1
- package/web/assets/{VideoPlugin-CwcxLwKM.js → VideoPlugin-CqdH7JY2.js} +1 -1
- package/web/assets/browserAgentMcp-Eq47pjMf.js +38 -0
- package/web/assets/{index-VDofnkb1.js → index-CSSh_R5o.js} +97 -80
- package/web/assets/index-CmJzwRhj.css +10 -0
- package/web/assets/{index-BWq4H1Vs.js → index-DAeaRkCw.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/browserAgentMcp-Dpy7F3rj.js +0 -35
- package/web/assets/index-6pA5bJ5o.css +0 -10
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as U,r as W,c as F,m as V,w as q,b as G,d as Y,o as $,a as B,e as j,f as J}from"./index-
|
|
1
|
+
import{_ as U,r as W,c as F,m as V,w as q,b as G,d as Y,o as $,a as B,e as j,f as J}from"./index-CSSh_R5o.js";function y(c,t,e,i){return new(e||(e=Promise))(function(s,n){function r(o){try{l(i.next(o))}catch(h){n(h)}}function a(o){try{l(i.throw(o))}catch(h){n(h)}}function l(o){var h;o.done?s(o.value):(h=o.value,h instanceof e?h:new e(function(u){u(h)})).then(r,a)}l((i=i.apply(c,t||[])).next())})}let R=class{constructor(){this.listeners={}}on(t,e,i){if(this.listeners[t]||(this.listeners[t]=new Set),this.listeners[t].add(e),i==null?void 0:i.once){const s=()=>{this.un(t,s),this.un(t,e)};return this.on(t,s),s}return()=>this.un(t,e)}un(t,e){var i;(i=this.listeners[t])===null||i===void 0||i.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach(i=>i(...e))}};const L={decode:function(c,t){return y(this,void 0,void 0,function*(){const e=new AudioContext({sampleRate:t});return e.decodeAudioData(c).finally(()=>e.close())})},createBuffer:function(c,t){return typeof c[0]=="number"&&(c=[c]),function(e){const i=e[0];if(i.some(s=>s>1||s<-1)){const s=i.length;let n=0;for(let r=0;r<s;r++){const a=Math.abs(i[r]);a>n&&(n=a)}for(const r of e)for(let a=0;a<s;a++)r[a]/=n}}(c),{duration:t,length:c[0].length,sampleRate:c[0].length/t,numberOfChannels:c.length,getChannelData:e=>c==null?void 0:c[e],copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};function H(c,t){const e=t.xmlns?document.createElementNS(t.xmlns,c):document.createElement(c);for(const[i,s]of Object.entries(t))if(i==="children")for(const[n,r]of Object.entries(t))typeof r=="string"?e.appendChild(document.createTextNode(r)):e.appendChild(H(n,r));else i==="style"?Object.assign(e.style,s):i==="textContent"?e.textContent=s:e.setAttribute(i,s.toString());return e}function z(c,t,e){const i=H(c,t||{});return e==null||e.appendChild(i),i}var K=Object.freeze({__proto__:null,createElement:z,default:z});const Q={fetchBlob:function(c,t,e){return y(this,void 0,void 0,function*(){const i=yield fetch(c,e);if(i.status>=400)throw new Error(`Failed to fetch ${c}: ${i.status} (${i.statusText})`);return function(s,n){y(this,void 0,void 0,function*(){if(!s.body||!s.headers)return;const r=s.body.getReader(),a=Number(s.headers.get("Content-Length"))||0;let l=0;const o=u=>y(this,void 0,void 0,function*(){l+=(u==null?void 0:u.length)||0;const d=Math.round(l/a*100);n(d)}),h=()=>y(this,void 0,void 0,function*(){let u;try{u=yield r.read()}catch{return}u.done||(o(u.value),yield h())});h()})}(i.clone(),t),i.blob()})}};class Z extends R{constructor(t){super(),this.isExternalMedia=!1,t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),t.mediaControls&&(this.media.controls=!0),t.autoplay&&(this.media.autoplay=!0),t.playbackRate!=null&&this.onMediaEvent("canplay",()=>{t.playbackRate!=null&&(this.media.playbackRate=t.playbackRate)},{once:!0})}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e,i)}getSrc(){return this.media.currentSrc||this.media.src||""}revokeSrc(){const t=this.getSrc();t.startsWith("blob:")&&URL.revokeObjectURL(t)}canPlayType(t){return this.media.canPlayType(t)!==""}setSrc(t,e){const i=this.getSrc();if(t&&i===t)return;this.revokeSrc();const s=e instanceof Blob&&(this.canPlayType(e.type)||!t)?URL.createObjectURL(e):t;i&&(this.media.src="");try{this.media.src=s}catch{this.media.src=t}}destroy(){this.isExternalMedia||(this.media.pause(),this.media.remove(),this.revokeSrc(),this.media.src="",this.media.load())}setMediaElement(t){this.media=t}play(){return y(this,void 0,void 0,function*(){return this.media.play()})}pause(){this.media.pause()}isPlaying(){return!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=Math.max(0,Math.min(t,this.getDuration()))}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}isSeeking(){return this.media.seeking}setPlaybackRate(t,e){e!=null&&(this.media.preservesPitch=e),this.media.playbackRate=t}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}}class T extends R{constructor(t,e){super(),this.timeouts=[],this.isScrollable=!1,this.audioData=null,this.resizeObserver=null,this.lastContainerWidth=0,this.isDragging=!1,this.subscriptions=[],this.unsubscribeOnScroll=[],this.subscriptions=[],this.options=t;const i=this.parentFromOptionsContainer(t.container);this.parent=i;const[s,n]=this.initHtml();i.appendChild(s),this.container=s,this.scrollContainer=n.querySelector(".scroll"),this.wrapper=n.querySelector(".wrapper"),this.canvasWrapper=n.querySelector(".canvases"),this.progressWrapper=n.querySelector(".progress"),this.cursor=n.querySelector(".cursor"),e&&n.appendChild(e),this.initEvents()}parentFromOptionsContainer(t){let e;if(typeof t=="string"?e=document.querySelector(t):t instanceof HTMLElement&&(e=t),!e)throw new Error("Container not found");return e}initEvents(){const t=e=>{const i=this.wrapper.getBoundingClientRect(),s=e.clientX-i.left,n=e.clientY-i.top;return[s/i.width,n/i.height]};if(this.wrapper.addEventListener("click",e=>{const[i,s]=t(e);this.emit("click",i,s)}),this.wrapper.addEventListener("dblclick",e=>{const[i,s]=t(e);this.emit("dblclick",i,s)}),this.options.dragToSeek!==!0&&typeof this.options.dragToSeek!="object"||this.initDrag(),this.scrollContainer.addEventListener("scroll",()=>{const{scrollLeft:e,scrollWidth:i,clientWidth:s}=this.scrollContainer,n=e/i,r=(e+s)/i;this.emit("scroll",n,r,e,e+s)}),typeof ResizeObserver=="function"){const e=this.createDelay(100);this.resizeObserver=new ResizeObserver(()=>{e().then(()=>this.onContainerResize()).catch(()=>{})}),this.resizeObserver.observe(this.scrollContainer)}}onContainerResize(){const t=this.parent.clientWidth;t===this.lastContainerWidth&&this.options.height!=="auto"||(this.lastContainerWidth=t,this.reRender())}initDrag(){this.subscriptions.push(function(t,e,i,s,n=3,r=0,a=100){if(!t)return()=>{};const l=matchMedia("(pointer: coarse)").matches;let o=()=>{};const h=u=>{if(u.button!==r)return;u.preventDefault(),u.stopPropagation();let d=u.clientX,p=u.clientY,m=!1;const w=Date.now(),f=v=>{if(v.preventDefault(),v.stopPropagation(),l&&Date.now()-w<a)return;const S=v.clientX,x=v.clientY,P=S-d,M=x-p;if(m||Math.abs(P)>n||Math.abs(M)>n){const k=t.getBoundingClientRect(),{left:A,top:N}=k;m||(i==null||i(d-A,p-N),m=!0),e(P,M,S-A,x-N),d=S,p=x}},g=v=>{if(m){const S=v.clientX,x=v.clientY,P=t.getBoundingClientRect(),{left:M,top:k}=P;s==null||s(S-M,x-k)}o()},b=v=>{v.relatedTarget&&v.relatedTarget!==document.documentElement||g(v)},E=v=>{m&&(v.stopPropagation(),v.preventDefault())},C=v=>{m&&v.preventDefault()};document.addEventListener("pointermove",f),document.addEventListener("pointerup",g),document.addEventListener("pointerout",b),document.addEventListener("pointercancel",b),document.addEventListener("touchmove",C,{passive:!1}),document.addEventListener("click",E,{capture:!0}),o=()=>{document.removeEventListener("pointermove",f),document.removeEventListener("pointerup",g),document.removeEventListener("pointerout",b),document.removeEventListener("pointercancel",b),document.removeEventListener("touchmove",C),setTimeout(()=>{document.removeEventListener("click",E,{capture:!0})},10)}};return t.addEventListener("pointerdown",h),()=>{o(),t.removeEventListener("pointerdown",h)}}(this.wrapper,(t,e,i)=>{this.emit("drag",Math.max(0,Math.min(1,i/this.wrapper.getBoundingClientRect().width)))},t=>{this.isDragging=!0,this.emit("dragstart",Math.max(0,Math.min(1,t/this.wrapper.getBoundingClientRect().width)))},t=>{this.isDragging=!1,this.emit("dragend",Math.max(0,Math.min(1,t/this.wrapper.getBoundingClientRect().width)))}))}getHeight(t,e){var i;const s=((i=this.audioData)===null||i===void 0?void 0:i.numberOfChannels)||1;if(t==null)return 128;if(!isNaN(Number(t)))return Number(t);if(t==="auto"){const n=this.parent.clientHeight||128;return e!=null&&e.every(r=>!r.overlay)?n/s:n}return 128}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"}),i=this.options.cspNonce&&typeof this.options.cspNonce=="string"?this.options.cspNonce.replace(/"/g,""):"";return e.innerHTML=`
|
|
2
2
|
<style${i?` nonce="${i}"`:""}>
|
|
3
3
|
:host {
|
|
4
4
|
user-select: none;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as l,c as s,o as i,a as r}from"./index-
|
|
1
|
+
import{_ as l,c as s,o as i,a as r}from"./index-CSSh_R5o.js";const u=["src"],_={__name:"ImagePlugin",props:{content:{type:Object,default:()=>({})}},setup(a){const e=a,n=s(()=>e.content.blob_url||e.content.image_url.url);function c(t){t.target.classList.toggle("rawSizeImg")}function o(){window.open(n.value,"_blank")}return(t,p)=>(i(),r("img",{class:"on-panda-image-plugin",src:n.value,alt:"ON_PANDA_IMAGE",onClick:c,onDblclick:o},null,40,u))}},m=l(_,[["__scopeId","data-v-3a06bfde"]]);export{m as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{_ as r,r as l,g as u,h as d,o as i,a as p}from"./index-
|
|
1
|
+
import{_ as r,r as l,g as u,h as d,o as i,a as p}from"./index-CSSh_R5o.js";const _=["src"],f={__name:"VideoPlugin",props:{content:{type:Object,default:()=>({})}},setup(s){const c=s,e=l("");return u(function(o){const t=c.content.video_url.url;if(!t.startsWith("data:")){e.value=t;return}const a=d(t);e.value=a,o(()=>URL.revokeObjectURL(a))}),(n,o)=>(i(),p("video",{class:"on-panda-video-plugin",src:e.value,controls:"",preload:"metadata"},null,8,_))}},b=r(f,[["__scopeId","data-v-8950981c"]]);export{b as default};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const R=Object.getPrototypeOf(async function(){}).constructor,x=256*1024,j=5,p=200,g=6e4,E={"image/png":"image","image/jpeg":"image","image/gif":"image","image/webp":"image","audio/wav":"audio","audio/mp3":"audio","audio/mpeg":"audio","video/mp4":"video","video/webm":"video","video/quicktime":"video"},O={name:"run_browser_js",description:"Run JavaScript in the current browser runtime and return logs from `console.log`. `console.log` accepts `Blob` arguments of MCP-supported image, audio, and video types, returned as inline media in your context. Each tool call uses a fresh local scope, so local variables do not persist across calls, but shared globals like window and document do persist. Your JavaScript local scope includes a `browserAgent` variable. For content that should be reused across tool calls, prefer storing it on the `browserAgent.local` object. You can access the internet under CORS restrictions. Do not refresh or switch the current webpage, as this will reset the JavaScript runtime and your context lost.",inputSchema:{type:"object",properties:{code:{type:"string",description:"If your code starts any async work, such as fetch, promises, or async functions, await it with top-level await or await the returned promise; otherwise the tool may return before later logs run. Do not rely on un-awaited .then() callbacks for console.log output."}}}},$={name:"render_svg",description:"Render an SVG string into a bitmap PNG image. The tool uses the SVG width/height, or falls back to viewBox.",inputSchema:{type:"object",properties:{svg:{type:"string",description:"SVG markup to render. It must start with `<svg` and end with `</svg>`."}}}};function I(e){return new Promise((t,o)=>{const n=new FileReader;n.onload=()=>{const r=n.result;t(r.slice(r.indexOf(",")+1))},n.onerror=o,n.readAsDataURL(e)})}function v(e=""){return`<|js_error_start|>
|
|
2
|
+
${e}
|
|
3
|
+
<|js_error_end|>`}function _(e="",t=x){if(e.length<=t)return e;const o=Math.ceil(t/2),n=t-o,r=e.length-t;return`(Total length: ${e.length} characters. Showing ${t} characters after truncating the middle.)
|
|
4
|
+
${e.slice(0,o)}
|
|
5
|
+
<|truncate_long_text|>
|
|
6
|
+
{Output exceeded ${t} characters. Omitted ${r} characters from the middle.} ......
|
|
7
|
+
<|truncate_long_text|>
|
|
8
|
+
${e.slice(e.length-n)}`}function A(e=""){const t=e.split(`
|
|
9
|
+
`),o=[];let n=t.length>p?t.slice(0,p).join(`
|
|
10
|
+
`):e;return t.length>p&&o.push(`original ${t.length} lines exceeded ${p} lines`),e.length>g&&o.push(`original ${e.length} characters exceeded ${g} characters`),n.length>g&&(n=n.slice(0,g)),{text:n,truncationReason:o.length?`Truncated: ${o.join("; ")}. So, find an opportunity to organize the memory: clean up or archive outdated or unimportant information, move less important content out of \`browser-agent/memory/MEMORY.md\` into other localStorage keys under \`browser-agent/memory/\`, and keep only brief descriptions and references in \`browser-agent/memory/MEMORY.md\` so you can read the archived content later when needed.`:""}}function T(){const e=`## Persistent memory
|
|
11
|
+
Persistent memory is stored in localStorage. Treat localStorage as a virtual filesystem: each localStorage key is a file path, and \`browser-agent/memory/\` is the memory directory. The primary memory file is \`browser-agent/memory/MEMORY.md\`, which is always loaded into your conversation context. Use \`run_browser_js\` with localStorage to record and modify it. Store other memory files under \`browser-agent/memory/\`; use \`Object.keys(localStorage).filter(key => key.startsWith('browser-agent/memory/'))\` to query available files. Keep \`browser-agent/memory/MEMORY.md\` concise; it is truncated after ${p} lines or ${g} characters.`,t=localStorage.getItem("browser-agent/memory/MEMORY.md")||"";if(!t.trim())return`${e}
|
|
12
|
+
The current \`browser-agent/memory/MEMORY.md\` is empty.`;const{text:o,truncationReason:n}=A(t);return`${e}
|
|
13
|
+
### Content of primary MEMORY.md
|
|
14
|
+
<|browser_agent_memory_start|>
|
|
15
|
+
${o}
|
|
16
|
+
<|browser_agent_memory_end|>${n?`
|
|
17
|
+
${n}`:""}`}async function U(e="",t){const o=[],n=[],r=performance.now(),s={...console,log(...i){const c=i.map(u=>{const b=u instanceof Blob?E[u.type]:null;if(b){const y={type:b,mimeType:u.type,data:""};return n.push(I(u).then(M=>{y.data=M})),y}return String(u)});o.push({kind:"log",row:c}),console.log("[run_browser_js.log]:",...i)},error(...i){const c=i.map(u=>String(u)).join(" ");o.push({kind:"error",text:v(c)}),console.log("[run_browser_js.error]:",c)}},h=t({callScope:{console:s}});try{await new R("console","browserAgent",e)(s,h)}catch(i){const c=String(i);o.push({kind:"error",text:v(c)}),console.log("[run_browser_js.error]:",c)}await Promise.all(n);const l=Math.round(performance.now()-r),d=[{type:"text",text:`<|execution_info_start|>
|
|
18
|
+
Code execution time: ${l} ms
|
|
19
|
+
<|execution_info_end|>`}];o.some(i=>i.kind==="log")||(d.push({type:"text",text:"<|no_js_log|>"}),l<j&&d.push({type:"text",text:`<|system_reminder_start|>
|
|
20
|
+
No console.log output was produced and the JavaScript execution completed very quickly. If output was expected, the code may have started asynchronous work without awaiting it, so the tool returned before the asynchronous callback could run. Await the promise or use top-level await, then call console.log.
|
|
21
|
+
<|system_reminder_end|>`}));let a="";const w=()=>{a&&(d.push({type:"text",text:_(a)}),a="")};return o.forEach(i=>{i.kind==="log"?i.row.forEach((c,u)=>{typeof c=="string"?(a&&(a+=u===0?`
|
|
22
|
+
`:" "),a+=c):(w(),d.push(c))}):(w(),d.push({type:"text",text:_(i.text)}))}),w(),d}async function L(e=""){const t=URL.createObjectURL(new Blob([e],{type:"image/svg+xml"}));try{const o=await new Promise((d,f)=>{const a=new Image;a.onload=()=>d(a),a.onerror=f,a.src=t}),n=new DOMParser().parseFromString(e,"image/svg+xml").documentElement,r=Number.parseFloat(n.getAttribute("width")),s=Number.parseFloat(n.getAttribute("height")),h=(n.getAttribute("viewBox")||"").trim().split(/[\s,]+/).map(Number),l=document.createElement("canvas");return l.width=Number.isFinite(r)&&Number.isFinite(s)?r:h.length===4?h[2]:o.naturalWidth,l.height=Number.isFinite(r)&&Number.isFinite(s)?s:h.length===4?h[3]:o.naturalHeight,l.getContext("2d").drawImage(o,0,0,l.width,l.height),l.toDataURL("image/png").slice(22)}finally{URL.revokeObjectURL(t)}}function S(e,t={}){return new Response(JSON.stringify(e),{status:200,headers:{"content-type":"application/json"},...t})}function m(e,t){return S({jsonrpc:"2.0",id:e,result:t})}function k(e,t,o){return S({jsonrpc:"2.0",id:e,error:{code:t,message:o}})}async function B({message:e={},instructions:t="",buildBrowserAgent:o}={}){var n,r;if(e.method==="initialize")return m(e.id,{protocolVersion:e.params.protocolVersion,capabilities:{tools:{}},serverInfo:{name:"browser-agent-mcp",version:"0.1.0"},instructions:t});if(e.method==="ping")return m(e.id,{});if(e.method==="tools/list")return m(e.id,{tools:[O,$]});if(e.method==="tools/call"){if(e.params.name==="run_browser_js"){const s=await U(((n=e.params.arguments)==null?void 0:n.code)||"",o);return m(e.id,{content:s})}if(e.params.name==="render_svg"){const s=await L(((r=e.params.arguments)==null?void 0:r.svg)||"");return m(e.id,{content:[{type:"image",mimeType:"image/png",data:s}]})}return k(e.id,-32601,`Tool not found: ${e.params.name}`)}return e.id==null?new Response(null,{status:204}):k(e.id,-32601,`Method not found: ${e.method}`)}function P({proxyPath:e=""}={}){return`You are an agent running in a browser. You are operating in the JavaScript runtime of the current webpage, called onPanda, where the user interacts with you. Please make the appropriate adjustments for this browser JavaScript environment.
|
|
23
|
+
|
|
24
|
+
## Skills
|
|
25
|
+
A skill is a set of instructions to follow that is stored in a \`SKILL.md\` file. Below is the list of skills that can be used. Each entry includes a name, description, and skillUrl so you can open the source for full instructions when using a specific skill.
|
|
26
|
+
### Available skills
|
|
27
|
+
- \`cors-internet\`: Skill for web search and information retrieval under CORS. Use when you need to access the internet. ([skillUrl](https://raw.githubusercontent.com/on-panda/browser-agent-skills/main/skills/cors-internet/SKILL.md))${e?`
|
|
28
|
+
- Fallback: for critical resources that even cors-internet cannot reach, use the server-side proxy at \`${e}/{url}\`.`:""}
|
|
29
|
+
- \`interactive-webpage\`: Use when you need to create webpages or interactive artifacts, or modify the current UI. ([skillUrl](https://raw.githubusercontent.com/on-panda/browser-agent-skills/main/skills/interactive-webpage/SKILL.md))
|
|
30
|
+
- \`user-local-files\`: Use when the user shares local files, indicated by \`<|user_local_files\` in the context. Includes local filesystem read/write guidelines and common tools. ([skillUrl](https://raw.githubusercontent.com/on-panda/browser-agent-skills/main/skills/user-local-files/SKILL.md))
|
|
31
|
+
- \`onpanda-docs\`: Use when the user asks about onPanda or asks you to manage API configuration. This skill contains information about onPanda, its source code, and related resources. ([skillUrl](https://raw.githubusercontent.com/on-panda/browser-agent-skills/main/skills/onpanda-docs/SKILL.md))
|
|
32
|
+
### How to load skills
|
|
33
|
+
If the task clearly matches a skill's description shown above, using tool "run_browser_js" with this pattern code to load the skill:
|
|
34
|
+
\`\`\`js
|
|
35
|
+
await fetch(skillUrl).then(res => res.text()).then(console.log)
|
|
36
|
+
\`\`\`
|
|
37
|
+
|
|
38
|
+
${T()}`}function J({buildBrowserAgent:e,proxyPath:t=""}={}){return{localFetch:async function(n,r={}){if((r.method||"GET")!=="POST")return new Response(null,{status:405});const s=JSON.parse(r.body||"{}");return await B({message:s,instructions:s.method==="initialize"?P({proxyPath:t}):"",buildBrowserAgent:e})}}}export{J as BrowserAgentMcpClosure};
|