├── docs ├── web │ ├── .gitignore │ ├── src │ │ ├── vite-env.d.ts │ │ ├── components │ │ │ ├── ui │ │ │ │ ├── use-toast.ts │ │ │ │ ├── aspect-ratio.tsx │ │ │ │ ├── skeleton.tsx │ │ │ │ ├── collapsible.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── toaster.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ ├── progress.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── sonner.tsx │ │ │ │ ├── slider.tsx │ │ │ │ ├── checkbox.tsx │ │ │ │ ├── badge.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ ├── hover-card.tsx │ │ │ │ ├── popover.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── toggle.tsx │ │ │ │ ├── radio-group.tsx │ │ │ │ ├── alert.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ ├── resizable.tsx │ │ │ │ ├── toggle-group.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── tabs.tsx │ │ │ │ ├── accordion.tsx │ │ │ │ ├── input-otp.tsx │ │ │ │ ├── calendar.tsx │ │ │ │ ├── table.tsx │ │ │ │ ├── pagination.tsx │ │ │ │ └── breadcrumb.tsx │ │ │ ├── YamlContent.tsx │ │ │ ├── ThemeToggle.tsx │ │ │ ├── CollapsibleSetup.tsx │ │ │ ├── SearchButton.tsx │ │ │ ├── StandardOutput.tsx │ │ │ ├── Note.tsx │ │ │ ├── AltairChart.tsx │ │ │ ├── Installation.tsx │ │ │ ├── Features.tsx │ │ │ └── TableOfContents.tsx │ │ ├── pages │ │ │ ├── MCP.tsx │ │ │ ├── Charting.tsx │ │ │ ├── Indexing.tsx │ │ │ ├── Profile.tsx │ │ │ ├── Bucketing.tsx │ │ │ ├── Filtering.tsx │ │ │ ├── Windowing.tsx │ │ │ ├── ComposeModels.tsx │ │ │ ├── Sessionized.tsx │ │ │ ├── YAMLConfig.tsx │ │ │ ├── QueryMethods.tsx │ │ │ ├── QueryAgentChat.tsx │ │ │ ├── QueryAgentMCP.tsx │ │ │ ├── SemanticTable.tsx │ │ │ ├── NestedSubtotals.tsx │ │ │ ├── PercentageTotal.tsx │ │ │ ├── QueryAgentOverview.tsx │ │ │ ├── QueryAgentSkill.tsx │ │ │ ├── QueryAgentTool.tsx │ │ │ ├── About.tsx │ │ │ ├── KeyFeatures.tsx │ │ │ ├── Quickstart.tsx │ │ │ ├── Installation.tsx │ │ │ ├── NotFound.tsx │ │ │ ├── NameConflicts.tsx │ │ │ ├── MultiModelQuery.tsx │ │ │ ├── SemanticTableDefinition.tsx │ │ │ ├── Measures.tsx │ │ │ └── Dimensions.tsx │ │ ├── main.tsx │ │ ├── lib │ │ │ └── utils.ts │ │ └── hooks │ │ │ └── use-mobile.tsx │ ├── bun.lockb │ ├── public │ │ ├── favicon.ico │ │ ├── bsl-chat-demo.png │ │ ├── robots.txt │ │ ├── pages.json │ │ ├── favicon.svg │ │ ├── logo.svg │ │ ├── bsl-data │ │ │ ├── query-agent.json │ │ │ ├── query-agent-skill.json │ │ │ ├── filtering.json │ │ │ ├── query-agent-chat.json │ │ │ └── builder-agent.json │ │ ├── 404.html │ │ ├── og-image.svg │ │ └── placeholder.svg │ ├── postcss.config.js │ ├── tsconfig.json │ ├── components.json │ ├── vite.config.ts │ ├── tsconfig.node.json │ ├── tsconfig.app.json │ ├── eslint.config.js │ └── index.html └── md │ ├── prompts │ └── query │ │ ├── mcp │ │ ├── tool-query-param-limit.md │ │ ├── tool-get-model-desc.md │ │ ├── tool-get-time-range-desc.md │ │ ├── tool-list-models-desc.md │ │ ├── tool-query-param-dimensions.md │ │ ├── tool-query-param-order_by.md │ │ ├── tool-query-param-measures.md │ │ ├── tool-query-desc.md │ │ ├── tool-query-param-chart_backend.md │ │ ├── tool-query-param-records_limit.md │ │ ├── tool-query-param-get_chart.md │ │ ├── tool-query-param-get_records.md │ │ ├── tool-query-param-chart_format.md │ │ ├── tool-query-param-time_range.md │ │ ├── tool-list-models.md │ │ ├── tool-query-param-time_grain.md │ │ ├── tool-get-model.md │ │ ├── tool-get-time-range.md │ │ ├── tool-query-param-chart_spec.md │ │ └── system.md │ │ └── langchain │ │ ├── tool-list-models.md │ │ ├── param-query-model-chart_backend.md │ │ ├── param-query-model-chart_spec.md │ │ ├── param-query-model-get_chart.md │ │ ├── param-query-model-get_records.md │ │ ├── param-query-model-chart_format.md │ │ ├── param-query-model-query.md │ │ ├── param-query-model-records_limit.md │ │ ├── param-query-model-records_displayed_limit.md │ │ ├── param-query-model-limit.md │ │ └── input-query-model.md │ └── doc │ ├── yaml_example.yaml │ ├── query-agent.md │ ├── mcp_example.yaml │ ├── query-agent-skill.md │ ├── example.md │ ├── query-agent-chat.md │ └── builder-agent.md ├── .envrc.user ├── .gitignore.template ├── src └── boring_semantic_layer │ ├── agents │ ├── tests │ │ └── __init__.py │ ├── eval │ │ ├── __init__.py │ │ └── questions.yaml │ ├── backends │ │ └── __init__.py │ └── utils │ │ └── prompts.py │ ├── chart │ ├── tests │ │ └── __init__.py │ └── md_parser │ │ └── __init__.py │ ├── tests │ ├── integration │ │ ├── __init__.py │ │ ├── malloy_data │ │ │ ├── moving_avg.malloy │ │ │ ├── comparing_timeframe.py │ │ │ ├── moving_avg.py │ │ │ ├── percent_of_total.malloy │ │ │ ├── cohorts.malloy │ │ │ └── comparing_timeframe.malloy │ │ └── test_malloy_integration.py │ ├── fixtures │ │ └── __init__.py │ ├── test_percent_of_total.py │ └── test_cross_team.py │ ├── config.py │ └── __init__.py ├── .envrc ├── examples ├── __init__.py ├── order_items.yml ├── profiles.yml ├── example_openai_tool.py ├── percent_of_total.py ├── example_mcp.py ├── bucketing_with_other.py ├── graph_example.py ├── nested_subtotals.py ├── basic_flights.py ├── ga_sessions.yaml ├── joins.py ├── basic_flights_xorq.py ├── window_functions.py └── nested_data.py ├── LICENSE ├── .pre-commit-config.yaml ├── README.md ├── .gitignore ├── flake.lock └── pyproject.toml /docs/web/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules** -------------------------------------------------------------------------------- /.envrc.user: -------------------------------------------------------------------------------- 1 | use flake .#editable 2 | -------------------------------------------------------------------------------- /.gitignore.template: -------------------------------------------------------------------------------- 1 | .gitignore 2 | *.direnv 3 | __pycache__ 4 | -------------------------------------------------------------------------------- /docs/web/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-limit.md: -------------------------------------------------------------------------------- 1 | Maximum number of rows to return -------------------------------------------------------------------------------- /src/boring_semantic_layer/agents/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for BSL agents.""" 2 | -------------------------------------------------------------------------------- /src/boring_semantic_layer/chart/tests/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for chart backends.""" 2 | -------------------------------------------------------------------------------- /src/boring_semantic_layer/agents/eval/__init__.py: -------------------------------------------------------------------------------- 1 | """Evaluation suite for BSL agents.""" 2 | -------------------------------------------------------------------------------- /docs/web/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boringdata/boring-semantic-layer/HEAD/docs/web/bun.lockb -------------------------------------------------------------------------------- /src/boring_semantic_layer/tests/integration/__init__.py: -------------------------------------------------------------------------------- 1 | """Integration tests for Malloy-BSL equivalence.""" 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-get-model-desc.md: -------------------------------------------------------------------------------- 1 | Fetch dimensions and measures for a semantic model before querying it. -------------------------------------------------------------------------------- /docs/md/prompts/query/langchain/tool-list-models.md: -------------------------------------------------------------------------------- 1 | List all semantic models, including their dimensions and measures. 2 | -------------------------------------------------------------------------------- /docs/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boringdata/boring-semantic-layer/HEAD/docs/web/public/favicon.ico -------------------------------------------------------------------------------- /docs/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /docs/web/src/components/ui/use-toast.ts: -------------------------------------------------------------------------------- 1 | import { useToast, toast } from "@/hooks/use-toast"; 2 | 3 | export { useToast, toast }; 4 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-get-time-range-desc.md: -------------------------------------------------------------------------------- 1 | Return the earliest and latest timestamps available for a model's time dimension. -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-list-models-desc.md: -------------------------------------------------------------------------------- 1 | List all available semantic model names. Call this first to understand what's queryable. -------------------------------------------------------------------------------- /docs/web/public/bsl-chat-demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boringdata/boring-semantic-layer/HEAD/docs/web/public/bsl-chat-demo.png -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-dimensions.md: -------------------------------------------------------------------------------- 1 | List of dimension names to group by (e.g., ['flights.origin', 'flights.destination']) -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-order_by.md: -------------------------------------------------------------------------------- 1 | List of [field, direction] pairs for sorting (e.g., [['flights.flight_count', 'desc']]) -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-measures.md: -------------------------------------------------------------------------------- 1 | List of measure names to aggregate (e.g., ['flights.flight_count', 'flights.avg_distance']) -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-desc.md: -------------------------------------------------------------------------------- 1 | Execute semantic model queries with dimensions, measures, filters, ordering, time grain, and chart spec options. -------------------------------------------------------------------------------- /docs/web/src/pages/MCP.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function MCP() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Charting.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Charting() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Indexing.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Indexing() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Profile.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Profile() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Bucketing.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Bucketing() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Filtering.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Filtering() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Windowing.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Windowing() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/ComposeModels.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function ComposeModels() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/Sessionized.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function Sessionized() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/YAMLConfig.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function YAMLConfig() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from "react-dom/client"; 2 | import App from "./App.tsx"; 3 | import "./index.css"; 4 | 5 | createRoot(document.getElementById("root")!).render(); 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/QueryMethods.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function QueryMethods() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-chart_backend.md: -------------------------------------------------------------------------------- 1 | Override the default chart backend for this call (`altair`, `plotly`, or `plotext`). Leave `null` to use the server's default backend (altair). 2 | -------------------------------------------------------------------------------- /docs/web/src/components/ui/aspect-ratio.tsx: -------------------------------------------------------------------------------- 1 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; 2 | 3 | const AspectRatio = AspectRatioPrimitive.Root; 4 | 5 | export { AspectRatio }; 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/QueryAgentChat.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function QueryAgentChat() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/QueryAgentMCP.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function QueryAgentMCP() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/SemanticTable.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function SemanticTable() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/NestedSubtotals.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function NestedSubtotals() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/PercentageTotal.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function PercentageTotal() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/QueryAgentOverview.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function QueryAgentOverview() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/QueryAgentSkill.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function QueryAgentSkill() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/QueryAgentTool.tsx: -------------------------------------------------------------------------------- 1 | import BSLMarkdownPage from './BSLMarkdownPage' 2 | 3 | export default function QueryAgentTool() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /docs/web/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | -------------------------------------------------------------------------------- /docs/md/prompts/query/langchain/param-query-model-chart_backend.md: -------------------------------------------------------------------------------- 1 | Override the default chart backend for this call (`plotext`, `altair`, or `plotly`). Leave `null` to use the backend configured when the agent was created. 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/langchain/param-query-model-chart_spec.md: -------------------------------------------------------------------------------- 1 | Optional chart customization dict. Common: `{"chart_type": "bar"}` or `"line"`, `"scatter"`. 2 | 3 | For detailed options → `get_documentation("charting")` 4 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-records_limit.md: -------------------------------------------------------------------------------- 1 | Max records returned to LLM context (default: None = all). Use to limit token usage for large result sets. For example, set to 50 to cap the data sent to your context window. 2 | -------------------------------------------------------------------------------- /docs/web/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: Googlebot 2 | Allow: / 3 | 4 | User-agent: Bingbot 5 | Allow: / 6 | 7 | User-agent: Twitterbot 8 | Allow: / 9 | 10 | User-agent: facebookexternalhit 11 | Allow: / 12 | 13 | User-agent: * 14 | Allow: / 15 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-get_chart.md: -------------------------------------------------------------------------------- 1 | Generate chart visualization (default: true). Set `false` to skip chart generation and return only data records. Charts are automatically hidden for single-row results (e.g., a single aggregate value). 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-get_records.md: -------------------------------------------------------------------------------- 1 | Return data records to LLM (default: true). Set `false` for final display-only queries where you don't need to process the data further. This saves tokens when the chart/table display is sufficient. 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/langchain/param-query-model-get_chart.md: -------------------------------------------------------------------------------- 1 | Generate chart visualization (default: true). Set `false` to skip chart generation and return only data records. Charts are automatically hidden for single-row results (e.g., a single aggregate value). 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/langchain/param-query-model-get_records.md: -------------------------------------------------------------------------------- 1 | Return data records to LLM (default: true). Set `false` for final display-only queries where you don't need to process the data further. This saves tokens when the chart/table display is sufficient. 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/langchain/param-query-model-chart_format.md: -------------------------------------------------------------------------------- 1 | Override chart output format: `json` (serializable spec), `static` (rendered to terminal), or `string` (ANSI string). Leave `null` to auto-select based on backend (json for altair/plotly, static for plotext). 2 | -------------------------------------------------------------------------------- /docs/md/prompts/query/mcp/tool-query-param-chart_format.md: -------------------------------------------------------------------------------- 1 | Override chart output format: `json` (serializable spec), `static` (rendered image), or `string` (ANSI string for terminal). Leave `null` to auto-select based on backend (json for altair/plotly, static for plotext). 2 | -------------------------------------------------------------------------------- /src/boring_semantic_layer/tests/fixtures/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Test fixtures for Malloy correctness testing. 3 | 4 | This package provides shared fixtures for: 5 | - Dataset loading from malloy-samples 6 | - Database connection management 7 | - Test data validation 8 | """ 9 | -------------------------------------------------------------------------------- /docs/web/src/components/ui/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | function Skeleton({ className, ...props }: React.HTMLAttributes) { 4 | return
; 5 | } 6 | 7 | export { Skeleton }; 8 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | if ! has nix_direnv_version || ! nix_direnv_version 2.4.0; then 2 | source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.4.0/direnvrc" "sha256-XQzUAvL6pysIJnRJyR7uVpmUSZfc7LSgWQwq/4mBr1U=" 3 | fi 4 | source_env_if_exists .envrc.secrets 5 | source_env_if_exists .envrc.user 6 | -------------------------------------------------------------------------------- /docs/web/src/pages/About.tsx: -------------------------------------------------------------------------------- 1 | import { WhatIsBSL } from "@/components/WhatIsBSL"; 2 | import { Footer } from "@/components/Footer"; 3 | 4 | const About = () => { 5 | return ( 6 | <> 7 | 8 |