@bicharts/chart-mcp 0.6.56 → 0.6.57
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/index.mjs +3 -3
- package/package.json +1 -1
- package/skills/bic-charts/SKILL.md +6 -0
package/dist/index.mjs
CHANGED
|
@@ -74,8 +74,8 @@ License: MIT
|
|
|
74
74
|
`;)m+=a[m]==="\\"?2:1;n+=a.slice(r,Math.min(m+1,t)),r=m+1,i=c,s="",l=!1;continue}if(c==="`"){o.push(-1),n+=c,r++,l=!1;continue}if(c==="/"&&u()){let m=r+1,h=!1;for(;m<t&&a[m]!==`
|
|
75
75
|
`;){let g=a[m];if(g==="\\"){m+=2;continue}if(g==="[")h=!0;else if(g==="]")h=!1;else if(g==="/"&&!h)break;m++}if(m<t&&a[m]==="/"){for(m++;m<t&&/[A-Za-z]/.test(a[m]);)m++;n+=a.slice(r,m),r=m,i="/",s="",l=!1;continue}}if(p!==null&&p>=0){if(c==="{")o[o.length-1]=p+1;else if(c==="}"){if(p===0){o[o.length-1]=-1,n+=c,r++;continue}o[o.length-1]=p-1}}n+=c,r++,/\s/.test(c)?l=!1:(/[A-Za-z0-9_$]/.test(c)?(s=l?s+c:c,l=!0):(s="",l=!1),i=c)}return n}var ny=Object.freeze({sankey:"d3-sankey",sankeyLinkHorizontal:"d3-sankey",sankeyJustify:"d3-sankey",sankeyCenter:"d3-sankey",sankeyLeft:"d3-sankey",sankeyRight:"d3-sankey",hexbin:"d3-hexbin",voronoiTreemap:"d3-voronoi-treemap",voronoiMap:"d3-voronoi-map",weightedVoronoi:"d3-weighted-voronoi",mermaid:"mermaid",llmMermaid:"mermaid"});function M7(e){let a=new Set,t=ty(String(e||"")),n=r=>{let o=ny[r];o&&a.add(o)};for(let r of t.matchAll(/\bd3\s*\.\s*(\w+)/g))n(r[1]);for(let r of t.matchAll(/\bd3\s*\[\s*['"](\w+)['"]\s*\]/g))n(r[1]);for(let r of t.matchAll(/\{([^{}]*)\}\s*=\s*d3\b/g))for(let o of r[1].split(","))n(o.split(":")[0].trim());return[...a].sort()}var UK=Object.freeze({sourceId:null,rows:Object.freeze([])});/*! @bicharts/chart-host — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; Natural Earth and US Census/TIGER (public domain). Full text: NOTICE in this package. */var Ix=10,Ex=1e5,xx=1e4,Y1=e=>Object.freeze({...e,...e.values?{values:Object.freeze([...e.values])}:{}}),Y0=Object.freeze({aggregation:Y1({timing:"live-and-next-generate",default:"",values:["","sum","average","median","min","max","count","distinct"],wire:"request"}),colorScaleLow:Y1({timing:"live-and-next-generate",default:"",wire:"request"}),colorScaleHigh:Y1({timing:"live-and-next-generate",default:"",wire:"request"}),palette:Y1({timing:"live-and-next-generate",default:"",wire:"request"}),maxMapPoints:Y1({timing:"live-and-next-generate",default:q9,min:Ix,max:Ex,wire:"clientHints"}),pageSize:Y1({timing:"live",default:0,min:0}),valueAxisBaseline:Y1({timing:"live",default:Lf,values:["fit","zero","auto"]}),seasonalMarkers:Y1({timing:"live",default:Ff,values:["auto","always","never"]}),animAutoPlay:Y1({timing:"live",default:!1}),animPlaySpeedMs:Y1({timing:"live",default:j8,min:G9,max:X9}),animLoopDelaySec:Y1({timing:"live",default:K9,min:If}),animStopAtEnd:Y1({timing:"live",default:!1}),animMaxIdealFrames:Y1({timing:"live",default:L8,min:Z9,max:V9}),animTimelineStyle:Y1({timing:"live",default:"",values:["","line","boxes"]}),filtersDuringPlay:Y1({timing:"live",default:!1}),flipMode:Y1({timing:"live",default:Ef,values:["both","all","single"]}),flipIntervalMs:Y1({timing:"live",default:"",min:0,max:xf}),flipDirection:Y1({timing:"live",default:jf,values:["horizontal","vertical"]}),levelOfDetail:Y1({timing:"next-generate",default:"",values:["","High","Medium","Low"],wire:"clientHints"}),favorLimitTo:Y1({timing:"next-generate",default:"",values:["","latest","top / greatest","bottom / smallest","most common","outliers"],wire:"clientHints"}),favorLimitCount:Y1({timing:"next-generate",default:0,min:0,max:xx,wire:"clientHints"}),favorTitle:Y1({timing:"next-generate",default:"",values:["","1","0"],wire:"clientHints"}),favorDPValues:Y1({timing:"next-generate",default:"",values:["","1","0"],wire:"clientHints"}),legendPlacement:Y1({timing:"next-generate",default:"",values:["","outside","inside","none"],wire:"clientHints"}),industryContext:Y1({timing:"next-generate",default:"",wire:"clientHints"}),suggestFontFamily:Y1({timing:"next-generate",default:"",wire:"clientHints"}),visionReview:Y1({timing:"after-render",default:!1}),saveThumbnails:Y1({timing:"after-render",default:!1})}),sq=Object.freeze(Object.keys(Y0).filter(e=>Y0[e].timing==="live"||Y0[e].timing==="live-and-next-generate"));var jx=/\.(?:getFullYear|getMonth|getDate|getDay|getHours|getMinutes|setFullYear|setMonth|setDate|setHours|setMinutes|setSeconds|setMilliseconds)\s*\(/,Lx=/\bd3\s*\.\s*(?:scaleTime|time[A-Z]\w*)\b/,Fx=/\bnew\s+Date\s*\(\s*[^(),]+,/,Bx=/\bIntl\s*\.\s*DateTimeFormat\b|\.toLocaleDateString\s*\(|\.toLocaleTimeString\s*\(/;function ly(e){return e?jx.test(e)||Lx.test(e)||Fx.test(e)?!0:Bx.test(e)&&!/timeZone/.test(e):!1}var uy="loose";function cy(e){return typeof e=="string"&&e.trim().toLowerCase()==="exact"?"exact":uy}function Q0(e){return typeof e!="string"||e===""?"":e.normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLowerCase().replace(/\s+/g," ").trim()}var ry=2;function Dx(e,a){for(let t=e.indexOf(a);t>=0;t=e.indexOf(a,t+1)){if(t===0)return!0;let n=e.charCodeAt(t-1);if(!(n>=97&&n<=122||n>=48&&n<=57))return!0}return!1}function oy(e){let a="",t=new Set,n=!1;for(let r of e){let o=d4(r),i=r.charCodeAt(0),s=i>=97&&i<=122||i>=48&&i<=57;o&&(n||t.add(a.length),a+=o),n=s}return{form:a,starts:t}}function iy(e,a){for(let t=e.form.indexOf(a);t>=0;t=e.form.indexOf(a,t+1))if(e.starts.has(t))return!0;return!1}function P7(e,a,t,n=uy){let r=Array.isArray(e)?e.slice():[],o=Q0(a);if(o.length<ry)return{rows:r,tier:"all",term:""};let i=n==="loose"?d4(o):"",s=i.length>=ry?i:"",l=[],u=[],c=[];for(let d of r){let p=t(d),m=Q0(p.name);if(m==="")continue;if(m.indexOf(o)>=0){(Dx(m,o)?l:u).push(d);continue}if(s&&iy(oy(m),s)){l.push(d);continue}let h=Q0(p.description);(h.indexOf(o)>=0||s&&iy(oy(h),s))&&c.push(d)}return l.length>0?{rows:l,tier:"name",term:o}:u.length>0?{rows:u,tier:"namePart",term:o}:c.length>0?{rows:c,tier:"desc",term:o}:{rows:[],tier:"none",term:o}}function n5(e){return{name:e.name,description:e.description}}function dy(e){return{name:e.name,description:e.reason}}function ue(e,a,t,n){var r,o=arguments.length,i=o<3?a:n===null?n=Object.getOwnPropertyDescriptor(a,t):n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(e,a,t,n);else for(var s=e.length-1;s>=0;s--)(r=e[s])&&(i=(o<3?r(i):o>3?r(a,t,i):r(a,t))||i);return o>3&&i&&Object.defineProperty(a,t,i),i}function xe(e,a,t){if(t||arguments.length===2)for(var n,r=0,o=a.length;r<o;r++)!n&&r in a||(n||(n=Array.prototype.slice.call(a,0,r)),n[r]=a[r]);return e.concat(n||Array.prototype.slice.call(a))}var hy=function(e,a,t){return[e,a,t].map((function(n){return(n/=255)>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92}))},py=function(e,a,t){return[e,a,t].map((function(n){return 255*(n<=.00304?12.92*n:1.055*Math.pow(n,1/2.4)-.055)}))},f3=function(e,a,t){return Math.min(Math.max(e,a),t)},my=function(e,a){return Math.round((e+Number.EPSILON)*Math.pow(10,a))/Math.pow(10,a)},Q9=function(e,a){return Math.floor(Math.random()*(a-e+1)-e)},gy=function(e,a,t,n){for(var r,o=[e,a,t],i="#",s=0;s<o.length;s++)i+=(r=o[s],Math.round(f3(r,0,255)).toString(16).padStart(2,"0"));return n!=null&&(i+=Math.round(f3(n,0,100)/100*255).toString(16).padStart(2,"0")),i},fy=function(e){var a=e.length,t=(e=(function(o){var i=(o=/^#/.test(o)?o.slice(1):o).length;if(![3,4,6,8].includes(i))return"000000";if(i===6||i===8)return o;if(i===3||i===4){for(var s="",l=0;l<i;l++){var u=o[l];s+=""+u+u}return s}return"000000"})(e).padEnd(8,"ff")).match(/.{2}/g);if(!t)return[0,0,0,1];var n=[0,0,0],r=!1;return t.forEach((function(o,i){i<3?n[i]=parseInt(o,16):r=100*parseInt(o,16)/255})),r===!1||a<8?n:xe(xe([],n,!0),[r],!1)},yy=function(e,a,t){var n;n=[e,a,t].map((function(i){return i/255})),e=n[0],a=n[1],t=n[2];var r=1-Math.max(e,a,t),o=r<1?1/(1-r):0;return[(1-e-r)*o*100,(1-a-r)*o*100,(1-t-r)*o*100,100*r]},Ny=function(e,a,t,n){return n===100?[0,0,0]:(n/=100,[e,a,t].map((function(r){return(r/=100)>=1?0:255*(1-r)*(1-n)})))};function os(e,a,t,n){var r;n===void 0&&(n="l"),r=[e,a,t].map((function(m){return m/255})),e=r[0],a=r[1],t=r[2];var o=Math.max(e,a,t),i=Math.min(e,a,t),s=(function(m,h,g,f){var S;f===void 0&&(f=!1),S=[m,h,g].map((function(w){return w/255})),m=S[0],h=S[1],g=S[2];var W=Math.max(m,h,g),k=Math.min(m,h,g),M=0;if(W!==k)if(f)M=(m-h+(m-g))/2,M/=Math.sqrt((m-h)*(m-h)+(m-g)*(h-g)),M=Math.acos(M),g>h&&(M=2*Math.PI-M),M/=2*Math.PI;else{var A=W-k;M=W===m?(h-g)/A+(h<g?6:0):W===h?(g-m)/A+2:(m-h)/A+4,M/=6}else M=NaN;return 360*M})(e,a,t,n==="i"),l=0,u=(o+i)/2,c=o-i,d=o,p=(e+a+t)/3;return n==="v"&&(l=o===0?0:c/o),o!==i&&n==="l"&&(l=u>.5?c/(2-o-i):c/(o+i)),n==="i"&&(l=p>0?1-i/p:0),l*=100,u*=100,p*=100,n==="l"?[s,l,u]:n==="v"?[s,l,d*=100]:[s,l,p]}var is=function(e,a,t){return os(e,a,t,"l")},H4=function(e,a,t){var n,r,o=function(i){return 6*(i=i<0?i+1:i>1?i-1:i)<1?n+(r-n)*i*6:2*i<1?r:3*i<2?n+(r-n)*(.6666666666666666-i)*6:n};return e=e%360/360,a=f3(a/100,0,1),t=f3(t/100,0,1),n=2*t-(r=t<=.5?t*(a+1):t+a-t*a),[255*o(e+1/3),255*o(e),255*o(e-1/3)]},by=function(e,a,t){return os(e,a,t,"v")},ss=function(e,a,t){var n,r,o=[t/=100,t*(1-(a/=100)),t*(1-(r=(e=e%360/360*360)/60-(n=Math.floor(e/60%6)))*a),t*(1-(1-r)*a)],i=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return[255*o[i[n][0]],255*o[i[n][1]],255*o[i[n][2]]]},Sy=function(e,a,t){return os(e,a,t,"i")},ls=function(e,a,t){var n,r,o,i;a/=100,t/=100,isNaN(e)&&(e=0),isNaN(a)&&(a=0);var s=function(l){return(1+a*Math.cos(2*Math.PI*l)/Math.cos(Math.PI/3-2*Math.PI*l))/3};return(e=(360+e)%360/360)<1/3?o=1-((i=(1-a)/3)+(r=s(e))):e<2/3?i=1-((r=(1-a)/3)+(o=s(e-=1/3))):r=1-((o=(1-a)/3)+(i=s(e-=2/3))),n=[r,o,i].map((function(l){return 255*f3(t*l*3,0,1)})),[r=n[0],o=n[1],i=n[2]]},Wy=function(e,a,t){return[is(e,a,t)[0],100*(Math.min(e,a,t)/255),100*(1-Math.max(e,a,t)/255)]};function us(e,a,t){return a/=100,t/=100,H4(e,100,50).map((function(n){return 255*(n/255*(1-a-t)+a)}))}var es={x:[.4124564,.3575761,.1804375],y:[.2126729,.7151522,.072175],z:[.0193339,.119192,.9503041]},as={r:[3.2404542,-1.5371385,-.4985314],g:[-.969266,1.8760108,.041556],b:[.0556434,-.2040259,1.0572252]},ky=.95047,vy=1,Cy=1.08883,Ox=.206896552,$x=.008856452,wy=24389/27,ts=function(e,a,t){var n=hy(e,a,t);return[100*es.x.reduce((function(r,o,i){return r+o*n[i]}),0),100*es.y.reduce((function(r,o,i){return r+o*n[i]}),0),100*es.z.reduce((function(r,o,i){return r+o*n[i]}),0)]},U7=function(e,a,t){var n=[e,a,t],r=as.r.reduce((function(s,l,u){return s+l*n[u]}),0)/100,o=as.g.reduce((function(s,l,u){return s+l*n[u]}),0)/100,i=as.b.reduce((function(s,l,u){return s+l*n[u]}),0)/100;return py(r,o,i)},e5=function(e,a,t){var n;return n=[e=e/ky/100,a=a/vy/100,t=t/Cy/100].map((function(r){return r>$x?Math.pow(r,1/3):(wy*r+16)/116})),e=n[0],a=n[1],t=n[2],[Math.max(0,116*a-16),500*(e-a),200*(a-t)]},cs=function(e,a,t){var n,r=(e+16)/116,o=isNaN(a)?r:r+a/500,i=isNaN(t)?r:r-t/200;return n=[o,r,i].map((function(s){return s>Ox?Math.pow(s,3):(116*s-16)/wy})),o=n[0],r=n[1],i=n[2],[o*ky*100,r*vy*100,i*Cy*100]},ds=function(e,a,t){return U7.apply(void 0,cs(e,a,t))},ns=function(e,a,t){a=f3(a,-100,100),t=f3(t,-100,100);var n=Math.sqrt(a*a+t*t),r=(180*Math.atan2(t,a)/Math.PI+360)%360;return Math.round(1e4*n)===0&&(r=Number.NaN),[e,n,r]},My=function(e,a,t){return isNaN(t)&&(t=0),t*=Math.PI/180,[e,Math.cos(t)*a,Math.sin(t)*a]},hs=function(e,a,t){return cs.apply(void 0,My(e,a,t))},Ay=function(e,a,t){var n=e+a+t,r=0,o=0;return n>0&&(r=e/n,o=a/n),[r,o,a]},Hx=Object.freeze({__proto__:null,linear2rgb:py,rgb2linear:hy,rgb2hex:gy,hex2rgb:fy,rgb2cmyk:yy,cmyk2rgb:Ny,rgb2hsl:is,hsl2rgb:H4,rgb2hsv:by,hsv2rgb:ss,rgb2hsi:Sy,hsi2rgb:ls,rgb2hwb:Wy,hwb2rgb:us,rgb2xyz:ts,xyz2rgb:U7,xyz2lab:e5,lab2xyz:cs,rgb2lab:function(e,a,t){return e5.apply(void 0,ts(e,a,t))},lab2rgb:ds,lch2lab:My,lab2lch:ns,xyz2lch:function(e,a,t){return ns.apply(void 0,e5(e,a,t))},lch2xyz:hs,xyY2xyz:function(e,a,t){return a===0?[0,0,0]:[e*(t/a),t,t/a*(1-e-a)]},xyz2xyY:Ay});function Ee(e,a){return a===void 0&&(a=!1),function(t,n,r){var o=r.value;r.value=function(){for(var i=[],s=0;s<arguments.length;s++)i[s]=arguments[s];if(i.length>0&&a){var l=JSON.stringify(i);e+=l}if(this.cache.has(e))return this.cache.get(e);var u=o.call.apply(o,xe([this],i,!1));return this.cache.set(e,u),u}}}function Se(e,a,t,n){return e===void 0&&(e=[0,2,2]),a===void 0&&(a=0),t===void 0&&(t=!0),n===void 0&&(n=0),function(r,o,i){var s=i.value;i.value=function(){for(var l=[],u=0;u<arguments.length;u++)l[u]=arguments[u];var c=l[n]===void 0?t:l[n],d=s.call.apply(s,xe([this],l,!1));if(c===!1)return d;var p=typeof c=="number"?Math.round(c):0,m=typeof e=="number"?new Array(d.length).fill(e):e,h=m.map((function(g){return a===1?typeof c=="number"?p:g:g+p}));return d.map((function(g,f){return my(g,h[f])}))}}}var Py=function(e,a,t){var n=e instanceof b3?e:new b3(e),r=a instanceof b3?a:new b3(a),o=f3(t,0,100)/100,i=2*o-1,s=n.alpha()-r.alpha(),l=((i*s==-1?i:(i+s)/(1+i*s))+1)/2,u=1-l,c=[Math.round(f3(n.red()*l+r.red()*u,0,255)),Math.round(f3(n.green()*l+r.green()*u,0,255)),Math.round(f3(n.blue()*l+r.blue()*u,0,255))],d=n.alpha()*o+r.alpha()*(1-o);return new b3(c,d)},te=Math.sqrt,E1=Math.pow,O8=Math.cos,A7=Math.abs,sy=Math.sin,Gx=Math.exp,Xx=Math.atan2,Uy=Math.PI,$4=function(e){return Uy*e/180},rs=function(e,a,t){t===void 0&&(t=!0);var n=Xx(a,e);return t&&(n=(n=(n=180*n/Uy)>0?n:n+360)>360?n-360:n),n},$8=function(e,a){a===void 0&&(a=!0);var t=e.lab(!1),n=t[0],r=t[1],o=t[2];return[n,te(E1(r,2)+E1(o,2)),rs(r,o,a),r,o]},Kx=["CMC","CIE","CIE2000","CIE1994","CIE1976"],Zx="CMC",Vx="CIE2000",qx="CIE1994",Jx="CIE1976",_y=function(e,a,t,n){t===void 0&&(t="CIE");var r=(function(c){var d=c.toUpperCase();return Kx.includes(d)&&d!=="CIE"?d:Vx})(t);if(n=n||{},r===Zx){var o=Object.assign({},{l:1,c:1},n);return(function(c,d,p,m){p===void 0&&(p=1),m===void 0&&(m=1);var h=$8(c,!0),g=h[0],f=h[1],S=h[2],W=h[3],k=h[4],M=$8(d),A=M[0],w=M[1],T=M[3],$=f-w,v=g-A,b=k-M[4],C=te(E1(W-T,2)+E1(b,2)-E1($,2)),P=g<16?.511:.040975*g/(1+.01765*g),y=.0638*f/(1+.0131*f)+.638,N=164<=S&&S<=345?.56+A7(.2*O8($4(S+168))):.36+A7(.4*O8($4(S+35))),U=te(E1(f,4)/(E1(f,4)+1900)),R=y*(U*N+1-U);return te(E1(v/(p*P),2)+E1($/(m*y),2)+E1(C/R,2))})(e,a,o.l,o.c)}if(r===qx){var i={kL:1,kC:1,kH:1,cate:"graphic"},s=Object.assign({},i,n);return(function(c,d,p,m,h,g){p===void 0&&(p=1),m===void 0&&(m=1),h===void 0&&(h=1),g===void 0&&(g="graphic");var f=g==="textiles"?.048:.045,S=g==="textiles"?.014:.015;p=g==="textiles"?2:p;var W=$8(c),k=W[0],M=W[1],A=W[3],w=W[4],T=$8(d),$=T[0],v=T[1],b=T[3],C=k-$,P=M-v,y=w-T[4],N=1+f*M,U=1+S*M,R=te(E1(A-b,2)+E1(y,2)-E1(P,2));return te(E1(C/(1*p),2)+E1(P/(m*N),2)+E1(R/(h*U),2))})(e,a,s.kL,s.kC,s.kH,s.cate)}if(r===Jx)return(function(c,d){var p=c.lab(!1),m=p[0],h=p[1],g=p[2],f=d.lab(!1),S=f[0],W=f[1],k=f[2];return te(E1(m-S,2)+E1(h-W,2)+E1(g-k,2))})(e,a);var l={kL:1,kC:1,kH:1},u=Object.assign({},l,n);return(function(c,d,p,m,h){p===void 0&&(p=1),m===void 0&&(m=1),h===void 0&&(h=1);var g=$8(c),f=g[0],S=g[1],W=g[3],k=g[4],M=$8(d),A=M[0],w=M[1],T=M[3],$=M[4],v=(f+A)/2,b=(S+w)/2,C=(1-te(E1(b,7)/(E1(b,7)+E1(25,7))))/2,P=W*(1+C),y=T*(1+C),N=te(E1(P,2)+E1(k,2)),U=te(E1(y,2)+E1($,2)),R=rs(P,k,!0),z=rs(y,$,!0),E=(N+U)/2,O=A7(R-z)>180?(R+z+360)/2:(R+z)/2,x=1-.17*O8($4(O-30))+.24*O8($4(2*O))+.32*O8($4(3*O+6))-.2*O8($4(4*O-63)),X=A7(z-R)<=180?z-R:A7(z-R)>180&&z<=R?z-R+360:z-R-360,D=A-f,L=w-S,_=2*te(N*U)*sy($4(X)/2),K=1+.015*E1(v-50,2)/te(20+E1(v-50,2)),B=1+.045*E,q=1+.015*E*x,w1=30*Gx(-E1((O-275)/25,2)),Y=-2*te(E1(E,7)/(E1(E,7)+E1(25,7)))*sy(2*$4(w1));return te(E1(D/(p*K),2)+E1(L/(m*B),2)+E1(_/(h*q),2)+Y*(L/(m*B))*(_/(h*q)))})(e,a,u.kL,u.kC,u.kH)},Yx=function(e,a,t){var n=Math.abs,r=Math.max,o=Math.min,i=e instanceof b3?e:new b3(e),s=a instanceof b3?a:new b3(a),l=Object.assign({},{b:125,c:500},t);return!(n(255*i.brightness()/100-255*s.brightness()/100)<=l.b)&&!(r(i.red(),s.red())-o(i.red(),s.red())+(r(i.green(),s.green())-o(i.green(),s.green()))+(r(i.blue(),s.blue())-o(i.blue(),s.blue()))<=l.c)},H8=function(e,a,t){var n,r=function(u){return f3(u,0,100)},o=function(u){return f3(u,0,255)},i={h:[0,function(u){return u%360}],s:[1,r],l:[2,r],r:[0,o],g:[1,o],b:[2,o]},s=i[a][0];if(["h","s","l"].includes(a)){var l=e.hsl();if(t===void 0)return l[s];t=i[a][1](t),l[s]=t,n=H4.apply(void 0,l)}else{if(n=e.rgb(),t===void 0)return n[s];t=i[a][1](t),n[s]=t}return new b3(n,e.alpha())},t5={},Qx=new Set(["rgb","rgba","cmyk","lab","hsl","hsla","hsv","hsva","hsi","hsia","xyz","lch","hwb","hwba"]),ej=/^([a-zA-Z]+)\(([\s\S]+)\)$/,a5=function(e){return typeof e=="string"?e.indexOf("%")===-1?a5(Number(e.trim())):(e=e.split("%")[0],(e=Number(e.trim()))||0):Math.abs(e)<1?100*e:e},zy=function(e,a){a===void 0&&(a=new Set);var t=typeof e=="string"?e:e.join(",");if(a.has(t))throw new Error("Invalid Color");a.add(t);var n="rgb",r=[0,0,0],o=100;if(Array.isArray(e)){if(e.length<3)throw new Error("Invalid Color");for(var i=0;i<e.length;i++)if(i<3)r[i]=e[i];else{if(i!==3||e[3]===void 0)break;o=e[3]}}else{var s=!1,l=e.trim().match(ej);if(l||(s=!0),l){var u=l[1].toLocaleLowerCase();if(n=u,Qx.has(u)||(s=!0),l[2]&&!s){var c=l[2],d=c.indexOf(",")!==-1?",":" ",p=c.split(d);for(i=0;i<3;i++)p[i]!==void 0&&(["lch","lab"].includes(n)&&i===0||["hsl","hsla","hsv","hsva","hwb","hwba","hsi","hsia"].includes(n)&&i>0?r[i]=a5(p[i]):r[i]=Number(p[i].trim()));["rgba","hsla","hsva","hwba","hsia"].includes(n)?(n=n.slice(0,-1),p[3]!==void 0&&(o=a5(p[3]))):n==="cmyk"&&r.push(p[3]!==void 0?a5(p[3]):0)}}if(s){if(!/^#(([a-fA-F\d]{3}){1,2}|[a-fA-F\d]{8})$/.test(e))try{return e=(function(m,h){if(h===void 0&&(h=!1),m=m.toLowerCase(),t5[m]===void 0){if(h)throw new Error("Unknown color name: ".concat(m,")"));return m}return t5[m]})(e,!0),zy(e,a)}catch{throw new Error("Invalid Color")}r=fy(e)}}return[n,r,o]},Ty={thowParseError:!1},b3=(function(){function e(a,t,n){this.cache=new Map,this._rgb=[0,0,0],this._alpha=100;var r={thowParseError:Ty.thowParseError},o=Object.assign({},r,n??{});try{var i=(function(u){var c,d={lab2rgb:ds,hsl2rgb:H4,hsv2rgb:ss,xyz2rgb:U7,hwb2rgb:us,hsi2rgb:ls},p=zy(u),m=p[0],h=p[1],g=p[2];if(m==="rgb")return[h,g];m==="lch"&&(m=(c=["xyz",hs(h[0],h[1],h[2])])[0],h=c[1]);var f=h[0],S=h[1],W=h[2],k=h[3];if(m==="cmyk")return[Ny(f,S,W,k).map((function(A){return f3(A,0,255)})),g];var M="".concat(m,"2rgb");if(typeof d[M]=="function")return[d[M](f,S,W).map((function(A){return f3(A,0,255)})),g];throw new Error("Invalid color")})(a),s=i[0],l=i[1];this._alpha=l,this._rgb=s}catch(u){if(o.thowParseError)throw u}t!==void 0&&(this._alpha=f3(t,0,100))}return e.prototype.red=function(a){return H8(this,"r",a)},e.prototype.green=function(a){return H8(this,"g",a)},e.prototype.blue=function(a){return H8(this,"b",a)},e.prototype.alpha=function(a){return a===void 0?this._alpha:(a=f3(a,0,100),new e(this.rgb(),a))},e.prototype.fadeIn=function(a,t){return a===void 0&&(a=10),a=t&&t==="relative"?this._alpha*a/100:a,new e(this.rgb(),f3(this._alpha+a,0,100))},e.prototype.fadeOut=function(a,t){return a===void 0&&(a=10),a=t&&t==="relative"?this._alpha*a/100:a,new e(this.rgb(),f3(this._alpha-a,0,100))},e.prototype.opacify=function(a,t){return a===void 0&&(a=10),this.fadeIn(a,t)},e.prototype.transparentize=function(a,t){return a===void 0&&(a=10),this.fadeOut(a,t)},e.prototype.hue=function(a){return H8(this,"h",a)},e.prototype.saturation=function(a){return H8(this,"s",a)},e.prototype.lightness=function(a){return H8(this,"l",a)},e.prototype.rgb=function(a){return xe([],this._rgb,!0)},e.prototype.rgba=function(a){return xe(xe([],this.rgb(!1),!0),[this._alpha],!1)},e.prototype.cmyk=function(a){return yy.apply(void 0,this._rgb)},e.prototype.hsl=function(a){return is.apply(void 0,this._rgb)},e.prototype.hsla=function(a){return xe(xe([],this.hsl(!1),!0),[this._alpha],!1)},e.prototype.hsv=function(a){return by.apply(void 0,this._rgb)},e.prototype.hsi=function(a){return Sy.apply(void 0,this._rgb)},e.prototype.hwb=function(a){return Wy.apply(void 0,this._rgb)},e.prototype.xyz=function(a){return ts.apply(void 0,this._rgb)},e.prototype.lab=function(a){return e5.apply(void 0,this.xyz(!1))},e.prototype.lch=function(a){return ns.apply(void 0,this.lab(!1))},e.prototype.xyY=function(a){return Ay.apply(void 0,this.xyz(!1))},e.prototype.hex=function(a){a===void 0&&(a=2);var t=a===0?void 0:a===1?this._alpha:this._alpha===100?void 0:this._alpha,n="color:hex:param_".concat(a);if(this.cache.has(n))return this.cache.get(n);var r=gy.apply(void 0,xe(xe([],this._rgb,!1),[t],!1));return this.cache.set(n,r),r},e.prototype.lighten=function(a,t){a===void 0&&(a=5);var n=this.hsl(!1),r=n[0],o=n[1],i=n[2];return i=f3(i+=t!==void 0&&t==="relative"?i*(a/100):a,0,100),new e(H4(r,o,i),this._alpha)},e.prototype.darken=function(a,t){return a===void 0&&(a=5),this.lighten(-a,t)},e.prototype.saturate=function(a,t){a===void 0&&(a=5);var n=this.hsl(!1),r=n[0],o=n[1],i=n[2];return o=f3(o+=t!==void 0&&t==="relative"?o*(a/100):a,0,100),new e(H4(r,o,i),this._alpha)},e.prototype.desaturate=function(a,t){return a===void 0&&(a=5),this.saturate(-a,t)},e.prototype.spin=function(a){var t=this.hsl(!1),n=t[0],r=t[1],o=t[2];return new e(H4(n=(n+a%360+360)%360,r,o),this._alpha)},e.prototype.adjustHue=function(a){return this.spin(a)},e.prototype.complement=function(){return this.spin(180)},e.prototype.invert=function(){var a=this._rgb.map((function(t){return 255-t}));return new e([a[0],a[1],a[2]],this._alpha)},e.prototype.mix=function(a,t){return t===void 0&&(t=50),Py(this,a,100-f3(t,0,100))},e.prototype.luma=function(){var a=this._rgb.map((function(t){return(t/=255)<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)}));return .2126*a[0]+.7152*a[1]+.0722*a[2]},e.prototype.brightness=function(){var a=this._rgb;return(function(t,n,r){return(299*t+587*n+114*r)/1e3/255*100})(a[0],a[1],a[2])},e.prototype.deltaE=function(a,t,n){return t===void 0&&(t="CMC"),_y(this,a,t,n)},e.prototype.visibility=function(a,t){return Yx(this,a,t)},ue([Se(0,1,!0,0),Ee("color:rgb")],e.prototype,"rgb",null),ue([Se(0,1,!0,0)],e.prototype,"rgba",null),ue([Se(0,1,!0,0),Ee("color:cmyk")],e.prototype,"cmyk",null),ue([Se(0,1,!0,0),Ee("color:hsl")],e.prototype,"hsl",null),ue([Se(0,1,!0,0)],e.prototype,"hsla",null),ue([Se(0,1,!0,0),Ee("color:hsv")],e.prototype,"hsv",null),ue([Se(0,1,!0,0),Ee("color:hsi")],e.prototype,"hsi",null),ue([Se(0,1,!0,0),Ee("color: hwb")],e.prototype,"hwb",null),ue([Se(2,1,!0,0),Ee("color:xyz")],e.prototype,"xyz",null),ue([Se(2,1,!0,0),Ee("color:lab")],e.prototype,"lab",null),ue([Se(2,1,!0,0),Ee("color:lch")],e.prototype,"lch",null),ue([Se(2,1,!0,0),Ee("color:xyY")],e.prototype,"xyY",null),ue([Ee("color:luma")],e.prototype,"luma",null),e})(),aj=function(e,a,t,n){return new b3([e,a,t],n)},tj=function(e,a,t,n){return new b3(H4(e,a,t),n)},nj=function(e,a,t,n){return new b3(ss(e,a,t),n)},rj=function(e,a,t,n){return new b3(ls(e,a,t),n)},oj=function(e,a,t,n){return new b3(us(e,a,t),n)},ij=function(e,a,t,n){return new b3(U7(e,a,t),n)},sj=function(e,a,t,n){return new b3(ds(e,a,t),n)},lj=function(e,a,t,n){return new b3(U7.apply(void 0,hs(e,a,t)),n)};function T3(e,a,t){return new b3(e,a,t)}T3.config=function(e){Object.assign(Ty,e)},T3.random=function(){var e=Q9(0,255),a=Q9(0,255),t=Q9(0,255);return new b3([e,a,t])},T3.convertor=Hx,T3.Color=b3,T3.rgb=aj,T3.hsl=tj,T3.hsv=nj,T3.hsi=rj,T3.hwb=oj,T3.xyz=ij,T3.lab=sj,T3.lch=lj,T3.mix=Py,T3.deltaE=_y,T3.utils={roundDecimal:my,randomRange:Q9},T3.useNames=function(e,a){return(function(t,n){if(n!==void 0&&typeof n=="function"){var r={};for(var o in t){var i=n(o,t[o]),s=i[0],l=i[1];r[s]=l}Object.assign(t5,r)}else Object.assign(t5,t)})(e,a),T3};var Ry=9e5,uj=15e3,Iy=2e3,cj=12e4,dj=3e4,hj=3e5,pj=6e4;function Ey(e){return e<cj?uj:e<hj?dj:pj}function mj(e){return e?typeof e.c!="string"||e.c.trim()==="":!1}function xy(e,a){return!e||typeof e.c!="string"||e.c.trim()===""||typeof a!="string"||a.trim()===""?!1:a.trim().toLowerCase()===e.c.trim().toLowerCase()}function jy(e,a,t){return e?(t??0)>=e.v?"delivered":a-e.t>Ry?"expired":mj(e)?"blind":"poll":"none"}function Ly(e,a){return Math.max(0,e.t+Ry-a)}function Fy(e,a){return e&&a}var gj="The connection dropped before the chart finished - nothing was charged. Generate again.";function By(e){return!!e&&e.isGenerationCancelled===!0}function Dy(e){let a=String(e??"").trim();return a!==""?a:gj}var Wj="2Qy@Y\\{>",ps=f0(Wj);function ms(e){return Nf({signer:ps,transport:$9((a,t)=>fetch(a,t)),clock:{now:()=>Date.now()}},{baseUrl:()=>fs(e),apiPath:"/api",nocache:a=>fj(a==="qualify"?8:16).toString("hex")})}function $y(e){return AbortSignal.timeout(e),e>0?e:Number.MIN_VALUE}var kj="2.1.0.0",vj=new Set(["D3","PLOTLY"]);function Hy(e=process.env){let a=e.BIC_CREDENTIALS_FILE||Sj(bj(),".bic","credentials.json");try{return JSON.parse(Nj(a,"utf-8"))}catch{return{}}}function h4(e){return e!=null&&/^\$\{[^}]*\}$/.test(e.trim())?void 0:e}function gs(e=process.env){let a=Hy(e),t={licenseKey:h4(e.BIC_LICENSE_KEY)??a.licenseKey??"",licensee:h4(e.BIC_LICENSEE)??a.licensee??"",secretKey:h4(e.BIC_SECRET_KEY)??a.secretKey??""};if(!t.licenseKey||!t.licensee)throw new Error(`Missing BIC trial/paid credentials. Set BIC_LICENSE_KEY + BIC_LICENSEE (BIC_SECRET_KEY optional) in the MCP server's env, or put {"licenseKey":"\u2026","licensee":"\u2026"} in ~/.bic/credentials.json. MCP access requires a trial or paid account (no freemium).`);return t}function fs(e=process.env){let a=Hy(e);return(h4(e.BIC_URL)??a.url??"https://bizintelligencechampions.com").replace(/\/+$/,"")}function r5(e=process.env){return h4(e.BIC_MCP_CLIENT_VERSION)??kj}function _7(e,a,t=process.env){let n=yj(),r=cf(e.shape),o=(e.fontFamily??"").replace(/[^A-Za-z0-9 ,.\-]/g," ").replace(/\s+/g," ").trim().slice(0,100),i=uf({measure:()=>({width:Math.round(e.width??800),height:Math.round(e.height??600)})});return{payload:{...lf({triple:()=>({licensee:a.licensee.trim(),licenseKey:a.licenseKey.trim(),secretKey:a.secretKey.trim()})}).request,clientVersion:r5(t),host:"SDK",supportsStreaming:!0,...i.request,totalRows:e.totalRows,cultureCode:e.cultureCode??"en-US",...v0({genNew:!0,settingVersion:0}),identifier:"",temp:Ei,modifiers:[],backgroundColor:"#ffffff",palette:"",shape:e.shape,model:e.model??h4(t.BIC_MCP_MODEL)??"",renderer:e.renderer??"D3",language:e.language??"",sampleCsv:e.sampleCsv??null,...hf({budget:3}),rendererSpecificPayload:null,reasoningMode:e.reasoningMode||t.BIC_MCP_REASONING||"",...df({renderers:vj}),correlationId:n,compactness:"",clientHints:{supportsDatasetGlobal:!0,supportsMermaid:!0,supportsHtmlScene:!0,...i.hints,rowCount:e.totalRows,...pf(e.leafCardinality),maxNonMeasureCardinality:r,favorStyle:e.chartHint??"",userCommentary:e.prompt??"",...e.rowsPolicy?{rowsPolicy:e.rowsPolicy}:{},...e.requiredColumns?.length?{requiredColumns:e.requiredColumns}:{},...e.forbidDerivedColumns?{forbidDerivedColumns:!0}:{},...e.levelOfDetail?{levelOfDetail:e.levelOfDetail}:{},...o?{suggestFontFamily:o}:{},...e.geoExtent?{geoExtent:e.geoExtent}:{}}},correlationId:n}}function Cj(e){if(e.ok||!e.isServiceError||Ii(e)||e.isRateLimited===!0||!e.raw)return!1;let a=sf(k0(e.raw));if(a!==null)return a;let t=(e.errorMessage||"").toLowerCase();return/billed|still be running|completed server-side|may have completed/.test(t)||/no credits were used|nothing was generated/.test(t)?!1:/could ?n[o']?t reach|unable to reach|provider|upstream|rate.?limit|temporarily|try again|timed? out contacting|service unavailable/.test(t)}var Oy=[2e3,6e3];async function Gy(e,a=process.env){let t=Math.max(0,Math.min(2,Number(h4(a.BIC_MCP_GENERATE_RETRIES)??1))),n=[],r=null;for(let o=0;o<=t;o++){if(o>0){let i=Oy[Math.min(o-1,Oy.length-1)];e.onProgress?.(`Provider unavailable \u2014 retrying in ${Math.round(i/1e3)}s (attempt ${o+1} of ${t+1})`),await new Promise(s=>setTimeout(s,i))}if(r=await wj(e,a),r.correlationId&&n.push(r.correlationId),!Cj(r))break}return r&&!r.ok&&n.length>1?{...r,errorMessage:`${r.errorMessage} (retried ${n.length} times; correlationIds: ${n.join(", ")})`}:r}function ys(e,a){return{ok:!1,code:"",language:"",version:0,errorMessage:a,isServiceError:!0,isRefusal:!1,isRateLimited:!1,retryAfterSeconds:null,outputHash:"",codeSummary:"",finalChartName:"",warningMessage:"",creditCost:null,geoColumn:"",geoKind:"",pointCityColumn:"",pointStateColumn:"",pointZipColumn:"",pointCountryColumn:"",pointLatColumn:"",pointLonColumn:"",destPointCityColumn:"",destPointStateColumn:"",destPointZipColumn:"",destPointCountryColumn:"",destPointLatColumn:"",destPointLonColumn:"",correlationId:e,raw:null}}function Xy(e,a){let t=k0(e),n=t.geoPointCols??{},r=n.dest??{};return{ok:!!t.code&&!t.errorMessage,code:t.code,language:t.language,version:t.version,errorMessage:t.errorMessage,isServiceError:t.isServiceError,isRefusal:t.isRefusal,isRateLimited:t.isRateLimited,retryAfterSeconds:t.retryAfterSeconds,outputHash:t.outputHash,codeSummary:t.codeSummary,finalChartName:t.finalChartName,warningMessage:t.warningMessage,creditCost:t.creditCost,geoColumn:t.geoColumn,geoKind:t.geoKind,pointCityColumn:n.city??"",pointCountryColumn:n.country??"",pointStateColumn:n.state??"",pointZipColumn:n.zip??"",pointLatColumn:n.lat??"",pointLonColumn:n.lon??"",destPointCityColumn:r.city??"",destPointCountryColumn:r.country??"",destPointStateColumn:r.state??"",destPointZipColumn:r.zip??"",destPointLatColumn:r.lat??"",destPointLonColumn:r.lon??"",correlationId:a,servedCorrelationId:t.servedCorrelationId,isVersionNotFound:t.isVersionNotFound,isGenerationCancelled:t.isGenerationCancelled,raw:e}}async function wj(e,a){let t=gs(a),{payload:n,correlationId:r}=_7(e,t,a),o=Number(h4(a.BIC_MCP_TIMEOUT_MS)??9e5),i=Date.now(),s=h=>ys(r,h),l=h=>({...s(`Cancelled after ${h}s. The server was told to stop and bills only the passes that had already completed; nothing further is running. correlationId ${r}.`),isServiceError:!1}),u=h=>s(`Gave up waiting after ${h}s \u2014 this MCP client's own timeout (BIC_MCP_TIMEOUT_MS=${o}). The generation may still be running server-side and may be billed. Raise BIC_MCP_TIMEOUT_MS, or lower the cost of the request (simpler chart type, fewer rows, reasoning_mode "1P"). correlationId ${r}.`),c=(h,g)=>e.signal?.aborted?l(h):g?.name==="TimeoutError"||g?.name==="AbortError"?u(h):s(`Could not reach the BIC backend after ${h}s: ${String(g?.message??g)}. correlationId ${r}.`),d;try{d=$y(o)}catch(h){return c(Math.round((Date.now()-i)/1e3),h)}let p=await ms(a).generate(n,{timeoutMs:d,signal:e.signal??null,onStage:e.onProgress??null}),m=Math.round((Date.now()-i)/1e3);if(p.kind==="transport"&&!p.headersReceived)return c(m,p.error);if(p.kind==="http"){let g=(p.status===499||p.status===502||p.status===504)&&p.bodyStart.trim().length===0?`The connection was cut by an intermediary after ${m}s (HTTP ${p.status}, empty body) while the request was still in flight. The generation very likely COMPLETED server-side and MAY HAVE BEEN BILLED \u2014 it just could not be delivered. Raising this client's timeout will NOT help: the ceiling is a gateway between us, not your wait. Get under it by making the request cheaper \u2014 a simpler chart type, fewer rows, or reasoning_mode "1P" \u2014 and quote correlationId ${r} to BIC support to recover or refund this generation.`:`HTTP ${p.status}: ${p.bodyStart} (correlationId ${r})`;return s(g)}if(p.kind==="transport"){let h=p.error;if(e.signal?.aborted)return l(m);if(h?.name==="TimeoutError"||h?.name==="AbortError")return u(m);let g=String(h?.message??h);return Fy(!0,n.genNew)?Uj({correlationId:r,startedAt:i,cutAtMs:Date.now(),deadlineAt:i+o,pick:e.chartHint??"",cause:g,signal:e.signal,onProgress:e.onProgress},{fetchByCorrelation:f=>Aj(e,r,a,f),now:()=>Date.now(),sleep:Pj}):s(`The response stream ended after ${m}s without a result. The generation may have COMPLETED and BEEN BILLED \u2014 quote correlationId ${r} to BIC support to recover or refund it. (${g})`)}return Xy(p.value,r)}var Mj=6e4;async function Aj(e,a,t,n){let r=gs(t),{payload:o}=_7(e,r,t),i=await ms(t).generate({...o,...v0({genNew:!1,fetchCorrelationId:a}),correlationId:a},{timeoutMs:Mj,signal:n??null});if(i.kind==="transport")throw i.error;return i.kind==="http"?ys(a,`HTTP ${i.status}: ${i.bodyStart}`):Xy(i.value,a)}function Pj(e,a){return new Promise((t,n)=>{if(a?.aborted){n(a.reason??new Error("aborted"));return}let r=()=>{clearTimeout(o),n(a?.reason??new Error("aborted"))},o=setTimeout(()=>{a?.removeEventListener("abort",r),t()},e);a?.addEventListener("abort",r,{once:!0})})}async function Uj(e,a){let t={v:1,t:e.startedAt,c:e.correlationId,p:e.pick,h:0},n=Math.round((e.cutAtMs-e.startedAt)/1e3),r=()=>Math.min(Ly(t,a.now()),e.deadlineAt-a.now()),o=u=>ys(e.correlationId,u),i=`It may still complete and be billed \u2014 quote correlationId ${e.correlationId} to BIC support to recover or refund it.`;if(jy(t,a.now(),0)!=="poll"||r()<=0)return o(`The response stream was cut after ${n}s, after the server had accepted the request, and there is no time left in this call to check for the chart. ${i} (${e.cause})`);let s=Iy,l=0;for(;;){try{await a.sleep(Math.max(0,Math.min(s,r())),e.signal)}catch{}if(e.signal?.aborted)return{...o(`Cancelled while checking for a chart whose response stream was cut after ${n}s. The server had already accepted that generation, so cancelling the check did not stop it. ${i}`),isServiceError:!1};l++,e.onProgress?.(`The connection dropped after ${n}s, before the chart arrived. Checking for it on the server (check ${l})`);let u=null;try{u=await a.fetchByCorrelation(e.signal)}catch{}if(u?.ok&&u.code&&xy(t,u.servedCorrelationId))return{...u,correlationId:e.correlationId,creditCost:null,recoveredAfterMs:a.now()-e.startedAt};if(By(u))return o(`${Dy(u.errorMessage)} correlationId ${e.correlationId}.`);if(!(!u||u.ok&&!!u.code||u.isVersionNotFound||u.isServiceError&&!u.isRefusal))return o(`The response stream was cut after ${n}s. Checking for the chart by its correlation, the server answered that there is nothing to deliver: ${u.errorMessage||"no code returned"}. correlationId ${e.correlationId}.`);if(r()<=0){let d=Math.round((a.now()-e.cutAtMs)/1e3);return o(`The response stream was cut after ${n}s, after the server had accepted the request. This client checked for the finished chart ${l} time(s) over ${d}s and it had not arrived when the wait ended (the shared recovery window, or BIC_MCP_TIMEOUT_MS, whichever is sooner). ${i} (${e.cause})`)}s=Ey(a.now()-t.t)}}var o5="metered: free within an hourly allowance, usage credits beyond it";async function Ns(e,a=process.env){let t;try{t=gs(a)}catch{t={licenseKey:"",licensee:"",secretKey:""}}let{payload:n}=_7({shape:e.shape,totalRows:e.totalRows,leafCardinality:e.leafCardinality,geoExtent:e.geoExtent,width:e.width,height:e.height,renderer:e.renderer??"",language:e.language??"",levelOfDetail:e.levelOfDetail},t,a),r=ms(a),o=async c=>r.qualify(n,{timeoutMs:$y(Number(h4(a.BIC_MCP_QUALIFY_TIMEOUT_MS)??6e4)),route:c}),i=await o("/RegiaBI/whatfits");if(i.kind==="http"&&i.status===404&&(i=await o("/LLMChart/qualify")),i.kind==="transport")throw i.error;if(i.kind==="http")return{ok:!1,charts:[],refused:[],noFitSummary:"",errorMessage:`HTTP ${i.status}: ${i.bodyStart.slice(0,200)}`};let s=of(i.value);if(s.errorMessage)return{ok:!1,charts:[],refused:[],noFitSummary:"",errorMessage:s.errorMessage};let l=(s.charts??[]).map(c=>({name:c.name,description:c.description,rank:c.rank,score:c.score,renderer:c.renderer,language:c.language,recommended:c.recommended,isPreview:c.isPreview})),u=s.refused.map(c=>({name:c.name,reason:c.reason,isVeto:c.isVeto}));return{ok:!0,charts:l,refused:u,noFitSummary:s.noFitSummary,errorMessage:""}}/*! @bicharts/shape-core — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; US Census/TIGER (public domain). Full text: NOTICE in this package. */function _j(e){return!e||!e.trim()?0:Math.max(0,e.trim().split(/\r?\n/).length-1)}function Ky(e,a,t="",n=process.env){let{payload:r}=_7(e,{licenseKey:"",licensee:"",secretKey:""},n),o=_j(e.sampleCsv),i=Ji(r,{sampleNote:`${o} obfuscated sample row(s) travel at privacy_level ${a}; their values are not shown here. Lower privacy_level to send none.`,emptyShapeNote:"No columns were measured - pass csv_path, csv_text or data."});return{head:`NOTHING WAS SENT. This is the request generate_chart would send for these arguments${t}, with the licence, install id and correlation id removed (they are credentials, not your data). privacy_level ${a}: ${o>0?`${o} obfuscated sample row(s) travel`:"no rows travel - only the measured shape"}.`,preview:i,sampleRows:o}}function i5(e){let t=(e||"").replace(/[^A-Za-z0-9]+/g," ").trim().split(/\s+/).filter(Boolean).map(n=>n[0].toUpperCase()+n.slice(1)).join("");return(!t||/^[0-9]/.test(t))&&(t="Bic"+t),t.endsWith("Chart")?t:t+"Chart"}var zj=/^__.*__$/;function Zy(e){let a=i5(e.chartName),t=e.columns.filter(i=>!zj.test(i.name)).map(i=>({name:i.name,dataType:i.dataType,isMeasure:!!i.isMeasure})),n=e.plugins.flatMap((i,s)=>[`// @ts-ignore - ${i} often ships no type declarations; the chart only reaches it through d3. npm install ${i}`,`import * as d3Plugin${s} from "${i}";`]),r=e.plugins.map((i,s)=>`d3Plugin${s}`),o=i=>JSON.stringify(i,null,2);return[`// BIC generated React host for "${e.chartName}" - renders ./chart.js through @bicharts/chart-host.`,"// Regenerate with the MCP generate_chart tool rather than editing: it is rewritten with the chart.",'import { useMemo } from "react";','import * as d3base from "d3";',...n,'import { assembleD3, type GeoPointBinding, type MarkAnnotation } from "@bicharts/chart-host";','import { BicChart, BicChartGroup } from "@bicharts/chart-host/react";','import code from "./chart.js?raw";',"","/** The columns this chart was generated for. Each row must be keyed by these names. */",`export const columns = ${o(t)};`,"","/** How the payload is built from rows: the choropleth join, and where points and a route's far end come from. */","export const binding: {"," geo: { column: string; kind: string } | null;"," point: GeoPointBinding | null;"," destination: GeoPointBinding | null;",`} = ${o(e.binding)};`,"",'/** The geometry the chart draws on ("" when it draws none). */',`export const geoKind = ${JSON.stringify(e.geoKind||"")};`,"","// One d3 for the chart, with the plugins its code calls attached (an ES-module d3 namespace cannot be assigned onto).",`const d3 = assembleD3(d3base${r.length?", "+r.join(", "):""});`,"",'const key = (s: string) => s.replace(/^[^[]*\\[(.+)\\]$/, "$1").toLowerCase().replace(/[^a-z0-9]/g, "");',"","/**"," * Rows keyed by this chart's column names, from a query result of { columns: [{ name }], rows: [[...]] }.",` * A DAX result's "Table[Column]" and "[Measure]" headers match by the bracketed name, ignoring case, spaces and`,' * punctuation, so "[Revenue per Capita]" fills RevenuePerCapita with no alias. Pass `rename` for anything else.'," */","export function rowsFromTable("," table: { columns: { name: string }[]; rows: unknown[][] },"," rename: Record<string, string> = {},","): Record<string, unknown>[] {"," const wanted = new Map(columns.map((c) => [key(c.name), c.name]));"," const target = table.columns.map((c) => rename[c.name] ?? wanted.get(key(c.name)));"," return table.rows.map((r) => {"," const o: Record<string, unknown> = {};"," target.forEach((t, k) => { if (t) o[t] = r[k]; });"," return o;"," });","}","",`export interface ${a}Props {`," /** The live query result as it arrives ({ columns, rows }); mapped with rowsFromTable. Or pass rows. */"," table?: { columns: { name: string }[]; rows: unknown[][] };"," /** Header -> column name, for any header rowsFromTable can't match by name. */"," rename?: Record<string, string>;"," /** Rows already keyed by the chart's column names, instead of table. */"," rows?: Record<string, unknown>[];"," width: number;"," height: number;"," /** The clicked marks' source rows - read a stable key from them (an id or code), never a row position. */"," onSelectRows?: (rows: Record<string, unknown>[]) => void;"," /** Extra chart options (palette, colour scale, theme colours); a restyle, never a regeneration. */"," options?: Record<string, unknown>;"," /**"," * Notes on marks: a badge on each key's mark, kept there through filters, re-queries and zooms -",' * [{ column: "<a key column above>", value: "<its value>", label: "2", title: "the note" }], or a key over'," * several columns: { where: { <column>: <value>, ... } } (a route by both ends). Key by stable values from"," * the model, never a row position."," */"," annotations?: MarkAnnotation[];"," /** A badge was clicked (the mark beneath is not selected). */"," onAnnotationClick?: (annotation: MarkAnnotation) => void;","}","","/** Renders the chart from live data: the group builds the payload (row index, geometry columns) from the binding. */",`export function ${a}({ table, rename, rows: given, width, height, onSelectRows, options,`,` annotations, onAnnotationClick }: ${a}Props) {`," // Mapped once per result: a new rows array rebuilds the chart's payload."," const rows = useMemo(() => given ?? (table ? rowsFromTable(table, rename) : []), [given, table, rename]);"," return ("," <BicChartGroup columns={columns} rows={rows}"," geo={binding.geo} point={binding.point} destination={binding.destination}>"," <BicChart code={code} d3={d3} geoKind={geoKind || undefined}"," options={{ width, height, ...options }}"," annotations={annotations} onAnnotationClick={onAnnotationClick}"," onSelect={(idxs) => onSelectRows?.(idxs.map((k) => rows[k]))} />"," </BicChartGroup>"," );","}",""].join(`
|
|
76
76
|
`)}import{spawn as Jy}from"node:child_process";import{existsSync as bs,readFileSync as T7,readdirSync as Vy,writeFileSync as Tj}from"node:fs";import{join as p4}from"node:path";function Cs(e,a,t=3e5){return new Promise((n,r)=>{let o=Jy("npm",a,{cwd:e,shell:process.platform==="win32",windowsHide:!0,stdio:["ignore","ignore","pipe"]}),i="";o.stderr.on("data",l=>{i=(i+l).slice(-2e3)});let s=setTimeout(()=>{o.kill(),r(new Error(`timed out after ${t/1e3} s`))},t);o.on("error",l=>{clearTimeout(s),r(l)}),o.on("close",l=>{clearTimeout(s),l===0?n():r(new Error(i.trim()||`exit ${l}`))})})}function ws(e){let a=p4(e,"package.json"),t={has:new Set,hasCssTheme:!1};if(!bs(a))return{ok:!1,why:`no package.json in ${e}`,...t};let n;try{n=JSON.parse(T7(a,"utf-8"))}catch(s){return{ok:!1,why:`package.json does not parse (${s?.message??s})`,...t}}let r=new Set([...Object.keys(n.dependencies??{}),...Object.keys(n.devDependencies??{})]);if(!r.has("@microsoft/fabric-app-data")||!bs(p4(e,"fabric.yaml")))return{ok:!1,has:r,hasCssTheme:!1,why:"this is not a Rayfin data app project (it needs @microsoft/fabric-app-data and fabric.yaml)"};let o=p4(e,"node_modules","@microsoft","fabric-visuals","dist","index.d.ts"),i=bs(o)&&/\buseCssTheme\b/.test(T7(o,"utf-8"));return{ok:!0,has:r,hasCssTheme:i}}function Yy(e,a,t){let n=[];return t?n.push(`@bicharts/chart-host@${t}`):e.has("@bicharts/chart-host")||n.push(a?`@bicharts/chart-host@^${a}`:"@bicharts/chart-host"),e.has("d3")||n.push("d3"),{deps:n,devDeps:e.has("@types/d3")?[]:["@types/d3"]}}function Qy(e){return/@bicharts\/chart-host@(\d+\.\d+\.\d+[^\s,]*)/.exec(e)?.[1]??null}var eN="// Added by the RegiaBI chart server (setup_fabric_app). Yours to edit; it is never rewritten.",Rj=[eN,'import { useMemo } from "react";','import { useCssTheme } from "@microsoft/fabric-visuals";',"","/**"," * Chart options from the app's resolved Fabric theme, so every chart follows light, dark and the host's palette."," * Spread with the measured size: options={{ ...useBicChartOptions(), width, height }}. A change here restyles"," * the chart live; it never regenerates it."," */","export function useBicChartOptions() {"," const theme = useCssTheme();"," return useMemo(() => ({"," palette: theme.categoricalPalette ? [...theme.categoricalPalette] : [],"," themeFg: theme.foreground,"," themeAccent: theme.brandForeground,"," backgroundColor: theme.background,"," }), [theme]);","}",""].join(`
|
|
77
|
-
`),Ij=[eN,'import { useRef, type ReactNode } from "react";','import { useMeasuredSize } from "@bicharts/chart-host/react";',"","export type QueryTable = { columns: { name: string }[]; rows: unknown[][] };","","/** What useSemanticModelQuery returns (the template's hook); only these fields are read. */","export interface PanelQueryResult {",' data?: { status: "success"; table: QueryTable } | { status: "error"; error: { message: string } } | undefined;'," isLoading: boolean;"," error?: Error;","}","","interface BicChartPanelProps {"," result: PanelQueryResult;"," /** The panel's height when its
|
|
78
|
-
`),Ss="1.35.0-alpha.1413",z7="1.36.1",Ej="npx rayfin init --services auth,data --auth-methods fabric --dialect mssql --overwrite --project-name <id from rayfin/rayfin.yml> .",xj=["---","name: regiabi-charts","description: Use when adding or fixing a chart from the RegiaBI chart server (@bicharts/chart-host, BicChartPanel, a generated chart.component.tsx) in this Fabric App, laying out the cards and pages that hold charts, saving notes on chart marks, or deploying with rayfin up. Heads off the layout, Rayfin version and deploy traps measured on real builds.","---","","# RegiaBI charts in this Fabric App","","Added by the RegiaBI chart server's setup_fabric_app; it's never rewritten. The full guide is the chart server's `get_guide` tool","(topic `fabric-app`). The Rayfin facts here were checked against Rayfin's own docs on Rayfin "+z7+", a preview:","where your installed version differs (setup_fabric_app's reply names it), its own docs","(`node_modules/@microsoft/rayfin-guide/assets/docs`) win.","","## Layout: a chart is never clipped or squashed","","- Render every chart inside `BicChartPanel` (`src/components/bic-chart-panel.tsx`). It sizes the chart from its cell, never from the chart.","- Give each chart its minimum with `minChartWidth` and `minChartHeight` (a world map about 560 x 300; a time series wants height)."," Below that the panel scrolls; it never squashes or clips the chart.","- Take the actual size from the layout - percent, flex or grid `fr` - and never a fixed height smaller than the chart's minimum.","- Put `min-h-0` on every flex child between a card and its chart (`min-w-0` in a row). A flex item's default `min-height: auto`"," lets it grow past its card, and the card's `overflow-hidden` slices off the rest.","- Open anything secondary - notes, details, a form - in a dialog, drawer or popover that overlays the page through a portal"," (`createPortal(..., document.body)`), never inside a chart's card: a card has a fixed height and clips it.","","## Before you deploy: check every chart locally","","- Check every chart with the chart server's `check_chart` tool, at the size the panel will give it: by default it reads the"," chart's `minChartWidth` and `minChartHeight` off its `BicChartPanel`. A `WARNING` line in its reply is a label cut off at"," that size. You don't need to deploy to check a chart.","- Type-check with `npx tsc -b`: build mode builds the `rayfin/` project first, and a bare `tsc --noEmit` reports TS6305.","","## Rayfin packages: one version","","- Every `@microsoft/rayfin-*` package must be on the same version, and deploying needs 1.35 or later."," setup_fabric_app puts them all on npm's latest, the release `rayfin init` installs, so run it before `rayfin init`."," Run it again after anything else installs Rayfin packages: an install of only some of them leaves two copies of"," `rayfin-auth` and a TS2345 between them.","","## Turning on the data service (notes, saved settings)","","- The template ships with it off. One command turns it on:"," `"+Ej+"`"," Without `--overwrite` it prints 'Initialization cancelled' and exits 0; without `--project-name` it stops in a"," non-interactive shell. It rewrites `rayfin/rayfin.yml` and `.gitignore`, so diff both and put back anything of yours.","- It doesn't write the entities, `rayfin/data/schema.ts`, the root tsconfig's reference to `./rayfin`, or the typed client."," The notes-on-marks recipe in get_guide `fabric-app` has each one, with code that type-checks on Rayfin "+z7+". It was"," checked against Rayfin's own docs for that version, so on it the recipe is the version-matched source: read Rayfin's docs"," only for what it doesn't cover.","- Don't stand up a backend to test notes; the deploy creates the tables. Finish with `npx tsc -b` and the tests, and say the"," notes go live on deploy.","","## Deploying (`npx rayfin up`)","","- Signed in? `npx rayfin login status` (a subcommand, not a `--status` flag); `npx rayfin login` if not.",'- Name the workspace: `npx rayfin up -w "<workspace>"`. Left out, Rayfin '+z7+" deploys to My Workspace.","- The Fabric item is named by `id:` in `rayfin/rayfin.yml`, not `name:`. Two projects with the same `id:` in one workspace"," deploy into one item: give each its own `id:`, or deploy with `--item-name <unique-name>`.","- Pass `--yes` to reuse an existing item only when you know it's yours: it deploys into whatever item has the name.","- Deleted the app outside Rayfin? `rayfin/.deployments.json` still names the deleted item, so the next `rayfin up` fails with"," 404 Not Found. Move that file aside and deploy again.",""].join(`
|
|
77
|
+
`),Ij=[eN,'import { useRef, type ReactNode } from "react";','import { useMeasuredSize } from "@bicharts/chart-host/react";',"","export type QueryTable = { columns: { name: string }[]; rows: unknown[][] };","","/** What useSemanticModelQuery returns (the template's hook); only these fields are read. */","export interface PanelQueryResult {",' data?: { status: "success"; table: QueryTable } | { status: "error"; error: { message: string } } | undefined;'," isLoading: boolean;"," error?: Error;","}","","interface BicChartPanelProps {"," result: PanelQueryResult;"," /** The panel's height when its cell has none (a section with no height of its own). A cell with a height - even a"," * smaller one - keeps it: the panel fills that cell and scrolls, so it never runs over what's below it. */"," minHeight?: number;"," /** The smallest size this chart is drawn at; below it the panel scrolls rather than squash or clip the chart."," * A world map wants about 2:1 (e.g. 560 x 300); a time series wants height. */"," minChartWidth?: number;"," minChartHeight?: number;"," /** Renders the chart once the query has rows and the panel has a size. */"," children: (table: QueryTable, size: { width: number; height: number }) => ReactNode;","}","","/**"," * A chart's box: sized by the layout (put it in a cell that has a height - a grid row, h-full, a flex item with"," * min-h-0), never by the chart. The measured box is absolutely positioned inside its cell, so a drawn chart can't"," * make it taller than the card shows; when the cell is smaller than the chart's minimum, the panel scrolls. Shows"," * the query's loading, error and empty states in place of the chart."," * <BicChartPanel result={useSemanticModelQuery({ connection, query })} minChartWidth={560} minChartHeight={300}>"," * {(table, size) => <MyChart table={table} {...size} options={options} />}"," * </BicChartPanel>"," */","export function BicChartPanel({ result, minHeight = 360, minChartWidth = 320, minChartHeight = 240, children }: BicChartPanelProps) {"," const ref = useRef<HTMLDivElement>(null);"," const { width: boxWidth, height: boxHeight } = useMeasuredSize(ref);"," const width = Math.max(boxWidth, minChartWidth);"," const height = Math.max(boxHeight, minChartHeight);"," const { data, isLoading, error } = result;",' const failed = error?.message ?? (data?.status === "error" ? data.error.message : undefined);',' const table = data?.status === "success" ? data.table : undefined;',' const note = (text: string, role?: "alert") => (',' <div role={role} style={{ display: "grid", placeItems: "center", height: "100%", opacity: 0.7, fontSize: 13 }}>{text}</div>'," );"," return (",' <div style={{ position: "relative", width: "100%", height: "100%", minWidth: 0 }}>'," {/* The fallback height, capped at 100% of the panel: in a cell with a height the cap holds it to the cell; in a"," cell with none, 100% resolves to nothing and this gives the panel its height. A min-height can't tell the two. */}",' <div aria-hidden="true" style={{ height: minHeight, maxHeight: "100%" }} />',' <div ref={ref} style={{ position: "absolute", inset: 0, overflow: "auto" }}>',' {failed ? note(`The query failed: ${failed}`, "alert")',' : isLoading || !table ? note("Loading...")',' : table.rows.length === 0 ? note("No data for this selection.")'," : boxWidth > 0 && boxHeight > 0 && width > 0 && height > 0 ? children(table, { width, height })"," : null}"," </div>"," </div>"," );","}",""].join(`
|
|
78
|
+
`),Ss="1.35.0-alpha.1413",z7="1.36.1",Ej="npx rayfin init --services auth,data --auth-methods fabric --dialect mssql --overwrite --project-name <id from rayfin/rayfin.yml> .",xj=["---","name: regiabi-charts","description: Use when adding or fixing a chart from the RegiaBI chart server (@bicharts/chart-host, BicChartPanel, a generated chart.component.tsx) in this Fabric App, laying out the cards and pages that hold charts, saving notes on chart marks, or deploying with rayfin up. Heads off the layout, Rayfin version and deploy traps measured on real builds.","---","","# RegiaBI charts in this Fabric App","","Added by the RegiaBI chart server's setup_fabric_app; it's never rewritten. The full guide is the chart server's `get_guide` tool","(topic `fabric-app`). The Rayfin facts here were checked against Rayfin's own docs on Rayfin "+z7+", a preview:","where your installed version differs (setup_fabric_app's reply names it), its own docs","(`node_modules/@microsoft/rayfin-guide/assets/docs`) win.","","## Layout: a chart is never clipped or squashed","","- Render every chart inside `BicChartPanel` (`src/components/bic-chart-panel.tsx`). It sizes the chart from its cell, never from the chart.","- Give each chart its minimum with `minChartWidth` and `minChartHeight` (a world map about 560 x 300; a time series wants height)."," Below that the panel scrolls; it never squashes or clips the chart.","- Take the actual size from the layout - percent, flex or grid `fr` - and never a fixed height smaller than the chart's minimum.","- Put `min-h-0` on every flex child between a card and its chart (`min-w-0` in a row). A flex item's default `min-height: auto`"," lets it grow past its card, and the card's `overflow-hidden` slices off the rest.","- A chart with controls drawn inside it (sliders, steppers, a reset) gets its card's full width. Put a side panel that goes"," with it - saved scenarios, a form - below the chart, not beside it: beside it, the chart's cell drops under its minimum.","- When you stack a panel below a chart, don't keep a fixed card height that can't hold both: let the card grow (a `min-h-*`"," in place of its `h-*`), or give the panel below `min-h-0 flex-1 overflow-auto` so it scrolls inside the card. Give the"," chart's cell at least the chart's `minChartHeight` (`h-72` is 288px, under a 300 minimum).","- Open anything secondary - notes, details, a form - in a dialog, drawer or popover that overlays the page through a portal"," (`createPortal(..., document.body)`), never inside a chart's card: a card has a fixed height and clips it.","","## Before you deploy: check every chart locally","","- Check every chart with the chart server's `check_chart` tool, at the size the panel will give it: by default it reads the"," chart's `minChartWidth` and `minChartHeight` off its `BicChartPanel`. A `WARNING` line in its reply is a label cut off at"," that size. You don't need to deploy to check a chart.","- Type-check with `npx tsc -b`: build mode builds the `rayfin/` project first, and a bare `tsc --noEmit` reports TS6305.","","## Rayfin packages: one version","","- Every `@microsoft/rayfin-*` package must be on the same version, and deploying needs 1.35 or later."," setup_fabric_app puts them all on npm's latest, the release `rayfin init` installs, so run it before `rayfin init`."," Run it again after anything else installs Rayfin packages: an install of only some of them leaves two copies of"," `rayfin-auth` and a TS2345 between them.","","## Turning on the data service (notes, saved settings)","","- The template ships with it off. One command turns it on:"," `"+Ej+"`"," Without `--overwrite` it prints 'Initialization cancelled' and exits 0; without `--project-name` it stops in a"," non-interactive shell. It rewrites `rayfin/rayfin.yml` and `.gitignore`, so diff both and put back anything of yours.","- It doesn't write the entities, `rayfin/data/schema.ts`, the root tsconfig's reference to `./rayfin`, or the typed client."," The notes-on-marks recipe in get_guide `fabric-app` has each one, with code that type-checks on Rayfin "+z7+". It was"," checked against Rayfin's own docs for that version, so on it the recipe is the version-matched source: read Rayfin's docs"," only for what it doesn't cover.","- Don't stand up a backend to test notes; the deploy creates the tables. Finish with `npx tsc -b` and the tests, and say the"," notes go live on deploy.","","## Deploying (`npx rayfin up`)","","- Signed in? `npx rayfin login status` (a subcommand, not a `--status` flag); `npx rayfin login` if not.",'- Name the workspace: `npx rayfin up -w "<workspace>"`. Left out, Rayfin '+z7+" deploys to My Workspace.","- The Fabric item is named by `id:` in `rayfin/rayfin.yml`, not `name:`. Two projects with the same `id:` in one workspace"," deploy into one item: give each its own `id:`, or deploy with `--item-name <unique-name>`.","- Pass `--yes` to reuse an existing item only when you know it's yours: it deploys into whatever item has the name.","- Deleted the app outside Rayfin? `rayfin/.deployments.json` still names the deleted item, so the next `rayfin up` fails with"," 404 Not Found. Move that file aside and deploy again.",""].join(`
|
|
79
79
|
`);function aN(e){let a={"src/components/bic-chart-panel.tsx":Ij,".agents/skills/regiabi-charts/SKILL.md":xj};return e.hasCssTheme&&(a["src/lib/bic-chart-options.ts"]=Rj),a}var vs=/^@microsoft\/rayfin-/;function Ba(e,a){let t=o=>{let i=/^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(o.trim())??[];return{nums:[1,2,3].map(s=>Number(i[s]??0)),pre:i[4]?i[4].split("."):[]}},n=t(e),r=t(a);for(let o=0;o<3;o++)if(n.nums[o]!==r.nums[o])return n.nums[o]-r.nums[o];if(!n.pre.length||!r.pre.length)return(n.pre.length?-1:0)+(r.pre.length?1:0);for(let o=0;o<Math.max(n.pre.length,r.pre.length);o++){let i=n.pre[o],s=r.pre[o];if(i===void 0)return-1;if(s===void 0)return 1;if(i===s)continue;let l=/^\d+$/.test(i),u=/^\d+$/.test(s);return l&&u?Number(i)-Number(s):l!==u?l?-1:1:i<s?-1:1}return 0}function jj(e,a,t){let n=Object.keys(e.dependencies??{}).filter(f=>vs.test(f)),r=Object.keys(e.devDependencies??{}).filter(f=>vs.test(f)),o=[...n,...r];if(!o.length)return{target:null,deps:[],devDeps:[],note:"no @microsoft/rayfin-* packages in package.json"};let i=f=>(e.dependencies?.[f]??e.devDependencies?.[f]??"").replace(/^[\^~=v\s]+/,""),s=f=>a[f]??i(f),l=o.map(s),u=[...new Set(l)],c=[...l].sort(Ba).at(-1),d=`all ${o.length} @microsoft/rayfin-* packages`,p=()=>`they were on different versions (${[...u].sort(Ba).join(", ")}), which leaves two copies of a shared Rayfin package and a type error between them`,m=(f,S)=>{let W=k=>k.filter(M=>!f||s(M)!==f).map(M=>`${M}@${f?"^"+f:"latest"}`);return{target:f,deps:W(n),devDeps:W(r),note:S}};if(t){let f=Ba(c,t)>0?c:t;if(u.length===1&&u[0]===f)return{target:f,deps:[],devDeps:[],note:f===t?`${d} on ${f}, npm's latest`:`${d} on ${f}, newer than npm's latest (${t})`};let S=`npm's latest is ${t}, the release \`rayfin init\` installs - from any other version, init leaves two copies of a shared Rayfin package`;return m(f,u.length>1?`${p()}; ${S}`:Ba(u[0],Ss)<0?`they were on ${u[0]}: deploying needs 1.35 or later, and ${S}`:`they were on ${u[0]}, and ${S}`)}let h="couldn't read npm's latest Rayfin release, so they were checked only against the deploy floor";if(u.length===1&&Ba(u[0],Ss)>=0)return{target:u[0],deps:[],devDeps:[],note:`${d} on ${u[0]} (${h})`};let g=Ba(c,Ss)>=0?c:null;return m(g,`${u.length>1?p():`they were on ${u[0]}, and deploying needs 1.35 or later`} (${h})`)}function Lj(e,a){let t=[...new Set(a.map(r=>l5(e,r)).filter(r=>!!r))];if(!t.length)return[];if(t.length>1)return[`Rayfin versions installed: ${t.sort(Ba).join(", ")} - not one version yet`];let n=t[0];return[`Rayfin version installed: ${n}. `+(n===z7?"The notes recipe in get_guide 'fabric-app' was checked against Rayfin's own docs on this version, so here it's the version-matched source: read Rayfin's docs only for what it doesn't cover.":`The notes recipe in get_guide 'fabric-app' was checked on Rayfin ${z7}; where this version differs, Rayfin's own docs (node_modules/@microsoft/rayfin-guide/assets/docs) win.`)]}function l5(e,a){try{return JSON.parse(T7(p4(e,"node_modules",a,"package.json"),"utf-8")).version}catch{return}}function Fj(e){let a=p4(e,"node_modules","@microsoft"),t=[],n=[];try{n=Vy(a)}catch{return t}for(let r of n){let o=[];try{o=Vy(p4(a,r,"node_modules","@microsoft"))}catch{continue}for(let i of o.filter(s=>s.startsWith("rayfin-"))){let s=l5(p4(a,r),`@microsoft/${i}`);s&&s!==l5(e,`@microsoft/${i}`)&&t.push(`@microsoft/${r} > @microsoft/${i}@${s}`)}}return t}function Bj(e,a,t=6e4){return new Promise(n=>{let r=Jy("npm",["view",a,"version"],{cwd:e,shell:process.platform==="win32",windowsHide:!0,stdio:["ignore","pipe","ignore"]}),o="";r.stdout.on("data",s=>{o+=s});let i=setTimeout(()=>{r.kill(),n(null)},t);r.on("error",()=>{clearTimeout(i),n(null)}),r.on("close",s=>{clearTimeout(i);let l=o.trim().split(/\s+/).at(-1)??"";n(s===0&&/^\d+\.\d+\.\d+/.test(l)?l:null)})})}var qy=e=>JSON.parse(T7(p4(e,"package.json"),"utf-8"));function Dj(e,a){let t=[];for(let n of["dependencies","devDependencies"]){let r=e[n]??{},o=a[n]??{};for(let i of new Set([...Object.keys(r),...Object.keys(o)]))r[i]!==o[i]&&t.push(`${i} ${r[i]??"(none)"} -> ${o[i]??"(removed)"}`)}return t}async function tN(e,a){let t;try{t=qy(e)}catch(d){return[`Rayfin packages: package.json unreadable (${d?.message??d})`]}let n=[...Object.keys(t.dependencies??{}),...Object.keys(t.devDependencies??{})].filter(d=>vs.test(d)),r=Object.fromEntries(n.map(d=>[d,l5(e,d)])),o=a.install?await(a.latest??(()=>Bj(e,"@microsoft/rayfin-cli")))():null,i=jj(t,r,o),s=[i.deps.length?`npm install ${i.deps.join(" ")}`:"",i.devDeps.length?`npm install -D ${i.devDeps.join(" ")}`:""].filter(Boolean).join(" && "),l=()=>{let d=Fj(e);return[...d.length?[`Rayfin packages: a nested copy is still installed (${d.join("; ")}); run npm dedupe, then check that npx tsc -b is clean`]:[],...Lj(e,n)]};if(!s)return[`Rayfin packages: ${i.note}`,...l()];if(!a.install)return[`Rayfin packages: ${i.note}. To put them on one version: ${s}`];let u=a.npm??(d=>Cs(e,d));try{i.deps.length&&await u(["install",...i.deps]),i.devDeps.length&&await u(["install","-D",...i.devDeps])}catch(d){return[`Rayfin packages: couldn't align the Rayfin packages (${String(d?.message??d).split(`
|
|
80
80
|
`)[0]}). Run: ${s}`]}let c=[];try{c=Dj(t,qy(e))}catch{}return[`Rayfin packages aligned on ${i.target??"the latest release"} (${i.note}): ${s}`,`package.json ranges changed: ${c.length?c.join("; "):"none"}`,...l()]}var Ws="scripts/validate-visual.spec.mjs",s5="@microsoft/fabric-visuals/headless",ks=e=>e.replace(/[.*+?^${}()|[\]\\/]/g,"\\$&");function Oj(e){let a=new RegExp(`^[ \\t]*import\\s+\\*\\s+as\\s+([A-Za-z_$][\\w$]*)\\s+from\\s+['"]${ks(s5)}['"]`,"m").exec(e)?.[1];if(!a||!new RegExp(`vi\\.spyOn\\(\\s*${ks(a)}\\s*,\\s*['"]renderVisualToSvg['"]`).test(e)||new RegExp(`vi\\.mock\\(\\s*['"]${ks(s5)}['"]`).test(e))return null;let t=-1;for(let o of e.matchAll(/^import(?!\s*\()\b[\s\S]*?['"][^'"\r\n]+['"][ \t]*;?[ \t]*(?=\r?\n|$)/gm))t=o.index+o[0].length;if(t<0)return null;let n=e.includes(`\r
|
|
81
81
|
`)?`\r
|
|
@@ -217,7 +217,7 @@ ${n.join(`
|
|
|
217
217
|
If these rows are a sample of a larger result, pass the whole result (every row at the chart's grain, or a csv_path): eligibility reads the row, region and category counts, so a sample can hide the chart you are looking for.`}function mb(e,a,t,n,r,o){if(!n||t!=="name"&&t!=="namePart")return"";let i=new Set(a),s=e.filter(p=>!i.has(p)),l=P7(s,n,n5,r);if(l.tier!=="namePart"&&l.tier!=="desc"||l.rows.length===0)return"";let u=l.rows.slice(0,6).map(p=>o(p)),c=l.rows.length>6?`, and ${l.rows.length-6} more`:"",d=l.tier==="desc"?"in their descriptions":"mid-word in their names";return`${l.rows.length} more eligible type(s) match "${n}" ${d} and were left out because a name matched first: ${u.join(", ")}${c}. Re-run without name_filter to compare them.`}function Zs(e){let a=e.rank!==void 0?`${e.rank}. `:"\u2022 ",t=e.isPreview?" (preview)":"",n=e.language?` [${e.language}]`:"";return`${a}${e.name}${t}${n}${e.description?` \u2014 ${e.description}`:""}`}function gb(e){let a=e.filter(n=>n.recommended!==!1),t=e.filter(n=>n.recommended===!1);return t.length===0?e.map(Zs):["Fits this data:",...a.map(Zs),"","Can also render it (the chart ontology judges these a weaker fit for this data; any of them can still be requested):",...t.map(Zs)]}var fb=["This is RegiaBI's chart server (npm @bicharts/chart-mcp). When a request asks for RegiaBI charts, it means these tools.","Starting to build an app with charts - a Microsoft Fabric App or any other? Your FIRST step, before you scaffold anything, is get_guide (topic 'fabric-app' for a Fabric App, else 'all'): it carries the scaffold command and the setup steps. Read it before either, and before the first generate_chart call.","For a Microsoft Fabric App over a semantic model, scaffold from Rayfin's dataapp template (npx -y @microsoft/create-rayfin --template dataapp), not blankapp. There, run setup_fabric_app once; query_semantic_model then runs a chart's DAX, saves every row and profiles it in ONE call.","Asked which charts suit the data (good chart types for this dataset, what could be charted)? Answer from these tools, not from general knowledge. Over a semantic model in a Fabric App, suggest_charts does it in ONE call: it queries the model's natural views and returns what fits each, with real counts. For a table you hold, list_eligible_charts.","Five rules for charts that fit on the first try:","1. Pass the chart's WHOLE result at its grain, not a sample: what fits depends on its counts. Use csv_path when long.","2. Give columns the plain names your app renders with (rename Table[Column] first), unchanged at render time.","3. Call list_eligible_charts on that data before choosing, and choose what answers the question as asked. Where a chart has controls drawn inside the chart, build no input beside it.","4. Host the code with @bicharts/chart-host: <BicChartGroup rows columns geo point destination> around <BicChart code d3 geoKind onSelect>, with the binding generate_chart returns; never hand-build __rowIdx__ or __geo* columns. With out_dir, a D3 chart comes with chart.component.tsx beside chart.js, already wired: import it rather than writing one.","5. Use `prompt` for what the chart shows; selection, cross-filtering, sizing and theming are the host's.","The guide is also skills/bic-charts/SKILL.md in the package."].join(`
|
|
218
218
|
`);import{readFileSync as yb}from"node:fs";import{dirname as DL,join as Nb,resolve as OL}from"node:path";import{fileURLToPath as $L}from"node:url";var bb=["fabric-app","all","chart-shapes"];function HL(){return OL(DL($L(import.meta.url)),"..","skills","bic-charts")}function GL(e){let t=e.replace(/^---[\s\S]*?\n---\s*\n/,"").split(/\n(?=## )/),n=new Map,r="";for(let o of t){let i=/^## (\w+)\./.exec(o);i?n.set(i[1],o.trim()):r+=o}return{preamble:r.trim(),byLabel:n}}function Sb(e="fabric-app",a=HL()){if(e==="chart-shapes")return yb(Nb(a,"CHART-SHAPES.md"),"utf-8");let t=yb(Nb(a,"SKILL.md"),"utf-8");if(e==="all")return t.replace(/^---[\s\S]*?\n---\s*\n/,"");let{preamble:n,byLabel:r}=GL(t),o=(r.get("3")??"").split(/\n(?=### Blazor)/)[0].trim();return[n,r.get("0"),r.get("2"),o,r.get("3a"),r.get("4")].filter(i=>!!i&&i.length>0).join(`
|
|
219
219
|
|
|
220
|
-
`)}function J8(e,a){return VN(e,a).dir??q8(e??process.cwd())}var XL="0.6.
|
|
220
|
+
`)}function J8(e,a){return VN(e,a).dir??q8(e??process.cwd())}var XL="0.6.57",Je=new v9({name:"bic-chart",version:XL},{instructions:fb}),k5="2026-10-02T09:25:07Z src:542d95c9de6b (22 files)",Wb="@bicharts/chart-host@0.6.56, @bicharts/shape-core@0.6.56",KL=I.object({columns:I.array(I.object({name:I.string(),dataType:I.enum(["String","Integer","Decimal","DateTime"]).optional().describe("Known type (DAX/semantic-model callers have it); omit to infer from values."),isMeasure:I.boolean().optional().describe("Known measure/dimension role; omit to apply the numeric-non-identifier heuristic. A semantic-model caller should set this."),format:I.string().optional().describe('Format string from the model (e.g. "$#,##0") \u2192 modelFormat.'),description:I.string().optional().describe("Column description from the model \u2192 modelDesc.")})).min(1),rows:I.array(I.union([I.array(I.any()),I.record(I.string(),I.any())])).min(1).describe("Rows as positional arrays aligned to columns, OR objects keyed by column name.")}).describe("A pre-typed {columns, rows} table (DAX query results, dataframe, arrow). Use INSTEAD of csv_path/csv_text."),Vs={csv_path:I.string().optional().describe("Path to a CSV file (header row required)."),csv_text:I.string().optional().describe("Inline CSV text (alternative to csv_path)."),data:KL.optional().describe("A pre-typed {columns, rows} table \u2014 the shape a Fabric DAX query / dataframe already has. Alternative to csv_path/csv_text; when columns carry isMeasure/format/description the shape matches PBI fidelity with no guessing."),measures:I.array(I.string()).optional().describe("Columns to treat as MEASURES (the PBI 'Values' well \u2014 fields the chart aggregates). Numeric non-identifier columns are measures by default."),dimensions:I.array(I.string()).optional().describe("Columns to treat as DIMENSIONS (a PBI category/axis well \u2014 fields to group/break by). Use for numeric codes/years that should NOT be aggregated."),formats:I.record(I.string(),I.string()).optional().describe(`Per-column number/date FORMAT STRING (e.g. {"Revenue":"$#,##0","Margin":"0.0%"}). PBI supplies these from its model; a CSV can't, so provide them to steer number formatting.`),descriptions:I.record(I.string(),I.string()).optional().describe("Per-column human DESCRIPTION \u2014 gives the model semantic context the bare column name lacks."),group_by:I.array(I.string()).optional().describe("Columns that are the PRIMARY series/breakdown (the PBI 'Group by' well); the backend leads the visualization with these."),non_additive:I.array(I.string()).optional().describe("MEASURE columns that must NOT be summed (a ratio/average/rate \u2014 use mean, never stack). Usually auto-detected; this is an authoritative override."),privacy_level:I.enum(["0","10","20","30"]).optional().describe("How much detail to compute/share: 0 names only, 10 +counts, 20 +detailed stats (default), 30 +obfuscated sample rows.")};function V8(e){return{measures:e.measures,dimensions:e.dimensions,formats:e.formats,descriptions:e.descriptions,groupBy:e.group_by,nonAdditive:e.non_additive,privacyLevel:e.privacy_level??"20"}}function w5(e){if(e.data)return yg(e.data.columns,e.data.rows,V8(e));if(e.csv_text)return A8(e.csv_text,V8(e));if(e.csv_path)return A8(E7(q8(e.csv_path),"utf-8"),V8(e));throw new Error("Provide one of: data ({columns, rows}), csv_text, or csv_path.")}Je.registerTool("assess_data_shape",{title:"Assess data shape",description:"Profile a dataset locally (no data leaves the machine): per-column types, cardinality, ranges, measure/dimension roles, temporal/ordinal detection, and cross-column signals (nesting, shared values, association). This is the same measurement engine the BIC Power BI visual uses before generating a chart.",inputSchema:Vs},async e=>{let a=w5(e),t={totalRows:a.totalRows,leafCardinality:a.index.getLeafCardinality(),columns:a.shape};return{content:[{type:"text",text:JSON.stringify(t,null,2)}]}});Je.registerTool("get_guide",{title:"Read the build guide",description:"How to build an app with these charts, from the guide this package ships. Local and free: no network, no credentials. topic 'fabric-app' (the default) is what a Microsoft Fabric App on the Rayfin data app template needs: what to pull, generating, wiring in React, the Fabric App section and the time-savers. 'all' is the whole guide, including Blazor. 'chart-shapes' lists every chart type with the columns, limits and renderers it needs. Read it before the first generate_chart call.",inputSchema:{topic:I.enum(bb).optional().describe("'fabric-app' (default), 'all', or 'chart-shapes'.")}},async e=>{try{return{content:[{type:"text",text:Sb(e.topic??"fabric-app")}]}}catch(a){return{isError:!0,content:[{type:"text",text:`The guide could not be read from this package (${a?.message??a}). It is also published as skills/bic-charts/SKILL.md inside @bicharts/chart-mcp on npm.`}]}}});Je.registerTool("list_eligible_charts",{title:"List eligible chart types",description:"The AUTHORITATIVE list of chart types that can render this dataset \u2014 the server's own eligibility engine, NOT a local guess. Profiles the data locally, then sends that profile to the backend. NO LLM in the loop, but this is a NETWORK call and it is METERED \u2014 see the licensing note below. By default the tool DETECTS the project's language (JS/TS vs Python from the working dir) and returns the charts for THAT language, SCOPED + RANKED by the picker's chart-type\xD7renderer weights (best first), each tagged with its source language and renderer. Pass `language` ('javascript'|'python') to force it, or `renderer` ('D3'/'PLOTLY'/\u2026) to rank one specific renderer, or renderer '' for the full renderer-agnostic eligibility across ALL renderers (also ranked, by chart type alone, with no renderer/language tag). If the language can't be auto-detected and none is given, the tool asks you to specify one. REQUIRES an active license (BIC_LICENSEE + BIC_LICENSE_KEY): eligibility IS the engine, so programmatic access to it is licensed. Free within a generous hourly allowance; beyond it a call may draw usage credits, so avoid calling it in a tight loop. The refusal names what to set.",inputSchema:{...Vs,language:I.enum(["javascript","typescript","python",""]).optional().describe("Project source language \u2192 the server ranks across that language's renderers (javascript/typescript = D3/Vega, python = Plotly/matplotlib). Omit to AUTO-DETECT from the working dir; `renderer` (if given) overrides this."),project_dir:I.string().optional().describe("Directory to auto-detect the project language from (default: the folder setup_fabric_app used, else the working directory or the one project folder directly inside it)."),renderer:I.enum(["D3","PLOTLY","PYMATPLOT","VEGA",""]).optional().describe("Force a specific renderer (overrides `language`): a concrete renderer ranks that renderer's charts; '' = the full renderer-agnostic eligibility (all renderers, ranked by chart type alone). Omit to use `language`/auto-detection."),level_of_detail:I.enum(["High","Medium","Low",""]).optional().describe("How much of the data the user wants to SEE \u2014 ASK THEM, do not infer. 'High' = every observation as its own mark, 'Medium' = every row shown as a distribution, 'Low' = one mark per category. Ranks this list the same way a generation would, so what you see here is what you will get. Omit if they have expressed no preference."),name_filter:I.string().optional().describe("Show only chart types matching this text (the same matcher the Power BI and Excel chart-type lists use). Three tiers, first non-empty one wins outright: the term starting a WORD in the name ('gan' -> Gantt chart, and NOT Organization chart), then mid-word in the name ('eth' -> Choropleth), then the description. A name match therefore SUPPRESSES description matches. Case- and accent-insensitive and, by default, space- and punctuation-insensitive too ('barchart' and 'bar-chart' find Bar chart; see name_filter_match). Minimum two characters, and it never reorders - the picker's ranking is preserved and the ranks stay as issued. Applied after ranking and before `top`."),name_filter_match:I.enum(["loose","exact"]).optional().describe("How name_filter matches a name. 'loose' (the default) ignores accents, case, spaces and punctuation, so 'barchart' finds Bar chart. 'exact' folds accents and case and collapses repeated spaces, and nothing else: a name typed without its space or hyphen matches nothing. The same setting the Power BI and Excel chart-type lists offer."),top:I.number().optional().describe("Show only the top-N ranked results. Omit for all."),width:I.number().optional().describe("Viewport width px (default 800) \u2014 affects small-viewport / facet-budget gates."),height:I.number().optional().describe("Viewport height px (default 600).")}},async e=>{let a=w5(e),t="",n="",r="",o="";if(e.renderer!==void 0)t=e.renderer;else if(e.language)n=e.language;else{let f=N5(J8(e.project_dir,S5));f.language?(n=f.language,r=` (auto-detected language: ${f.language} \u2014 ${f.reason})`):o=`Couldn't tell the project's language (${f.reason}), so this is the list across all renderers; pass language: "javascript" or "python", or project_dir, to narrow it.
|
|
221
221
|
`}Ts("list_eligible_charts",process.env);let i=await Ns({shape:a.shape,totalRows:a.totalRows,leafCardinality:a.index.getLeafCardinality(),geoExtent:a.index.getGeoExtent(),width:e.width,height:e.height,renderer:t,language:n,levelOfDetail:e.level_of_detail||void 0});if(!i.ok)return{isError:!0,content:[{type:"text",text:`Could not list eligible charts: ${i.errorMessage}`}]};let s=i.charts.length>0&&i.charts[0].rank!==void 0,l=n?`${n}`:t||"all renderers",u=i.charts,c=u.length,d=cy(e.name_filter_match),p=P7(u,e.name_filter,n5,d);u=p.rows;let m;if(s?(e.top&&e.top>0&&(u=u.slice(0,e.top)),m=`Top ${u.length} chart type(s) for this data in ${l}, ranked by the picker's weights (authoritative \u2014 the server's eligibility engine; ${o5})${r}:`):m=`${u.length} chart type(s) can render this data \u2014 renderer-agnostic eligibility (authoritative \u2014 the server's eligibility engine; ${o5}):`,m=o+m,p.tier!=="all"){let f=p.tier==="desc"?" (no NAME matched; these matched on description)":p.tier==="namePart"?" (matched mid-word in the name)":"";m=`Filtered to "${e.name_filter}"${f}: ${u.length} of ${c} eligible chart type(s). The other ${c-u.length} are eligible and simply do not match the filter.
|
|
222
222
|
`+m}let h=gb(u);if(u.length===0&&p.tier!=="all"&&c>0){let f=P7(i.refused,e.name_filter,dy,d),S=f.tier==="name"||f.tier==="namePart"?f.rows.filter(k=>k.reason).slice(0,3):[],W=S.length>0?`
|
|
223
223
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bicharts/chart-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.57",
|
|
4
4
|
"description": "MCP (Model Context Protocol) stdio server for BIC AI charts: profile a dataset locally, then generate chart code that has passed the BIC backend's render gates. Works with any MCP-capable client (Claude Code, Claude Desktop, Cursor, Copilot Studio). An account pays to author charts; the code it writes is yours and runs with no licence.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -592,6 +592,12 @@ function CountryMap({ table, onPick }) { // table = the live query resu
|
|
|
592
592
|
minimum.
|
|
593
593
|
- Put `min-h-0` on every flex child between a card and its chart (`min-w-0` in a row). A flex item's default
|
|
594
594
|
`min-height: auto` lets it grow past its card, and the card's `overflow-hidden` slices off the rest.
|
|
595
|
+
- A chart with controls drawn inside it (sliders, steppers, a reset) gets its card's full width. Put a side panel that
|
|
596
|
+
goes with it - saved scenarios, notes, a form - below the chart, not beside it: beside it, the chart's cell drops
|
|
597
|
+
under its minimum and the panel scrolls.
|
|
598
|
+
- When you stack a panel below a chart, don't keep a fixed card height that can't hold both: let the card grow (a
|
|
599
|
+
`min-h-*` in place of its `h-*`), or give the panel below `min-h-0 flex-1 overflow-auto` so it scrolls inside the card.
|
|
600
|
+
Give the chart's cell at least the chart's `minChartHeight` (`h-72` is 288px, under a 300 minimum).
|
|
595
601
|
|
|
596
602
|
**6. Cross-filter across queries by KEY, not by row.** Charts fed by different queries don't share a
|
|
597
603
|
row space, so one group can't span them. Put each query's charts in their own group, turn a click
|