@malloydata/cli 0.0.55-next.2026.6.4.afa381f → 0.0.55-next.2026.6.4.d462a4c

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/LICENSE CHANGED
@@ -1,7 +1,71 @@
1
+ Malloy Project License
2
+ SPDX-License-Identifier: MIT
3
+
4
+ Copyright Contributors to the Malloy project
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+
24
+ ========================================================================
25
+ SOURCE FILE HEADER
26
+ ========================================================================
27
+
28
+ Every source file in this project carries the following header (shown here
29
+ in C/Java/JavaScript comment style; equivalent comment styles are used for
30
+ other languages):
31
+
32
+ /*
33
+ * Copyright Contributors to the Malloy project
34
+ * SPDX-License-Identifier: MIT
35
+ */
36
+
37
+ ========================================================================
38
+ HISTORICAL ATTRIBUTIONS & NOTICES
39
+ ========================================================================
40
+
41
+ Portions of this software were originally contributed by Google LLC under
42
+ the MIT License. For ease of maintenance, individual file headers have been
43
+ updated to the current standard header. The full historical attribution and
44
+ authorship for individual files remains completely preserved and accessible
45
+ via the Git repository history.
46
+
47
+ The original copyright and permission notice for those contributions is
48
+ preserved below:
49
+
50
+ ------------------------------------------------------------------------
1
51
  Copyright 2023 Google LLC
2
52
 
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
53
+ Permission is hereby granted, free of charge, to any person obtaining
54
+ a copy of this software and associated documentation files (the
55
+ "Software"), to deal in the Software without restriction, including
56
+ without limitation the rights to use, copy, modify, merge, publish,
57
+ distribute, sublicense, and/or sell copies of the Software, and to
58
+ permit persons to whom the Software is furnished to do so, subject to
59
+ the following conditions:
4
60
 
5
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
61
+ The above copyright notice and this permission notice shall be
62
+ included in all copies or substantial portions of the Software.
6
63
 
7
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
65
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
66
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
67
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
68
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
69
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
70
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
71
+ ------------------------------------------------------------------------
package/dist/cli.js CHANGED
@@ -4499,7 +4499,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4499
4499
  `+t}async function mq(t){if(t.uri&&t.source||!t.uri&&t.source===void 0)return{ok:!1,problems:[{severity:"error",code:"bad-input",message:"Exactly one of {uri, source} must be provided."}]};let e=t.source!==void 0?gTa(t.source):void 0,r=t.uri?DCi(t.uri):fTa(t.baseUri),{urlReader:n,readSource:i}=hTa(r,e),s=new Spt.Runtime({config:Rc,urlReader:n});try{let o=await s2(()=>s.loadModel(r).getModel());return{ok:!0,loaded:{model:o,rootUrl:r,runtime:s,readSource:i},problems:gq(o.problems)}}catch(o){return o instanceof Spt.MalloyError?{ok:!1,problems:gq(o.problems)}:{ok:!1,problems:[PH(o,r.href)]}}}var kyr,TCi,vCi,Spt,pTa,wpt=Ie(()=>{"use strict";kyr=ut(require("node:url")),TCi=ut(require("node:fs")),vCi=ut(require("node:path")),Spt=ut(Ac());Fv();oy();Pyr();pTa="memory://mcp/"});function kH(t){if(t)return[t.range.start.line,t.range.start.character]}function Eq(t){return t?t.forRoute().map(e=>({route:e.route,text:e.content})):[]}function DRe(t,e){return!!t&&t.url===e}function qyr(t,e){if(!t||!e)return;let r=t.split(`
4500
4500
  `),{start:n,end:i}=e.range;if(n.line<0||n.line>=r.length||i.line<0||i.line>=r.length)return;if(n.line===i.line)return r[n.line].slice(n.character,i.character);let s=[r[n.line].slice(n.character)];for(let o=n.line+1;o<i.line;o++)s.push(r[o]);return s.push(r[i.line].slice(0,i.character)),s.join(`
4501
4501
  `)}function ETa(t){let e=t.structDef.join;return e==="one"||e==="many"||e==="cross"?e:"one"}function NCi(t){let e=t.structDef;return e.type==="array"&&e.elementTypeDef?.type!=="record_element"}function CTa(t){let e=t.structDef;return e.type==="array"&&e.elementTypeDef?.type==="record_element"}function yTa(t){return t.structDef.type==="record"}function ITa(t,e){return NCi(t)?e.filter(r=>r.name!=="value"):e}function bTa(t,e){let n=e.find(i=>i.name===t.name)?.expressionType;return n&&((0,Tpt.expressionIsAggregate)(n)||(0,Tpt.expressionIsAnalytic)(n))?"measure":"dimension"}function _Ta(t,e){if(NCi(t)||CTa(t)||yTa(t))return;let r=t.structDef;if(r.sourceID){let n=r.sourceID.split("@")[0];if(n&&e.has(n))return n}if(r.name&&e.has(r.name))return r.name;if(e.has(t.name))return t.name}function QCi(t,e,r,n){let i=Eq(t.annotations),s=t.location,o=DRe(s,n.rootUri),a={name:t.name,kind:"dimension"};if(i.length>0&&(a.annotations=i),o){let l=kH(s);l&&(a.location=l)}if(t.isExploreField()){let l=t,A=_Ta(l,n.knownSources);if(a.kind="join",a.relationship=ETa(l),A&&(a.source_ref=A),(n.opts.expand==="inline"||!A)&&r<mTa){let f=l.structDef.fields??[],h=[];for(let g of l.allFields)h.push(QCi(g,f,r+1,n));a.fields=ITa(l,h)}return a}if(t.isQueryField()){let l=t;a.kind="view";let A=l.expression||void 0;if(A&&A!==t.name&&(a.expression=A),o&&s){let p=n.readSource(s.url),f=qyr(p,s);f&&(a.body=f)}return a}let c=t;a.kind=bTa(c,e),a.type=c.type;let u=c.expression||void 0;return u&&u!==t.name&&(a.expression=u),a}function xTa(t,e){let r=[],n=[],i=[],s=[],o=t.structDef.fields??[];for(let l of t.allFields){let A=QCi(l,o,0,e);switch(A.kind){case"dimension":r.push(A);break;case"measure":n.push(A);break;case"view":i.push(A);break;case"join":s.push(A);break}}let a=Eq(t.annotations),c={name:t.name,dimensions:r,measures:n,views:i,joins:s};a.length>0&&(c.annotations=a);let u=kH(t.location);return u&&(c.location=u),t.primaryKey&&(c.primaryKey=t.primaryKey),c}function zCi(t){if(t.type==="filter expression")return t.filterType?`filter<${t.filterType}>`:"filter";if(t.type==="array"){let e=t.elementTypeDef;return e?e.type==="record_element"?"record[]":`${zCi(e)}[]`:"array"}return t.type}function BTa(t,e,r){let n={name:e,type:zCi(t.type),hasDefault:t.default!==void 0},i=Eq(t.annotations);i.length>0&&(n.annotations=i);let s=t.location;if(s&&DRe(s,r.rootUri)){let o=kH(s);o&&(n.location=o);let a=qyr(r.readSource(s.url),s);a&&(n.body=a)}return n}function Fyr(t){try{return[...t().givens.keys()]}catch{return[]}}async function MTa(t,e,r,n){let i=t.queries(),s=new Set([...t.explores.map(f=>f.name),...i.named]),o={rootUri:e,knownSources:s,opts:n,readSource:r},a=[];for(let f of t.explores)DRe(f.location,e)&&a.push(xTa(f,o));let c=[];for(let f of i.named){let h=t.getPreparedQueryByName(f),g=h.location;if(!DRe(g,e))continue;let E={name:f},C=Eq(h.annotations);C.length>0&&(E.annotations=C);let y=kH(g);y&&(E.location=y);let b=qyr(r(e),g);b&&(E.body=b);let O=Fyr(()=>h);O.length>0&&(E.givens=O),c.push(E)}let u=[];for(let f=0;f<i.unnamed;f++){let h=t.getPreparedQueryByIndex(f),g={index:f},E=Eq(h.annotations);E.length>0&&(g.annotations=E);let C=kH(h.location);C&&(g.location=C);try{let y=[...h.givens.keys()];y.length>0&&(g.givens=y),n.emitRunSql&&(g.sql=h.preparedResult.sql.trim())}catch(y){n.emitRunSql&&(g.error=y instanceof Error?y.message:String(y))}u.push(g)}let l=[];for(let[f,h]of t.givens)l.push(BTa(h,f,o));let A=Eq(t.annotations),p={rootUri:e,sources:a,queries:c,runs:u};return A.length>0&&(p.annotations=A),l.length>0&&(p.givens=l),p}async function NRe(t,e={}){let r=await mq(t);if(!r.ok||!r.loaded)return{ok:!1,problems:r.problems};let{model:n,rootUrl:i,readSource:s}=r.loaded;try{return{ok:!0,model:await MTa(n,i.href,s,{expand:e.expand??"ref",emitRunSql:e.emitRunSql??!1}),problems:r.problems}}catch(o){return{ok:!1,problems:[...r.problems,PH(o,i.href)]}}}async function LCi(t){let e=await mq(t);if(!e.ok||!e.loaded)return{ok:!1,runs:[],queries:[],problems:e.problems};let{model:r,rootUrl:n}=e.loaded,i=r.queries(),s=Array.from({length:i.unnamed},(a,c)=>{let u=r.getPreparedQueryByIndex(c),l={index:c},A=kH(u.location);A&&(l.location=A);let p=Eq(u.annotations);p.length>0&&(l.annotations=p);let f=Fyr(()=>u);return f.length>0&&(l.givens=f),l}),o=i.named.map(a=>{let c=r.getPreparedQueryByName(a),u=c.location;return{pq:c,queryName:a,loc:u}}).filter(({loc:a})=>DRe(a,n.href)).map(({pq:a,queryName:c,loc:u})=>{let l={name:c},A=kH(u);A&&(l.location=A);let p=Eq(a.annotations);p.length>0&&(l.annotations=p);let f=Fyr(()=>a);return f.length>0&&(l.givens=f),l});return{ok:!0,rootUri:n.href,runs:s,queries:o,problems:e.problems}}var Tpt,mTa,Uyr=Ie(()=>{"use strict";Tpt=ut(Ac());wpt();mTa=4});async function Gyr(t,e={}){let r=await mq(t);if(!r.ok||!r.loaded)return{ok:!1,problems:r.problems.map(u=>PCi(u,t))};let{model:n,rootUrl:i,runtime:s}=r.loaded,o=n.queries(),a=s.loadModel(i),c;if(e.name){if(!o.named.includes(e.name)){let u={queries:o.named,runs:o.unnamed};return{ok:!1,problems:[{severity:"error",code:"selector-not-found",message:`No query named '${e.name}'. Available: ${JSON.stringify(u)}`,uri:i.href}]}}c=a.loadQueryByName(e.name)}else if(typeof e.index=="number"){if(e.index<0||e.index>=o.unnamed)return{ok:!1,problems:[{severity:"error",code:"selector-out-of-range",message:`Index ${e.index} out of range; file has ${o.unnamed} run: statement(s).`,uri:i.href}]};c=a.loadQueryByIndex(e.index)}else{if(o.unnamed===0)return{ok:!1,problems:[{severity:"error",code:"no-run",message:"Source has no run: statement. Specify a named query via `name`, or add a run: to the source.",uri:i.href}]};c=a.loadFinalQuery()}return Wyr(c,e.rowLimit??qv,e.givens,r.problems,{nudge:u=>PCi(u,t),uri:i.href})}async function Wyr(t,e,r,n,i={}){let s=r?{givens:r}:void 0;try{let o=Date.now(),a=(await t.getSQL(s)).trim(),c=Date.now(),u=await s2(()=>t.run({rowLimit:e,...s})),l=Date.now(),A=u.toJSON().queryResult.result;return{ok:!0,sql:a,rowCount:A.length,truncated:A.length===e,rows:A,compileTimeMS:c-o,totalTimeMS:l-o,problems:n}}catch(o){let a=i.nudge??(c=>c);return o instanceof kCi.MalloyError?{ok:!1,problems:[...n,...gq(o.problems).map(a)]}:{ok:!1,problems:[...n,PH(o,i.uri)]}}}function PCi(t,e){if(t.code!=="field-not-found")return t;let r=e.uri?`Call compile_file with uri="${e.uri}" to see what fields, measures, views, and joins exist on this source.`:"Call compile on the same source (or compile_file on any imported file) to see what fields, measures, views, and joins exist.";return{...t,message:`${t.message} \u2014 ${r}`,help_topic:t.help_topic??"fields"}}var kCi,Hyr=Ie(()=>{"use strict";kCi=ut(Ac());wpt();TU();oy()});function GCi(t){return t.split(/\r?\n/).some(e=>qCi.test(e)||UCi.test(e))}function OTa(t){let e=t.split(/\r?\n/);for(let r=0;r<e.length;r++){let n=qCi.exec(e[r]);if(n){let s=n[1],o=[];for(let a=r+1;a<e.length;a++){if(/^[ \t]*\|##[ \t]*$/.test(e[a])){let c=o.map(u=>u.startsWith(s)?u.slice(s.length):u).join(`
4502
- `).trim();return c.length>0?c:void 0}o.push(e[a])}return}let i=UCi.exec(e[r]);if(i){let s=i[1].trim();return s.length>0?s:void 0}}}function ice(t){return{severity:"error",code:"model-not-found",message:`No published model '${t}'. Models are exposed by carrying the \`##|(mcp-description) \u2026 |##\` marker; call list_models to see what is available.`}}function jyr(t,e){if(aQ.default.isAbsolute(e)||e.includes("\0"))return{problem:ice(e)};let r=aQ.default.resolve(t,e),n=aQ.default.relative(t,r);if(n.startsWith("..")||aQ.default.isAbsolute(n))return{problem:ice(e)};if(n.split(aQ.default.sep).some(DOt))return{problem:ice(e)};if(!wde(r)||!vpt.default.existsSync(r))return{problem:ice(e)};let i;try{i=vpt.default.readFileSync(r,"utf8")}catch{return{problem:ice(e)}}return GCi(i)?{abs:r}:{problem:ice(e)}}function WCi(t){let e=[];for(let r of Tde(t)){let n;try{n=vpt.default.readFileSync(r,"utf8")}catch{continue}if(!GCi(n))continue;let i=aQ.default.relative(t,r).split(aQ.default.sep).join("/"),s=OTa(n);e.push(s?{handle:i,description:s}:{handle:i})}return e.sort((r,n)=>r.handle.localeCompare(n.handle)),e}async function HCi(t,e,r={}){let n=jyr(t,e);return"problem"in n?{ok:!1,problems:[n.problem]}:NRe({uri:n.abs},r)}async function jCi(t,e,r){let n=jyr(t,e);if("problem"in n)return{ok:!1,problems:[n.problem]};let i=await mq({uri:n.abs});if(!i.ok||!i.loaded)return{ok:!1,problems:i.problems};let{runtime:s,rootUrl:o}=i.loaded;try{let a=s.loadModel(o).loadRestrictedQuery(r),c=gq(await a.validate());return{ok:!c.some(l=>l.severity==="error"),problems:[...i.problems,...c]}}catch(a){return a instanceof FCi.MalloyError?{ok:!1,problems:[...i.problems,...gq(a.problems)]}:{ok:!1,problems:[...i.problems,PH(a)]}}}async function VCi(t,e,r,n={}){let i=jyr(t,e);if("problem"in i)return{ok:!1,problems:[i.problem]};let s=await mq({uri:i.abs});if(!s.ok||!s.loaded)return{ok:!1,problems:s.problems};let{runtime:o,rootUrl:a}=s.loaded,c=o.loadModel(a).loadRestrictedQuery(r);return Wyr(c,n.rowLimit??qv,n.givens,s.problems)}function $Ci(t){if(!t)throw new Error("Restricted MCP mode (--restricted) requires a project directory: pass -p DIR to scope which models are exposed.");return aQ.default.resolve(t)}var vpt,aQ,FCi,qCi,UCi,KCi=Ie(()=>{"use strict";vpt=ut(require("node:fs")),aQ=ut(require("node:path")),FCi=ut(Ac());wpt();Uyr();Hyr();TU();oy();qCi=/^([ \t]*)##\|\(mcp-description\)[ \t]*$/,UCi=/^[ \t]*##\(mcp-description\)[ \t]?(.*)$/});function QRe(t){let{result:e,errors:r}=(0,YCi.prettify)(t);return{formatted:e,errors:r}}var YCi,Vyr=Ie(()=>{"use strict";YCi=ut(NX())});var JCi=m((mL0,RTa)=>{RTa.exports={name:"@malloydata/cli",version:"0.0.55-next.2026.6.4.afa381f",description:"Malloy CLI",bin:{"malloy-cli":"dist/index.js","malloy-packages":"scripts/malloy-packages.ts"},files:["dist/**","scripts/malloy-packages.ts"],engines:{node:">=20"},pkg:{assets:["node_modules/@duckdb/node-bindings-*/libduckdb.*","node_modules/@duckdb/node-bindings-*/duckdb.dll"]},scripts:{lint:"tsc --noEmit && gts lint",test:"NODE_ENV=test jest --projects jest.config.js --runInBand","test-silent":"NODE_ENV=test JEST_SILENT_REPORTER_SHOW_PATHS=true jest --projects jest.config.js --runInBand --reporters jest-silent-reporter","test-e2e":"npm run package-npm test > /dev/null 2>&1 && NODE_ENV=test jest --projects=jest-e2e.config.js --runInBand","test-silent-e2e":"npm run package-npm test > /dev/null 2>&1 && NODE_ENV=test JEST_SILENT_REPORTER_SHOW_PATHS=true jest --projects=jest-e2e.config.js --runInBand --reporters jest-silent-reporter",build:"ts-node scripts/build","build-action":"esbuild --platform=node --bundle ./.github/actions/permission-check/lib/index.ts --outfile=./.github/actions/permission-check/dist/index.js","build-action-dev":"npm run build-action -- --watch",cli:"npx ts-node ./dist/cli.js",watch:"ts-node scripts/build watch",package:"ts-node scripts/package","package-npm":"ts-node scripts/package-npm","npm-publish":"ts-node scripts/npm-publish",postpack:"npm run build","malloy-update-next":"npm install --no-fund --no-audit --save-exact $(./scripts/malloy-packages.ts next) && ts-node scripts/sync-duckdb.ts && npm install --no-fund --no-audit","malloy-update":"npm install --no-fund --no-audit --save-exact $(./scripts/malloy-packages.ts latest) && ts-node scripts/sync-duckdb.ts && npm install --no-fund --no-audit","malloy-link":"npm --no-fund --no-audit link $(./scripts/malloy-packages.ts)","malloy-unlink":"npm --no-fund --no-save --no-audit unlink $(./scripts/malloy-packages.ts) && npm --no-fund --no-audit install --force"},repository:{type:"git",url:"git+https://github.com/malloydata/malloy-cli.git"},author:"Malloy",license:"MIT",bugs:{url:"https://github.com/malloydata/malloy-cli/issues"},homepage:"https://github.com/malloydata/malloy-cli#readme",builtIntoPackageDependencies:["@malloydata/db-bigquery","@malloydata/db-duckdb","@malloydata/db-mysql","@malloydata/db-postgres","@malloydata/db-snowflake","@malloydata/db-presto","@malloydata/db-trino","@malloydata/malloy","@malloydata/malloy-connections","@malloydata/malloy-sql","chalk","commander","logform","winston"],optionalDependencies:{"@duckdb/node-bindings-darwin-arm64":"1.5.3-r.2","@duckdb/node-bindings-darwin-x64":"1.5.3-r.2","@duckdb/node-bindings-linux-arm64":"1.5.3-r.2","@duckdb/node-bindings-linux-arm64-musl":"1.5.3-r.2","@duckdb/node-bindings-linux-x64":"1.5.3-r.2","@duckdb/node-bindings-linux-x64-musl":"1.5.3-r.2","@duckdb/node-bindings-win32-arm64":"1.5.3-r.2","@duckdb/node-bindings-win32-x64":"1.5.3-r.2"},devDependencies:{"@actions/core":"^1.11.1","@actions/github":"^6.0.0","@commander-js/extra-typings":"^12.1.0","@duckdb/node-api":"1.5.3-r.2","@duckdb/node-bindings":"1.5.3-r.2","@malloydata/db-bigquery":"0.0.405","@malloydata/db-duckdb":"0.0.405","@malloydata/db-postgres":"0.0.405","@malloydata/db-snowflake":"0.0.405","@malloydata/db-trino":"0.0.405","@malloydata/malloy":"0.0.405","@malloydata/malloy-connections":"0.0.405","@malloydata/malloy-sql":"0.0.405","@types/jest":"^29.2.5","@types/node":"^20.14.8","@typescript-eslint/eslint-plugin":"^5.48.2","@typescript-eslint/parser":"^5.48.2","@yao-pkg/pkg":"^6.20.0",ajv:"^8.12.0",axios:"^1.4.0",chalk:"^4.0.0",commander:"^12.1.0","csv-stringify":"^6.4.0",esbuild:"0.25.0",eslint:"^8.32.0","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0",gts:"^3.1.1",jest:"^29.3.1","jest-silent-reporter":"^0.5.0",logform:"^2.5.1","ts-jest":"^29.1.0","ts-node":"^10.9.1",typescript:"^5.9.3",winston:"^3.9.0"},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",zod:"^4.3.6"}}});function vI(t){let e={...t};return{content:[{type:"text",text:JSON.stringify(t,null,2)}],structuredContent:e}}async function Cq(){await Rc.shutdown("idle")}function vTa(t){t.registerTool("prettify",{title:"Pretty-print Malloy source",description:"Reformat a Malloy source string. Returns the formatted source and any parse errors (lexer + parser only \u2014 semantic errors are not checked here; use `compile` for that). When `errors` is non-empty the formatted output is best-effort and may not round-trip; fix the parse errors first. Useful for cleaning up freshly-authored or machine-generated Malloy before saving.",inputSchema:{source:Xyr}},async({source:r})=>vI(QRe(r))),t.registerTool("language_help",{title:"Malloy language reference (by topic)",description:"Look up a section of the Malloy language reference by topic slug or title. Call this before guessing syntax \u2014 especially for pipelines, reduction vs projection, aggregate locality, calculations/window functions, filtered aggregates, pick expressions, time ranges, tags/annotations. Also call this after any compile error whose fix is not obvious from the message \u2014 problems[] entries carry a `help_topic` field when there's a natural match. Call with no topic to list the available topics.",inputSchema:{topic:tf.string().optional().describe("Topic slug or title to look up (case-insensitive; substrings match). Omit to list all available topics.")}},async({topic:r})=>{if(!r)return vI({topics:Lyr()});let n=SCi(r);return vI(n?{slug:n.slug,title:n.title,body:n.body}:{error:`No topic matches '${r}'.`,topics:Lyr()})});let e=MCi(Rpt());for(let r of e)t.registerPrompt(r.name,{title:r.name,description:r.description},()=>({messages:[{role:"user",content:{type:"text",text:r.body}}]})),t.registerResource(r.name,`malloy-skill://${r.name}`,{title:r.name,description:r.description,mimeType:"text/markdown"},async n=>({contents:[{uri:n.href,mimeType:"text/markdown",text:r.body}]}))}function DTa(t){t.registerTool("compile_file",{title:"Inspect a Malloy file (compile)",description:"PREFER THIS OVER READING A .malloy FILE AS TEXT. Compile a .malloy file at the given URI and return the full structured model: sources (with dimensions, measures, views, joins), named queries, top-level run: statements with their SQL, givens (model-level parameters declared with `given:`), and annotations. Each query/run carries the transitive set of given names it references \u2014 the values a caller must supply to execute it. This is the primary way to understand what is in a .malloy file \u2014 what data sources it defines, what can be queried, what the schema looks like \u2014 whether you are about to edit it, answer a question with it, or just explore it. Reading the file as text shows you syntax; compiling it shows you semantics. Joins to named sources render by reference via `source_ref` (look up the referenced source by name in the same response); pass `expand: 'inline'` to get recursive inlined fields instead.",inputSchema:{uri:$yr,expand:Yyr,emit_run_sql:Jyr}},async({uri:e,expand:r,emit_run_sql:n})=>{let i=await NRe({uri:e},{expand:r,emitRunSql:n});return await Cq(),vI(i)}),t.registerTool("compile",{title:"Compile an inline Malloy source string",description:'Compile a Malloy source string (not backed by a file). Same output shape as compile_file. Use this when drafting new Malloy \u2014 the common pattern is `import "file.malloy"` + a new `run: ...`, which you iterate on against the `problems[]` feedback until clean. The compiler is ground truth; do not guess syntax. When in doubt about what fields / measures / views exist in the imported file, call compile_file on it first.',inputSchema:{source:Xyr,base_uri:XCi,expand:Yyr,emit_run_sql:Jyr}},async({source:e,base_uri:r,expand:n,emit_run_sql:i})=>{let s=await NRe({source:e,baseUri:r},{expand:n,emitRunSql:i});return await Cq(),vI(s)}),t.registerTool("run_file",{title:"Execute a run: from a Malloy file",description:"Execute one run: or named query from a .malloy file against the user's configured connections. Selection: `name` wins if provided, else `index` (0-based into run: statements), else the final run:. Returns the generated SQL and rows (default 10000, set row_limit to override). If the run/query references givens (model-level parameters \u2014 see `compile_file` output), supply per-call values via the `givens` map.",inputSchema:{uri:$yr,name:tf.string().optional().describe("Name of a `query:` definition to execute. Wins over `index`."),index:tf.number().int().optional().describe("0-based index into run: statements."),row_limit:Zyr,givens:eIr}},async({uri:e,name:r,index:n,row_limit:i,givens:s})=>{let o=await Gyr({uri:e},{name:r,index:n,rowLimit:i,givens:s});return await Cq(),vI(o)}),t.registerTool("run",{title:"Execute inline Malloy source",description:"Compile an inline Malloy source and execute its final run: statement against the user's configured connections. Returns the generated SQL and rows (default 10000, set row_limit to override). If the source declares givens (model-level parameters), supply per-call values via the `givens` map. Use this after compile is clean to see the answer.",inputSchema:{source:Xyr,base_uri:XCi,row_limit:Zyr,givens:eIr}},async({source:e,base_uri:r,row_limit:n,givens:i})=>{let s=await Gyr({source:e,baseUri:r},{rowLimit:n,givens:i});return await Cq(),vI(s)}),t.registerTool("list_runs",{title:"List runnable queries in a Malloy file",description:"Lightweight discovery: return the runnable run: statements (with optional names and indexes) and named `query:` definitions in a file, without serializing the full model. Each entry also carries the transitive set of given names it references \u2014 the parameters a caller must supply to execute it. Use this when you only need to know what can be executed; if you need the full givens schema (types, defaults, annotations) or any source/field detail, use compile_file instead.",inputSchema:{uri:$yr}},async({uri:e})=>{let r=await LCi({uri:e});return await Cq(),vI(r)})}function NTa(t,e){t.registerTool("list_models",{title:"List published Malloy models",description:"List the models this server exposes. Each entry has a `handle` (pass it as `model` to describe_model / compile / run) and a `description` written by the model author. These are the only models you can query \u2014 you cannot open files by path or import anything else.",inputSchema:{}},async()=>vI({models:WCi(e)})),t.registerTool("describe_model",{title:"Inspect a published model",description:"Return the curated semantic surface of a published model: sources (with dimensions, measures, views, joins), named queries, and givens. Pick `model` from `list_models`. This is how you learn what is queryable before writing a restricted query \u2014 prefer it over guessing field names.",inputSchema:{model:Kyr,expand:Yyr,emit_run_sql:Jyr}},async({model:r,expand:n,emit_run_sql:i})=>{let s=await HCi(e,r,{expand:n,emitRunSql:i});return await Cq(),vI(s)}),t.registerTool("compile",{title:"Validate a restricted query against a model",description:"Compile (validate only, no execution) Malloy `query` text against the published `model`. Returns `problems[]`; iterate until clean, then `run`. Forbidden constructs (import, given: declarations, connection.table/sql, name!type(...), the sql_* functions, ##! flags) are rejected with code `restricted-construct-forbidden`.",inputSchema:{model:Kyr,query:ZCi}},async({model:r,query:n})=>{let i=await jCi(e,r,n);return await Cq(),vI(i)}),t.registerTool("run",{title:"Run a restricted query against a model",description:"Compile `query` against the published `model` in restricted mode and execute it against the operator's configured connections. Returns the generated SQL and rows (default 10000, set row_limit to override). Supply values for any `$NAME` givens the model declares via the `givens` map. Same restrictions as `compile`.",inputSchema:{model:Kyr,query:ZCi,row_limit:Zyr,givens:eIr}},async({model:r,query:n,row_limit:i,givens:s})=>{let o=await VCi(e,r,n,{rowLimit:i,givens:s});return await Cq(),vI(o)})}async function eyi(t={}){let e=t.restricted?$Ci(t.projectDir):void 0,r=new Bpt({name:"malloy-cli",version:STa.version??"development"},{instructions:t.restricted?TTa:wTa});e!==void 0?NTa(r,e):DTa(r),vTa(r);let n=new Opt;await r.connect(n)}var STa,Yyr,Jyr,$yr,Xyr,Zyr,eIr,XCi,Kyr,ZCi,wTa,TTa,tyi=Ie(()=>{"use strict";bCi();BCi();Tyr();Uyr();Hyr();KCi();Pyr();Nyr();Fv();Vyr();STa=JCi(),Yyr=tf.enum(["ref","inline"]).optional().describe("How to render joins in the model output. 'ref' (default) references joined sources by name via `source_ref`. 'inline' recursively inlines the joined source schema (larger output, useful when the client cannot cross-reference)."),Jyr=tf.boolean().optional().describe("If true, compile each run: statement to SQL and include it as `model.runs[].sql`. Default false because run SQL is typically large and is not needed while inspecting the schema. Use run_file to execute a run: and get both SQL and rows."),$yr=tf.string().describe("File URI (file://...) or bare filesystem path. Relative paths resolve against the server's working directory."),Xyr=tf.string().describe("Malloy source code."),Zyr=tf.number().int().optional().describe("Maximum number of rows to return. Defaults to 10000."),eIr=tf.record(tf.string(),tf.unknown()).optional().describe('Per-query given values, keyed by caller-facing surface name (no `$` prefix). Override the runtime\'s defaults for this call only. Use `compile_file` (or `list_runs`) to see which givens a run/query needs \u2014 each entry carries a `givens` array of the names it references. For per-type JS shapes (date as ISO string, naive timestamp as ISO without offset, record as JS object, filter<T> as Malloy filter source string, ...) call `language_help("givens")` \u2014 the "JS shapes for supplied values" subsection is the canonical reference.'),XCi=tf.string().optional().describe("Optional URI used to resolve relative imports in the inline source. Typically the file:// URI of the file the snippet will live next to. If omitted, imports must be absolute."),Kyr=tf.string().describe('Handle of a published model, as returned by `list_models` (a path relative to the server\'s model root, e.g. "sales/orders.malloy"). You cannot name an arbitrary file \u2014 only published models are reachable.'),ZCi=tf.string().describe("Malloy query text to compile against the chosen model. May contain `source:` / `query:` / `run:` statements and reference anything the model already defines, plus `$NAME` givens it declared. May NOT use `import`, declare `given:`, call `connection.table(...)` / `connection.sql(...)`, use the `name!type(...)` raw-SQL form or the `sql_*` functions, or set `##!` compiler flags \u2014 those are rejected with code `restricted-construct-forbidden`.");wTa=`
4502
+ `).trim();return c.length>0?c:void 0}o.push(e[a])}return}let i=UCi.exec(e[r]);if(i){let s=i[1].trim();return s.length>0?s:void 0}}}function ice(t){return{severity:"error",code:"model-not-found",message:`No published model '${t}'. Models are exposed by carrying the \`##|(mcp-description) \u2026 |##\` marker; call list_models to see what is available.`}}function jyr(t,e){if(aQ.default.isAbsolute(e)||e.includes("\0"))return{problem:ice(e)};let r=aQ.default.resolve(t,e),n=aQ.default.relative(t,r);if(n.startsWith("..")||aQ.default.isAbsolute(n))return{problem:ice(e)};if(n.split(aQ.default.sep).some(DOt))return{problem:ice(e)};if(!wde(r)||!vpt.default.existsSync(r))return{problem:ice(e)};let i;try{i=vpt.default.readFileSync(r,"utf8")}catch{return{problem:ice(e)}}return GCi(i)?{abs:r}:{problem:ice(e)}}function WCi(t){let e=[];for(let r of Tde(t)){let n;try{n=vpt.default.readFileSync(r,"utf8")}catch{continue}if(!GCi(n))continue;let i=aQ.default.relative(t,r).split(aQ.default.sep).join("/"),s=OTa(n);e.push(s?{handle:i,description:s}:{handle:i})}return e.sort((r,n)=>r.handle.localeCompare(n.handle)),e}async function HCi(t,e,r={}){let n=jyr(t,e);return"problem"in n?{ok:!1,problems:[n.problem]}:NRe({uri:n.abs},r)}async function jCi(t,e,r){let n=jyr(t,e);if("problem"in n)return{ok:!1,problems:[n.problem]};let i=await mq({uri:n.abs});if(!i.ok||!i.loaded)return{ok:!1,problems:i.problems};let{runtime:s,rootUrl:o}=i.loaded;try{let a=s.loadModel(o).loadRestrictedQuery(r),c=gq(await a.validate());return{ok:!c.some(l=>l.severity==="error"),problems:[...i.problems,...c]}}catch(a){return a instanceof FCi.MalloyError?{ok:!1,problems:[...i.problems,...gq(a.problems)]}:{ok:!1,problems:[...i.problems,PH(a)]}}}async function VCi(t,e,r,n={}){let i=jyr(t,e);if("problem"in i)return{ok:!1,problems:[i.problem]};let s=await mq({uri:i.abs});if(!s.ok||!s.loaded)return{ok:!1,problems:s.problems};let{runtime:o,rootUrl:a}=s.loaded,c=o.loadModel(a).loadRestrictedQuery(r);return Wyr(c,n.rowLimit??qv,n.givens,s.problems)}function $Ci(t){if(!t)throw new Error("Restricted MCP mode (--restricted) requires a project directory: pass -p DIR to scope which models are exposed.");return aQ.default.resolve(t)}var vpt,aQ,FCi,qCi,UCi,KCi=Ie(()=>{"use strict";vpt=ut(require("node:fs")),aQ=ut(require("node:path")),FCi=ut(Ac());wpt();Uyr();Hyr();TU();oy();qCi=/^([ \t]*)##\|\(mcp-description\)[ \t]*$/,UCi=/^[ \t]*##\(mcp-description\)[ \t]?(.*)$/});function QRe(t){let{result:e,errors:r}=(0,YCi.prettify)(t);return{formatted:e,errors:r}}var YCi,Vyr=Ie(()=>{"use strict";YCi=ut(NX())});var JCi=m((mL0,RTa)=>{RTa.exports={name:"@malloydata/cli",version:"0.0.55-next.2026.6.4.d462a4c",description:"Malloy CLI",bin:{"malloy-cli":"dist/index.js","malloy-packages":"scripts/malloy-packages.ts"},files:["dist/**","scripts/malloy-packages.ts"],engines:{node:">=20"},pkg:{assets:["node_modules/@duckdb/node-bindings-*/libduckdb.*","node_modules/@duckdb/node-bindings-*/duckdb.dll"]},scripts:{lint:"tsc --noEmit && gts lint",test:"NODE_ENV=test jest --projects jest.config.js --runInBand","test-silent":"NODE_ENV=test JEST_SILENT_REPORTER_SHOW_PATHS=true jest --projects jest.config.js --runInBand --reporters jest-silent-reporter","test-e2e":"npm run package-npm test > /dev/null 2>&1 && NODE_ENV=test jest --projects=jest-e2e.config.js --runInBand","test-silent-e2e":"npm run package-npm test > /dev/null 2>&1 && NODE_ENV=test JEST_SILENT_REPORTER_SHOW_PATHS=true jest --projects=jest-e2e.config.js --runInBand --reporters jest-silent-reporter",build:"ts-node scripts/build","build-action":"esbuild --platform=node --bundle ./.github/actions/permission-check/lib/index.ts --outfile=./.github/actions/permission-check/dist/index.js","build-action-dev":"npm run build-action -- --watch",cli:"npx ts-node ./dist/cli.js",watch:"ts-node scripts/build watch",package:"ts-node scripts/package","package-npm":"ts-node scripts/package-npm","npm-publish":"ts-node scripts/npm-publish",postpack:"npm run build","malloy-update-next":"npm install --no-fund --no-audit --save-exact $(./scripts/malloy-packages.ts next) && ts-node scripts/sync-duckdb.ts && npm install --no-fund --no-audit","malloy-update":"npm install --no-fund --no-audit --save-exact $(./scripts/malloy-packages.ts latest) && ts-node scripts/sync-duckdb.ts && npm install --no-fund --no-audit","malloy-link":"npm --no-fund --no-audit link $(./scripts/malloy-packages.ts)","malloy-unlink":"npm --no-fund --no-save --no-audit unlink $(./scripts/malloy-packages.ts) && npm --no-fund --no-audit install --force"},repository:{type:"git",url:"git+https://github.com/malloydata/malloy-cli.git"},author:"Malloy",license:"MIT",bugs:{url:"https://github.com/malloydata/malloy-cli/issues"},homepage:"https://github.com/malloydata/malloy-cli#readme",builtIntoPackageDependencies:["@malloydata/db-bigquery","@malloydata/db-duckdb","@malloydata/db-mysql","@malloydata/db-postgres","@malloydata/db-snowflake","@malloydata/db-presto","@malloydata/db-trino","@malloydata/malloy","@malloydata/malloy-connections","@malloydata/malloy-sql","chalk","commander","logform","winston"],optionalDependencies:{"@duckdb/node-bindings-darwin-arm64":"1.5.3-r.2","@duckdb/node-bindings-darwin-x64":"1.5.3-r.2","@duckdb/node-bindings-linux-arm64":"1.5.3-r.2","@duckdb/node-bindings-linux-arm64-musl":"1.5.3-r.2","@duckdb/node-bindings-linux-x64":"1.5.3-r.2","@duckdb/node-bindings-linux-x64-musl":"1.5.3-r.2","@duckdb/node-bindings-win32-arm64":"1.5.3-r.2","@duckdb/node-bindings-win32-x64":"1.5.3-r.2"},devDependencies:{"@actions/core":"^1.11.1","@actions/github":"^6.0.0","@commander-js/extra-typings":"^12.1.0","@duckdb/node-api":"1.5.3-r.2","@duckdb/node-bindings":"1.5.3-r.2","@malloydata/db-bigquery":"0.0.405","@malloydata/db-duckdb":"0.0.405","@malloydata/db-postgres":"0.0.405","@malloydata/db-snowflake":"0.0.405","@malloydata/db-trino":"0.0.405","@malloydata/malloy":"0.0.405","@malloydata/malloy-connections":"0.0.405","@malloydata/malloy-sql":"0.0.405","@types/jest":"^29.2.5","@types/node":"^20.14.8","@typescript-eslint/eslint-plugin":"^5.48.2","@typescript-eslint/parser":"^5.48.2","@yao-pkg/pkg":"^6.20.0",ajv:"^8.12.0",axios:"^1.4.0",chalk:"^4.0.0",commander:"^12.1.0","csv-stringify":"^6.4.0",esbuild:"0.25.0",eslint:"^8.32.0","eslint-config-prettier":"^8.3.0","eslint-plugin-prettier":"^3.4.0",gts:"^3.1.1",jest:"^29.3.1","jest-silent-reporter":"^0.5.0",logform:"^2.5.1","ts-jest":"^29.1.0","ts-node":"^10.9.1",typescript:"^5.9.3",winston:"^3.9.0"},dependencies:{"@modelcontextprotocol/sdk":"^1.29.0",zod:"^4.3.6"}}});function vI(t){let e={...t};return{content:[{type:"text",text:JSON.stringify(t,null,2)}],structuredContent:e}}async function Cq(){await Rc.shutdown("idle")}function vTa(t){t.registerTool("prettify",{title:"Pretty-print Malloy source",description:"Reformat a Malloy source string. Returns the formatted source and any parse errors (lexer + parser only \u2014 semantic errors are not checked here; use `compile` for that). When `errors` is non-empty the formatted output is best-effort and may not round-trip; fix the parse errors first. Useful for cleaning up freshly-authored or machine-generated Malloy before saving.",inputSchema:{source:Xyr}},async({source:r})=>vI(QRe(r))),t.registerTool("language_help",{title:"Malloy language reference (by topic)",description:"Look up a section of the Malloy language reference by topic slug or title. Call this before guessing syntax \u2014 especially for pipelines, reduction vs projection, aggregate locality, calculations/window functions, filtered aggregates, pick expressions, time ranges, tags/annotations. Also call this after any compile error whose fix is not obvious from the message \u2014 problems[] entries carry a `help_topic` field when there's a natural match. Call with no topic to list the available topics.",inputSchema:{topic:tf.string().optional().describe("Topic slug or title to look up (case-insensitive; substrings match). Omit to list all available topics.")}},async({topic:r})=>{if(!r)return vI({topics:Lyr()});let n=SCi(r);return vI(n?{slug:n.slug,title:n.title,body:n.body}:{error:`No topic matches '${r}'.`,topics:Lyr()})});let e=MCi(Rpt());for(let r of e)t.registerPrompt(r.name,{title:r.name,description:r.description},()=>({messages:[{role:"user",content:{type:"text",text:r.body}}]})),t.registerResource(r.name,`malloy-skill://${r.name}`,{title:r.name,description:r.description,mimeType:"text/markdown"},async n=>({contents:[{uri:n.href,mimeType:"text/markdown",text:r.body}]}))}function DTa(t){t.registerTool("compile_file",{title:"Inspect a Malloy file (compile)",description:"PREFER THIS OVER READING A .malloy FILE AS TEXT. Compile a .malloy file at the given URI and return the full structured model: sources (with dimensions, measures, views, joins), named queries, top-level run: statements with their SQL, givens (model-level parameters declared with `given:`), and annotations. Each query/run carries the transitive set of given names it references \u2014 the values a caller must supply to execute it. This is the primary way to understand what is in a .malloy file \u2014 what data sources it defines, what can be queried, what the schema looks like \u2014 whether you are about to edit it, answer a question with it, or just explore it. Reading the file as text shows you syntax; compiling it shows you semantics. Joins to named sources render by reference via `source_ref` (look up the referenced source by name in the same response); pass `expand: 'inline'` to get recursive inlined fields instead.",inputSchema:{uri:$yr,expand:Yyr,emit_run_sql:Jyr}},async({uri:e,expand:r,emit_run_sql:n})=>{let i=await NRe({uri:e},{expand:r,emitRunSql:n});return await Cq(),vI(i)}),t.registerTool("compile",{title:"Compile an inline Malloy source string",description:'Compile a Malloy source string (not backed by a file). Same output shape as compile_file. Use this when drafting new Malloy \u2014 the common pattern is `import "file.malloy"` + a new `run: ...`, which you iterate on against the `problems[]` feedback until clean. The compiler is ground truth; do not guess syntax. When in doubt about what fields / measures / views exist in the imported file, call compile_file on it first.',inputSchema:{source:Xyr,base_uri:XCi,expand:Yyr,emit_run_sql:Jyr}},async({source:e,base_uri:r,expand:n,emit_run_sql:i})=>{let s=await NRe({source:e,baseUri:r},{expand:n,emitRunSql:i});return await Cq(),vI(s)}),t.registerTool("run_file",{title:"Execute a run: from a Malloy file",description:"Execute one run: or named query from a .malloy file against the user's configured connections. Selection: `name` wins if provided, else `index` (0-based into run: statements), else the final run:. Returns the generated SQL and rows (default 10000, set row_limit to override). If the run/query references givens (model-level parameters \u2014 see `compile_file` output), supply per-call values via the `givens` map.",inputSchema:{uri:$yr,name:tf.string().optional().describe("Name of a `query:` definition to execute. Wins over `index`."),index:tf.number().int().optional().describe("0-based index into run: statements."),row_limit:Zyr,givens:eIr}},async({uri:e,name:r,index:n,row_limit:i,givens:s})=>{let o=await Gyr({uri:e},{name:r,index:n,rowLimit:i,givens:s});return await Cq(),vI(o)}),t.registerTool("run",{title:"Execute inline Malloy source",description:"Compile an inline Malloy source and execute its final run: statement against the user's configured connections. Returns the generated SQL and rows (default 10000, set row_limit to override). If the source declares givens (model-level parameters), supply per-call values via the `givens` map. Use this after compile is clean to see the answer.",inputSchema:{source:Xyr,base_uri:XCi,row_limit:Zyr,givens:eIr}},async({source:e,base_uri:r,row_limit:n,givens:i})=>{let s=await Gyr({source:e,baseUri:r},{rowLimit:n,givens:i});return await Cq(),vI(s)}),t.registerTool("list_runs",{title:"List runnable queries in a Malloy file",description:"Lightweight discovery: return the runnable run: statements (with optional names and indexes) and named `query:` definitions in a file, without serializing the full model. Each entry also carries the transitive set of given names it references \u2014 the parameters a caller must supply to execute it. Use this when you only need to know what can be executed; if you need the full givens schema (types, defaults, annotations) or any source/field detail, use compile_file instead.",inputSchema:{uri:$yr}},async({uri:e})=>{let r=await LCi({uri:e});return await Cq(),vI(r)})}function NTa(t,e){t.registerTool("list_models",{title:"List published Malloy models",description:"List the models this server exposes. Each entry has a `handle` (pass it as `model` to describe_model / compile / run) and a `description` written by the model author. These are the only models you can query \u2014 you cannot open files by path or import anything else.",inputSchema:{}},async()=>vI({models:WCi(e)})),t.registerTool("describe_model",{title:"Inspect a published model",description:"Return the curated semantic surface of a published model: sources (with dimensions, measures, views, joins), named queries, and givens. Pick `model` from `list_models`. This is how you learn what is queryable before writing a restricted query \u2014 prefer it over guessing field names.",inputSchema:{model:Kyr,expand:Yyr,emit_run_sql:Jyr}},async({model:r,expand:n,emit_run_sql:i})=>{let s=await HCi(e,r,{expand:n,emitRunSql:i});return await Cq(),vI(s)}),t.registerTool("compile",{title:"Validate a restricted query against a model",description:"Compile (validate only, no execution) Malloy `query` text against the published `model`. Returns `problems[]`; iterate until clean, then `run`. Forbidden constructs (import, given: declarations, connection.table/sql, name!type(...), the sql_* functions, ##! flags) are rejected with code `restricted-construct-forbidden`.",inputSchema:{model:Kyr,query:ZCi}},async({model:r,query:n})=>{let i=await jCi(e,r,n);return await Cq(),vI(i)}),t.registerTool("run",{title:"Run a restricted query against a model",description:"Compile `query` against the published `model` in restricted mode and execute it against the operator's configured connections. Returns the generated SQL and rows (default 10000, set row_limit to override). Supply values for any `$NAME` givens the model declares via the `givens` map. Same restrictions as `compile`.",inputSchema:{model:Kyr,query:ZCi,row_limit:Zyr,givens:eIr}},async({model:r,query:n,row_limit:i,givens:s})=>{let o=await VCi(e,r,n,{rowLimit:i,givens:s});return await Cq(),vI(o)})}async function eyi(t={}){let e=t.restricted?$Ci(t.projectDir):void 0,r=new Bpt({name:"malloy-cli",version:STa.version??"development"},{instructions:t.restricted?TTa:wTa});e!==void 0?NTa(r,e):DTa(r),vTa(r);let n=new Opt;await r.connect(n)}var STa,Yyr,Jyr,$yr,Xyr,Zyr,eIr,XCi,Kyr,ZCi,wTa,TTa,tyi=Ie(()=>{"use strict";bCi();BCi();Tyr();Uyr();Hyr();KCi();Pyr();Nyr();Fv();Vyr();STa=JCi(),Yyr=tf.enum(["ref","inline"]).optional().describe("How to render joins in the model output. 'ref' (default) references joined sources by name via `source_ref`. 'inline' recursively inlines the joined source schema (larger output, useful when the client cannot cross-reference)."),Jyr=tf.boolean().optional().describe("If true, compile each run: statement to SQL and include it as `model.runs[].sql`. Default false because run SQL is typically large and is not needed while inspecting the schema. Use run_file to execute a run: and get both SQL and rows."),$yr=tf.string().describe("File URI (file://...) or bare filesystem path. Relative paths resolve against the server's working directory."),Xyr=tf.string().describe("Malloy source code."),Zyr=tf.number().int().optional().describe("Maximum number of rows to return. Defaults to 10000."),eIr=tf.record(tf.string(),tf.unknown()).optional().describe('Per-query given values, keyed by caller-facing surface name (no `$` prefix). Override the runtime\'s defaults for this call only. Use `compile_file` (or `list_runs`) to see which givens a run/query needs \u2014 each entry carries a `givens` array of the names it references. For per-type JS shapes (date as ISO string, naive timestamp as ISO without offset, record as JS object, filter<T> as Malloy filter source string, ...) call `language_help("givens")` \u2014 the "JS shapes for supplied values" subsection is the canonical reference.'),XCi=tf.string().optional().describe("Optional URI used to resolve relative imports in the inline source. Typically the file:// URI of the file the snippet will live next to. If omitted, imports must be absolute."),Kyr=tf.string().describe('Handle of a published model, as returned by `list_models` (a path relative to the server\'s model root, e.g. "sales/orders.malloy"). You cannot name an arbitrary file \u2014 only published models are reachable.'),ZCi=tf.string().describe("Malloy query text to compile against the chosen model. May contain `source:` / `query:` / `run:` statements and reference anything the model already defines, plus `$NAME` givens it declared. May NOT use `import`, declare `given:`, call `connection.table(...)` / `connection.sql(...)`, use the `name!type(...)` raw-SQL form or the `sql_*` functions, or set `##!` compiler flags \u2014 those are rejected with code `restricted-construct-forbidden`.");wTa=`
4503
4503
  This server lets an agent inspect, author, and execute Malloy semantic models.
4504
4504
 
4505
4505
  Malloy (.malloy) files are NOT plain text you should read for comprehension.
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- process.MALLOY_CLI_VERSION="0.0.55-next.2026.6.4.afa381f";
2
+ process.MALLOY_CLI_VERSION="0.0.55-next.2026.6.4.d462a4c";
3
3
  require('./cli.js')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/cli",
3
- "version": "0.0.55-next.2026.6.4.afa381f",
3
+ "version": "0.0.55-next.2026.6.4.d462a4c",
4
4
  "description": "Malloy CLI",
5
5
  "bin": {
6
6
  "malloy-cli": "dist/index.js",