import{createRequire as L}from"node:module";import{existsSync as b,mkdirSync as B,writeFileSync as S}from"node:fs";import{dirname as _,join as l,resolve as x}from"node:path";import{fileURLToPath as N}from"node:url";var O=L(import.meta.url),f=null;function C(){return f||(f=O("echarts")),f}var p=null;function P(){return p||(p=O("@resvg/resvg-js")),p}var T=800,w=600,D=4096,F=16,v=60,E="Noto Sans";function k(){if(process.env.MCP_SKILL_PATH)return process.env.MCP_SKILL_PATH;let e=_(N(import.meta.url)),t=x(e,"..","bin","mcp-skill.mjs");return b(t)?t:null}function R(){let e=_(N(import.meta.url)),t=x(e,"..","assets","fonts");return["NotoSans-Regular.ttf","NotoSans-Bold.ttf"].map(r=>l(t,r)).filter(r=>b(r))}function j(){let e=process.env.ZIBBY_NODE_SESSION_PATH,t=process.env.ZIBBY_SESSION_PATH,r=e||(t?l(t,"chart-render"):l(process.cwd(),".zibby","output","charts"));return B(r,{recursive:!0}),r}function o(e){return e!=null&&typeof e=="object"&&!Array.isArray(e)}function A(e,t){let r=Number(e);return Number.isFinite(r)?Math.max(F,Math.min(D,Math.round(r))):t}function h(e){return typeof e!="string"||e.length<=v?e:`${e.slice(0,v-1)}\u2026`}function d(e){if(Array.isArray(e))for(let t=0;t<e.length;t++){let r=e[t];typeof r=="string"?e[t]=h(r):o(r)&&typeof r.name=="string"&&(r.name=h(r.name))}}function G(e){for(let n of["xAxis","yAxis"]){let s=Array.isArray(e[n])?e[n]:e[n]?[e[n]]:[];for(let a of s)o(a)&&d(a.data)}let t=Array.isArray(e.radar)?e.radar:e.radar?[e.radar]:[];for(let n of t)o(n)&&d(n.indicator);o(e.legend)&&d(e.legend.data);let r=Array.isArray(e.series)?e.series:e.series?[e.series]:[];for(let n of r)o(n)&&(typeof n.name=="string"&&(n.name=h(n.name)),d(n.data))}function H(e){let t=JSON.parse(JSON.stringify(e));return t.animation=!1,t.backgroundColor==null&&(t.backgroundColor="#fff"),o(t.textStyle)||(t.textStyle={}),t.textStyle.fontFamily==null&&(t.textStyle.fontFamily=E),G(t),t}function M(e){return typeof e!="string"?null:e.trim().replace(/\.(svg|png)$/i,"").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^[.-]+|[.-]+$/g,"")||null}function J(e,t,r){let s=C().init(null,null,{renderer:"svg",ssr:!0,width:t,height:r});try{return s.setOption(e),s.renderToSVGString()}finally{s.dispose()}}function Y(e){let{Resvg:t}=P();return new t(e,{font:{fontFiles:R(),loadSystemFonts:!0,defaultFontFamily:E}}).render().asPng()}var z={id:"chart-render",serverName:"chart_render",allowedTools:["mcp__chart_render__*"],description:"Chart render \u2014 local server-side chart rendering (Apache ECharts SVG SSR + resvg PNG); data never leaves the box",promptFragment:`## Chart Render (local, no external service)
You can render charts LOCALLY with the chart_render tool \u2014 pass a standard
Apache ECharts option object as \`spec\` (any chart type: bar, line, pie,
radar, scatter, heatmap, \u2026). It renders server-side to SVG/PNG files in the
run's output folder (auto-attached to the run as artifacts) and returns the
file paths. No browser, no external chart service \u2014 the data never leaves
the machine. Don't set animation (it's forced off). Default 800\xD7600 PNG.`,resolve({sessionPath:e,nodeName:t}={}){let r=k();if(!r)return{command:null,args:[],env:{},description:this.description};let n={},s=e&&t?l(e,t):null;s&&(n.ZIBBY_NODE_SESSION_PATH=s),e&&(n.ZIBBY_SESSION_PATH=e);for(let a of["ZIBBY_NODE_SESSION_PATH","ZIBBY_SESSION_PATH"])!n[a]&&process.env[a]&&(n[a]=process.env[a]);return{type:"stdio",command:"node",args:[r,"../dist/chartRender.js","chartRenderSkill"],env:n,description:this.description,alwaysLoad:!0}},async handleToolCall(e,t){if(e!=="chart_render")return JSON.stringify({error:`Unknown tool: ${e}`});try{let r=t?.spec;if(!o(r))return JSON.stringify({error:"spec must be a plain ECharts option OBJECT (e.g. { xAxis: {...}, yAxis: {...}, series: [...] }) \u2014 got "+(r===null?"null":Array.isArray(r)?"an array":typeof r)+". Pass the option object itself, not a string or an array."});let n=A(t?.width,T),s=A(t?.height,w),a=["svg","png","both"].includes(t?.output)?t.output:"png",m=M(t?.filename)||`chart-${Date.now()}`,c;try{c=J(H(r),n,s)}catch(i){return JSON.stringify({error:`Chart render failed: ${i.message}. The spec must be a valid Apache ECharts option (check series[].type, and that xAxis/yAxis/radar match the series type). Fix the spec and retry.`})}if(typeof c!="string"||!c.includes("<svg"))return JSON.stringify({error:"Chart render produced no SVG \u2014 the spec likely describes an empty chart (no series?). Add at least one series and retry."});let y=j(),u=[];if(a==="svg"||a==="both"){let i=l(y,`${m}.svg`);S(i,c,"utf-8"),u.push({path:i,format:"svg",bytes:Buffer.byteLength(c,"utf-8")})}if(a==="png"||a==="both"){let i;try{i=Y(c)}catch(I){return JSON.stringify({error:`PNG rasterization failed: ${I.message}. Retry with output:'svg' if you only need the vector.`})}let g=l(y,`${m}.png`);S(g,i),u.push({path:g,format:"png",bytes:i.length})}return JSON.stringify({ok:!0,width:n,height:s,files:u})}catch(r){return JSON.stringify({error:`chart_render failed: ${r.message}`})}},tools:[{name:"chart_render",description:'Render a chart LOCALLY (no external service) from a standard Apache ECharts option and save it as SVG/PNG files in the run output folder. Pass the raw ECharts option as `spec` \u2014 every ECharts chart type works (bar, line, pie, radar, scatter, heatmap, \u2026). Returns the written file path(s). animation is forced off; background defaults to white. Bar example: {"xAxis":{"type":"category","data":["Q1","Q2"]},"yAxis":{},"series":[{"type":"bar","data":[12,30]}]}. Radar example: {"legend":{"data":["A","B"]},"radar":{"indicator":[{"name":"speed","max":10},{"name":"cost","max":10},{"name":"quality","max":10}]},"series":[{"type":"radar","data":[{"name":"A","value":[7,4,9]},{"name":"B","value":[5,8,6]}]}]}.',input_schema:{type:"object",properties:{spec:{type:"object",description:"The Apache ECharts option object, passed through as-is (series, xAxis/yAxis, radar, legend, title, \u2026)."},width:{type:"number",description:"Image width in px (default 800, max 4096)."},height:{type:"number",description:"Image height in px (default 600, max 4096)."},output:{type:"string",enum:["svg","png","both"],description:"Which file(s) to write (default 'png')."},filename:{type:"string",description:"Optional file basename (no extension); defaults to chart-<timestamp>."}},required:["spec"]}}]};export{z as chartRenderSkill};
