dataface 0.1.2__py3-none-any.whl
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.
- d3_format/__init__.py +14 -0
- d3_format/errors.py +19 -0
- d3_format/format.py +551 -0
- d3_format/spec.py +159 -0
- dataface/DATAFACE_SYNTAX.md +1135 -0
- dataface/__init__.py +93 -0
- dataface/_docs_site.py +20 -0
- dataface/_install_hint.py +26 -0
- dataface/agent_api/__init__.py +79 -0
- dataface/agent_api/_init_templates/__init__.py +0 -0
- dataface/agent_api/_init_templates/agents_dft_snippet.md +26 -0
- dataface/agent_api/_init_templates/dataface.yml +15 -0
- dataface/agent_api/_init_templates/faces-dataface.yml +144 -0
- dataface/agent_api/_init_templates/index.md +24 -0
- dataface/agent_api/_paths.py +118 -0
- dataface/agent_api/_project_agents_md.py +43 -0
- dataface/agent_api/_session_store.py +486 -0
- dataface/agent_api/_state.py +28 -0
- dataface/agent_api/chat.py +221 -0
- dataface/agent_api/dashboards.py +257 -0
- dataface/agent_api/describe.py +366 -0
- dataface/agent_api/describe_query.py +120 -0
- dataface/agent_api/docs/__init__.py +25 -0
- dataface/agent_api/docs/_loader.py +292 -0
- dataface/agent_api/docs/yaml-reference.md +2757 -0
- dataface/agent_api/file_refs.py +118 -0
- dataface/agent_api/init.py +126 -0
- dataface/agent_api/inspect.py +128 -0
- dataface/agent_api/mcp_install.py +170 -0
- dataface/agent_api/query.py +274 -0
- dataface/agent_api/schema.py +658 -0
- dataface/agent_api/schema_search.py +284 -0
- dataface/agent_api/search.py +270 -0
- dataface/agent_api/skill_install.py +141 -0
- dataface/agent_api/skill_render.py +90 -0
- dataface/agent_api/skills.py +293 -0
- dataface/agent_api/surface_aliases.yaml +128 -0
- dataface/agent_api/validate.py +175 -0
- dataface/agent_api/validate_query.py +84 -0
- dataface/ai/__init__.py +39 -0
- dataface/ai/agent.py +139 -0
- dataface/ai/context.py +45 -0
- dataface/ai/events.py +62 -0
- dataface/ai/external_mcp.py +610 -0
- dataface/ai/generate_sql.py +96 -0
- dataface/ai/llm.py +403 -0
- dataface/ai/mcp/__init__.py +51 -0
- dataface/ai/mcp/server.py +289 -0
- dataface/ai/memories.py +85 -0
- dataface/ai/prompts.py +177 -0
- dataface/ai/schema_context.py +138 -0
- dataface/ai/skills/before-after-comparison/SKILL.md +102 -0
- dataface/ai/skills/before-after-comparison/examples/before-after-comparison.yml +24 -0
- dataface/ai/skills/dashboard-build/SKILL.md +212 -0
- dataface/ai/skills/dashboard-build/examples/_smoke.yml +15 -0
- dataface/ai/skills/dashboard-design/SKILL.md +182 -0
- dataface/ai/skills/dashboard-review/SKILL.md +113 -0
- dataface/ai/skills/dashboard-structural-review/SKILL.md +173 -0
- dataface/ai/skills/dashboard-visual-review/SKILL.md +139 -0
- dataface/ai/skills/dataface-mcp-setup/SKILL.md +177 -0
- dataface/ai/skills/dataface-troubleshooting/SKILL.md +225 -0
- dataface/ai/skills/drill-down-link/SKILL.md +112 -0
- dataface/ai/skills/drill-down-link/examples/drill-down-link.yml +27 -0
- dataface/ai/skills/faceted-small-multiples/SKILL.md +116 -0
- dataface/ai/skills/faceted-small-multiples/examples/faceted-small-multiples.yml +33 -0
- dataface/ai/skills/filter-bar-with-variables/SKILL.md +105 -0
- dataface/ai/skills/filter-bar-with-variables/examples/filter-bar-with-variables.yml +49 -0
- dataface/ai/skills/kpi-row/SKILL.md +101 -0
- dataface/ai/skills/kpi-row/examples/kpi-row.yml +55 -0
- dataface/ai/skills/report-design/SKILL.md +184 -0
- dataface/ai/skills/single-metric-bignum/SKILL.md +90 -0
- dataface/ai/skills/single-metric-bignum/examples/single-metric-bignum.yml +27 -0
- dataface/ai/skills/table-heavy-ops-dashboard/SKILL.md +114 -0
- dataface/ai/skills/table-heavy-ops-dashboard/examples/table-heavy-ops-dashboard.yml +48 -0
- dataface/ai/skills/time-series-trend/SKILL.md +93 -0
- dataface/ai/skills/time-series-trend/examples/time-series-trend.yml +26 -0
- dataface/ai/skills/top-n-with-detail/SKILL.md +98 -0
- dataface/ai/skills/top-n-with-detail/examples/top-n-with-detail.yml +45 -0
- dataface/ai/skills/two-by-two-grid-overview/SKILL.md +78 -0
- dataface/ai/skills/two-by-two-grid-overview/examples/two-by-two-grid-overview.yml +64 -0
- dataface/ai/tool_schemas.py +132 -0
- dataface/ai/tools/__init__.py +312 -0
- dataface/ai/yaml_utils.py +57 -0
- dataface/cli/__init__.py +3 -0
- dataface/cli/_console.py +48 -0
- dataface/cli/_error_format.py +83 -0
- dataface/cli/_extras.py +190 -0
- dataface/cli/_json_output.py +8 -0
- dataface/cli/_parsing.py +17 -0
- dataface/cli/_version_info.py +56 -0
- dataface/cli/commands/__init__.py +3 -0
- dataface/cli/commands/_agent_input.py +205 -0
- dataface/cli/commands/_agent_server.py +115 -0
- dataface/cli/commands/chat.py +645 -0
- dataface/cli/commands/describe.py +107 -0
- dataface/cli/commands/docs.py +131 -0
- dataface/cli/commands/extension.py +179 -0
- dataface/cli/commands/init.py +240 -0
- dataface/cli/commands/inspect.py +94 -0
- dataface/cli/commands/mcp_init.py +167 -0
- dataface/cli/commands/query.py +386 -0
- dataface/cli/commands/render.py +291 -0
- dataface/cli/commands/schema.py +411 -0
- dataface/cli/commands/search.py +49 -0
- dataface/cli/commands/serve.py +114 -0
- dataface/cli/commands/skills.py +133 -0
- dataface/cli/commands/skills_init.py +161 -0
- dataface/cli/commands/validate.py +63 -0
- dataface/cli/main.py +1501 -0
- dataface/core/__init__.py +75 -0
- dataface/core/compile/__init__.py +244 -0
- dataface/core/compile/_jinja_helpers.py +78 -0
- dataface/core/compile/channel.py +222 -0
- dataface/core/compile/chart_focus.py +101 -0
- dataface/core/compile/chart_resolved.py +169 -0
- dataface/core/compile/chart_type_detection.py +489 -0
- dataface/core/compile/chart_update.py +261 -0
- dataface/core/compile/colors.py +64 -0
- dataface/core/compile/compiler.py +904 -0
- dataface/core/compile/config.py +823 -0
- dataface/core/compile/custom_chart_types.py +208 -0
- dataface/core/compile/data_table_attachment.py +1287 -0
- dataface/core/compile/detect.py +110 -0
- dataface/core/compile/errors.py +302 -0
- dataface/core/compile/filter_injection.py +319 -0
- dataface/core/compile/introspection.py +527 -0
- dataface/core/compile/jinja.py +511 -0
- dataface/core/compile/labels_env.py +52 -0
- dataface/core/compile/markdown.py +154 -0
- dataface/core/compile/meta.py +388 -0
- dataface/core/compile/models/__init__.py +0 -0
- dataface/core/compile/models/chart/__init__.py +0 -0
- dataface/core/compile/models/chart/authored.py +2137 -0
- dataface/core/compile/models/chart/compiled.py +398 -0
- dataface/core/compile/models/config.py +347 -0
- dataface/core/compile/models/face/__init__.py +0 -0
- dataface/core/compile/models/face/authored.py +659 -0
- dataface/core/compile/models/face/compiled.py +522 -0
- dataface/core/compile/models/factories.py +201 -0
- dataface/core/compile/models/markers.py +40 -0
- dataface/core/compile/models/palette.py +36 -0
- dataface/core/compile/models/primitives.py +415 -0
- dataface/core/compile/models/query/__init__.py +0 -0
- dataface/core/compile/models/query/authored.py +246 -0
- dataface/core/compile/models/query/compiled.py +710 -0
- dataface/core/compile/models/refs.py +137 -0
- dataface/core/compile/models/source.py +611 -0
- dataface/core/compile/models/style/__init__.py +0 -0
- dataface/core/compile/models/style/authored.py +481 -0
- dataface/core/compile/models/style/compiled.py +3399 -0
- dataface/core/compile/models/style/merged.py +1682 -0
- dataface/core/compile/models/theme.py +362 -0
- dataface/core/compile/models/variable/__init__.py +0 -0
- dataface/core/compile/models/variable/authored.py +254 -0
- dataface/core/compile/models/vega_lite/__init__.py +0 -0
- dataface/core/compile/models/vega_lite/config.py +510 -0
- dataface/core/compile/models/vega_lite/contracts.py +171 -0
- dataface/core/compile/normalize_charts.py +494 -0
- dataface/core/compile/normalize_layout.py +1000 -0
- dataface/core/compile/normalize_queries.py +297 -0
- dataface/core/compile/normalize_variables.py +489 -0
- dataface/core/compile/normalizer.py +543 -0
- dataface/core/compile/palette.py +1100 -0
- dataface/core/compile/parameterized.py +658 -0
- dataface/core/compile/parser.py +228 -0
- dataface/core/compile/schema.py +20 -0
- dataface/core/compile/schema_renderers/__init__.py +0 -0
- dataface/core/compile/schema_renderers/json_schema.py +163 -0
- dataface/core/compile/schema_renderers/prompt.py +152 -0
- dataface/core/compile/schema_renderers/vscode_schema.py +301 -0
- dataface/core/compile/sizing.py +2126 -0
- dataface/core/compile/sources.py +518 -0
- dataface/core/compile/sql_authoring_lint.py +56 -0
- dataface/core/compile/style_cascade.py +471 -0
- dataface/core/compile/typography.py +299 -0
- dataface/core/compile/validator.py +301 -0
- dataface/core/compile/variables.py +53 -0
- dataface/core/compile/vega_config.py +98 -0
- dataface/core/compile/vega_lite/__init__.py +6 -0
- dataface/core/compile/vega_lite/validation.py +95 -0
- dataface/core/compile/yaml_error_formatter.py +838 -0
- dataface/core/connections.py +38 -0
- dataface/core/dashboard.py +358 -0
- dataface/core/defaults/default_config.yml +101 -0
- dataface/core/defaults/palettes/categorical/category-10-dark.yml +32 -0
- dataface/core/defaults/palettes/categorical/category-10-light.yml +43 -0
- dataface/core/defaults/palettes/categorical/category-10.yml +31 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-blue.yml +22 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-brown.yml +29 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-green.yml +20 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-orange.yml +21 -0
- dataface/core/defaults/palettes/categorical/category-6-tonal-purple.yml +20 -0
- dataface/core/defaults/palettes/categorical/editorial-10-dark.yml +32 -0
- dataface/core/defaults/palettes/categorical/editorial-10.yml +40 -0
- dataface/core/defaults/palettes/categorical/hero-6.yml +17 -0
- dataface/core/defaults/palettes/categorical/single-blue.yml +11 -0
- dataface/core/defaults/palettes/categorical/tableau.yml +20 -0
- dataface/core/defaults/palettes/data/xkcd_colors.json +3803 -0
- dataface/core/defaults/palettes/diverging/blue-red.yml +25 -0
- dataface/core/defaults/palettes/diverging/coolwarm.yml +24 -0
- dataface/core/defaults/palettes/diverging/crimson-green.yml +23 -0
- dataface/core/defaults/palettes/diverging/orange-teal.yml +23 -0
- dataface/core/defaults/palettes/diverging/sunset.yml +24 -0
- dataface/core/defaults/palettes/scaffold/dft-creams.yml +38 -0
- dataface/core/defaults/palettes/scaffold/dft-grays.yml +53 -0
- dataface/core/defaults/palettes/sequential/amber.yml +22 -0
- dataface/core/defaults/palettes/sequential/blue.yml +22 -0
- dataface/core/defaults/palettes/sequential/brown.yml +22 -0
- dataface/core/defaults/palettes/sequential/gray.yml +22 -0
- dataface/core/defaults/palettes/sequential/green.yml +22 -0
- dataface/core/defaults/palettes/sequential/purple.yml +22 -0
- dataface/core/defaults/palettes/sequential/rust.yml +22 -0
- dataface/core/defaults/palettes/sequential/teal.yml +22 -0
- dataface/core/defaults/palettes/tone/negative.yml +32 -0
- dataface/core/defaults/palettes/tone/positive.yml +22 -0
- dataface/core/defaults/palettes/tone/warning.yml +22 -0
- dataface/core/defaults/themes/_base.yaml +786 -0
- dataface/core/defaults/themes/bi.yaml +16 -0
- dataface/core/defaults/themes/carbong100.yaml +41 -0
- dataface/core/defaults/themes/cream.yaml +122 -0
- dataface/core/defaults/themes/dark.yaml +40 -0
- dataface/core/defaults/themes/diagnostics-title-angle-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-baseline-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-baseline.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-center.yaml +8 -0
- dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +25 -0
- dataface/core/defaults/themes/diagnostics-title-left.yaml +8 -0
- dataface/core/defaults/themes/diagnostics-title-offset-extreme.yaml +9 -0
- dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +24 -0
- dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +24 -0
- dataface/core/defaults/themes/editorial.yaml +147 -0
- dataface/core/defaults/themes/light.yaml +30 -0
- dataface/core/defaults/themes/looker.yaml +17 -0
- dataface/core/defaults/themes/stark.yaml +134 -0
- dataface/core/errors/__init__.py +67 -0
- dataface/core/errors/codes_compile.py +56 -0
- dataface/core/errors/codes_execute.py +177 -0
- dataface/core/errors/codes_render.py +106 -0
- dataface/core/errors/codes_unknown.py +15 -0
- dataface/core/errors/hints.py +74 -0
- dataface/core/errors/registry.py +42 -0
- dataface/core/errors/structured.py +92 -0
- dataface/core/execute/__init__.py +91 -0
- dataface/core/execute/adapters/__init__.py +49 -0
- dataface/core/execute/adapters/adapter_registry.py +400 -0
- dataface/core/execute/adapters/base.py +245 -0
- dataface/core/execute/adapters/csv_adapter.py +239 -0
- dataface/core/execute/adapters/dbt_adapter.py +283 -0
- dataface/core/execute/adapters/dbt_adapter_factory.py +212 -0
- dataface/core/execute/adapters/dbt_macro_loader.py +95 -0
- dataface/core/execute/adapters/dbt_utils.py +150 -0
- dataface/core/execute/adapters/http_adapter.py +224 -0
- dataface/core/execute/adapters/metricflow_adapter.py +94 -0
- dataface/core/execute/adapters/schema_resolver_adapter.py +144 -0
- dataface/core/execute/adapters/sql_adapter.py +710 -0
- dataface/core/execute/adapters/values_adapter.py +58 -0
- dataface/core/execute/batch.py +744 -0
- dataface/core/execute/cache_backend.py +135 -0
- dataface/core/execute/cache_keys.py +66 -0
- dataface/core/execute/dbt_jinja.py +21 -0
- dataface/core/execute/dialects/__init__.py +121 -0
- dataface/core/execute/dialects/athena.py +75 -0
- dataface/core/execute/dialects/base.py +302 -0
- dataface/core/execute/dialects/bigquery.py +38 -0
- dataface/core/execute/dialects/databricks.py +68 -0
- dataface/core/execute/dialects/duckdb.py +35 -0
- dataface/core/execute/dialects/mysql.py +68 -0
- dataface/core/execute/dialects/postgres.py +39 -0
- dataface/core/execute/dialects/redshift.py +12 -0
- dataface/core/execute/dialects/snowflake.py +51 -0
- dataface/core/execute/dialects/sqlserver.py +92 -0
- dataface/core/execute/duckdb_cache.py +712 -0
- dataface/core/execute/duckdb_config.py +26 -0
- dataface/core/execute/errors.py +213 -0
- dataface/core/execute/executor.py +1249 -0
- dataface/core/execute/parallel.py +162 -0
- dataface/core/execute/setup_sql.py +58 -0
- dataface/core/execute/source_registry.py +72 -0
- dataface/core/execute/source_resolver.py +255 -0
- dataface/core/execute/sql_guard.py +387 -0
- dataface/core/execute/sql_literals.py +199 -0
- dataface/core/fonts.py +52 -0
- dataface/core/inspect/__init__.py +32 -0
- dataface/core/inspect/cache_factory.py +98 -0
- dataface/core/inspect/db_types.py +162 -0
- dataface/core/inspect/dbt_schema.py +96 -0
- dataface/core/inspect/defaults.yml +37 -0
- dataface/core/inspect/fanout_risk.py +109 -0
- dataface/core/inspect/manifest_utils.py +77 -0
- dataface/core/inspect/partials/categorical.yml +40 -0
- dataface/core/inspect/partials/date.yml +40 -0
- dataface/core/inspect/partials/numeric.yml +55 -0
- dataface/core/inspect/partition_types.py +38 -0
- dataface/core/inspect/query_validator.py +975 -0
- dataface/core/inspect/renderer.py +354 -0
- dataface/core/inspect/resolver.py +808 -0
- dataface/core/inspect/search.py +461 -0
- dataface/core/inspect/sources/__init__.py +32 -0
- dataface/core/inspect/sources/dbt.py +738 -0
- dataface/core/inspect/sources/duckdb_utils.py +66 -0
- dataface/core/inspect/templates/__init__.py +1 -0
- dataface/core/inspect/templates/categorical_column.yml +196 -0
- dataface/core/inspect/templates/charts.yml +109 -0
- dataface/core/inspect/templates/date_column.yml +248 -0
- dataface/core/inspect/templates/model.yml +138 -0
- dataface/core/inspect/templates/numeric_column.yml +261 -0
- dataface/core/inspect/templates/quality.yml +80 -0
- dataface/core/inspect/templates/string_column.yml +263 -0
- dataface/core/project_roots.py +165 -0
- dataface/core/render/__init__.py +87 -0
- dataface/core/render/board_links.py +176 -0
- dataface/core/render/chart/__init__.py +27 -0
- dataface/core/render/chart/arc_attached_table.py +251 -0
- dataface/core/render/chart/artifacts.py +16 -0
- dataface/core/render/chart/callout.py +225 -0
- dataface/core/render/chart/decisions.py +358 -0
- dataface/core/render/chart/geo.py +700 -0
- dataface/core/render/chart/kpi.py +916 -0
- dataface/core/render/chart/labels.py +76 -0
- dataface/core/render/chart/pipeline.py +818 -0
- dataface/core/render/chart/presentation.py +36 -0
- dataface/core/render/chart/profile.py +3438 -0
- dataface/core/render/chart/render_single.py +347 -0
- dataface/core/render/chart/renderers.py +193 -0
- dataface/core/render/chart/rendering.py +565 -0
- dataface/core/render/chart/serialization.py +90 -0
- dataface/core/render/chart/spark.py +496 -0
- dataface/core/render/chart/spark_bar.py +370 -0
- dataface/core/render/chart/spec_builders.py +154 -0
- dataface/core/render/chart/standard_renderer.py +2645 -0
- dataface/core/render/chart/table.py +2957 -0
- dataface/core/render/chart/table_support.py +1452 -0
- dataface/core/render/chart/tick_values.py +66 -0
- dataface/core/render/chart/time_unit_detect.py +809 -0
- dataface/core/render/chart/title_overflow.py +157 -0
- dataface/core/render/chart/type_inference.py +122 -0
- dataface/core/render/chart/validation.py +99 -0
- dataface/core/render/chart/vega_lite.py +125 -0
- dataface/core/render/chart/vega_lite_types.py +268 -0
- dataface/core/render/chart/vl_field_maps.py +346 -0
- dataface/core/render/chart_interactivity.py +24 -0
- dataface/core/render/control_registry.py +287 -0
- dataface/core/render/converters/__init__.py +24 -0
- dataface/core/render/converters/chart.py +276 -0
- dataface/core/render/converters/html.py +98 -0
- dataface/core/render/converters/pdf.py +40 -0
- dataface/core/render/converters/png.py +41 -0
- dataface/core/render/errors.py +144 -0
- dataface/core/render/face_api.py +160 -0
- dataface/core/render/faces.py +1194 -0
- dataface/core/render/font_measurement.py +48 -0
- dataface/core/render/font_support.py +197 -0
- dataface/core/render/fonts/DFTSansTabular-Regular.ttf +0 -0
- dataface/core/render/fonts/DFTSansTabular-Regular.woff2 +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.ttf +0 -0
- dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.ttf +0 -0
- dataface/core/render/fonts/InterVariable.ttf +0 -0
- dataface/core/render/fonts/InterVariable.woff2 +0 -0
- dataface/core/render/fonts/NOTO_COLOR_EMOJI_LICENSE.txt +93 -0
- dataface/core/render/fonts/NOTO_EMOJI_LICENSE.txt +93 -0
- dataface/core/render/fonts/NotoColorEmoji-Regular.ttf +0 -0
- dataface/core/render/fonts/NotoColorEmoji-Regular.woff2 +0 -0
- dataface/core/render/fonts/NotoEmoji-Regular.ttf +0 -0
- dataface/core/render/fonts/NotoEmoji-Regular.woff2 +0 -0
- dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -0
- dataface/core/render/fonts/SOURCE_SERIF_4_LICENSE.txt +98 -0
- dataface/core/render/fonts/SourceCodePro-Regular.ttf +0 -0
- dataface/core/render/fonts/SourceSerif4-Regular.ttf +0 -0
- dataface/core/render/fonts/_emoji_font_face.css +43 -0
- dataface/core/render/fonts/source-serif-4-variable-latin.woff2 +0 -0
- dataface/core/render/format_utils.py +329 -0
- dataface/core/render/geo_defaults.yml +28 -0
- dataface/core/render/json_format.py +146 -0
- dataface/core/render/layout_sizing.py +865 -0
- dataface/core/render/layouts.py +541 -0
- dataface/core/render/markdown_defaults.yml +16 -0
- dataface/core/render/missing_vars_prompt.py +79 -0
- dataface/core/render/placeholder.py +389 -0
- dataface/core/render/render_result.py +14 -0
- dataface/core/render/renderer.py +467 -0
- dataface/core/render/script_embedding.py +16 -0
- dataface/core/render/svg_utils.py +212 -0
- dataface/core/render/template_loader.py +69 -0
- dataface/core/render/templates/controls/_styles.css +606 -0
- dataface/core/render/templates/controls/checkbox.html +16 -0
- dataface/core/render/templates/controls/date.html +16 -0
- dataface/core/render/templates/controls/number.html +19 -0
- dataface/core/render/templates/controls/readonly.html +9 -0
- dataface/core/render/templates/controls/select.html +21 -0
- dataface/core/render/templates/controls/slider.html +22 -0
- dataface/core/render/templates/controls/text.html +16 -0
- dataface/core/render/templates/scripts/chart_interactivity.js +191 -0
- dataface/core/render/templates/scripts/variables.js +976 -0
- dataface/core/render/templates/svg/grid_pattern.svg +3 -0
- dataface/core/render/templates/svg/styles.css +51 -0
- dataface/core/render/terminal.py +311 -0
- dataface/core/render/terminal_charts.py +563 -0
- dataface/core/render/terminal_defaults.yml +2 -0
- dataface/core/render/terminal_layouts.py +299 -0
- dataface/core/render/terminal_text.py +31 -0
- dataface/core/render/text/__init__.py +1 -0
- dataface/core/render/text/case.py +113 -0
- dataface/core/render/text_format.py +129 -0
- dataface/core/render/utils.py +106 -0
- dataface/core/render/variable_controls.py +946 -0
- dataface/core/render/variable_input_refinement.py +140 -0
- dataface/core/render/warnings/__init__.py +15 -0
- dataface/core/render/warnings/bar_color_1_to_1_with_x.py +80 -0
- dataface/core/render/warnings/base.py +44 -0
- dataface/core/render/warnings/fanout_risk.py +15 -0
- dataface/core/render/warnings/from_query_diagnostic.py +56 -0
- dataface/core/render/warnings/missing_join_predicate.py +13 -0
- dataface/core/render/warnings/query_parse_error.py +14 -0
- dataface/core/render/warnings/query_returned_zero_rows.py +42 -0
- dataface/core/render/warnings/reaggregation.py +14 -0
- dataface/core/render/warnings/registry.py +45 -0
- dataface/core/render/warnings/suppression.py +46 -0
- dataface/core/render/warnings/temporal_single_point.py +63 -0
- dataface/core/render/warnings/unreferenced_chart.py +15 -0
- dataface/core/render/warnings/y_encoding_mostly_null.py +76 -0
- dataface/core/render/yaml_format.py +167 -0
- dataface/core/resolve_face.py +195 -0
- dataface/core/schema/__init__.py +0 -0
- dataface/core/schema/guidance.py +151 -0
- dataface/core/scoped_paths.py +59 -0
- dataface/core/serve/__init__.py +14 -0
- dataface/core/serve/bootstrap.py +39 -0
- dataface/core/serve/embedded.py +57 -0
- dataface/core/serve/port.py +129 -0
- dataface/core/serve/server.py +938 -0
- dataface/core/serve/templates/__init__.py +0 -0
- dataface/core/serve/templates/directory.yml +6 -0
- dataface/core/serve/templates/error.html.j2 +217 -0
- dataface/core/utils.py +121 -0
- dataface/core/validate.py +64 -0
- dataface/integrations/__init__.py +0 -0
- dataface/integrations/highlighting.py +351 -0
- dataface/integrations/markdown.py +537 -0
- dataface/py.typed +0 -0
- dataface-0.1.2.dist-info/METADATA +375 -0
- dataface-0.1.2.dist-info/RECORD +455 -0
- dataface-0.1.2.dist-info/WHEEL +4 -0
- dataface-0.1.2.dist-info/entry_points.txt +2 -0
- dataface-0.1.2.dist-info/licenses/LICENSE +202 -0
- mdsvg/__init__.py +168 -0
- mdsvg/fonts.py +656 -0
- mdsvg/images.py +299 -0
- mdsvg/parser.py +629 -0
- mdsvg/playground.py +284 -0
- mdsvg/py.typed +2 -0
- mdsvg/renderer.py +1623 -0
- mdsvg/style.py +355 -0
- mdsvg/types.py +200 -0
- mdsvg/utils.py +86 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""validate_query verb — static SQL lint without warehouse access."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib.util
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
from dataface.core.inspect.query_validator import (
|
|
11
|
+
RelationshipContext,
|
|
12
|
+
validate_query as _core_validate,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
_SUPER_SCHEMA_AVAILABLE = importlib.util.find_spec("dataface_super_schema") is not None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _load_relationship_context() -> RelationshipContext | None:
|
|
19
|
+
"""Load relationship context from the private package when available."""
|
|
20
|
+
if not _SUPER_SCHEMA_AVAILABLE:
|
|
21
|
+
return None
|
|
22
|
+
from dataface_super_schema.inspect.relationship_context import ( # noqa: PLC0415
|
|
23
|
+
load_relationship_context,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
return load_relationship_context()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ValidateQueryResult(BaseModel):
|
|
30
|
+
has_errors: bool = Field(
|
|
31
|
+
False,
|
|
32
|
+
description="True when any active diagnostic has severity == 'error'.",
|
|
33
|
+
)
|
|
34
|
+
diagnostics: list[dict[str, Any]] = Field(
|
|
35
|
+
default_factory=list,
|
|
36
|
+
description="Active diagnostic messages (non-suppressed).",
|
|
37
|
+
)
|
|
38
|
+
suppressed: list[dict[str, Any]] | None = Field(
|
|
39
|
+
None,
|
|
40
|
+
description="Suppressed diagnostics (only present when return_suppressed=True).",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def validate_query(
|
|
45
|
+
sql: str,
|
|
46
|
+
*,
|
|
47
|
+
dialect: str | None = None,
|
|
48
|
+
return_suppressed: bool = False,
|
|
49
|
+
relationship_context: RelationshipContext | None = None,
|
|
50
|
+
) -> ValidateQueryResult:
|
|
51
|
+
"""Run static SQL validation and return a typed result.
|
|
52
|
+
|
|
53
|
+
Loads relationship context from the inspection cache automatically (same
|
|
54
|
+
as the CLI command). Pass relationship_context explicitly to override.
|
|
55
|
+
"""
|
|
56
|
+
if relationship_context is None:
|
|
57
|
+
relationship_context = _load_relationship_context()
|
|
58
|
+
|
|
59
|
+
if return_suppressed:
|
|
60
|
+
diags, suppressed = _core_validate(
|
|
61
|
+
sql,
|
|
62
|
+
dialect=dialect,
|
|
63
|
+
relationship_context=relationship_context,
|
|
64
|
+
return_suppressed=True,
|
|
65
|
+
)
|
|
66
|
+
suppressed_dicts: list[dict[str, Any]] | None = [
|
|
67
|
+
d.to_dict() for d in suppressed
|
|
68
|
+
]
|
|
69
|
+
else:
|
|
70
|
+
diags = _core_validate(
|
|
71
|
+
sql,
|
|
72
|
+
dialect=dialect,
|
|
73
|
+
relationship_context=relationship_context,
|
|
74
|
+
)
|
|
75
|
+
suppressed_dicts = None
|
|
76
|
+
|
|
77
|
+
diag_dicts = [d.to_dict() for d in diags]
|
|
78
|
+
has_errors = any(d.get("severity") == "error" for d in diag_dicts)
|
|
79
|
+
|
|
80
|
+
return ValidateQueryResult(
|
|
81
|
+
has_errors=has_errors,
|
|
82
|
+
diagnostics=diag_dicts,
|
|
83
|
+
suppressed=suppressed_dicts,
|
|
84
|
+
)
|
dataface/ai/__init__.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Core AI utilities for Dataface.
|
|
2
|
+
|
|
3
|
+
This module provides shared AI service utilities used by both Playground and Suite.
|
|
4
|
+
It consolidates common patterns like prompt loading, tool definitions, and YAML extraction.
|
|
5
|
+
|
|
6
|
+
Modules:
|
|
7
|
+
prompts: Prompt loading and building utilities
|
|
8
|
+
tools: Common AI tool definitions (render_dashboard, execute_query, schema)
|
|
9
|
+
yaml_utils: YAML extraction from AI responses
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from dataface.ai.prompts import PromptLoader, load_prompt
|
|
13
|
+
from dataface.ai.schema_context import get_schema_context
|
|
14
|
+
from dataface.ai.tools import (
|
|
15
|
+
TOOL_EXECUTE_QUERY,
|
|
16
|
+
TOOL_RENDER_DASHBOARD,
|
|
17
|
+
TOOL_SCHEMA,
|
|
18
|
+
TOOL_SEARCH_DASHBOARDS,
|
|
19
|
+
get_tools,
|
|
20
|
+
handle_tool_call,
|
|
21
|
+
) # noqa: F401 — re-exported for public surface
|
|
22
|
+
from dataface.ai.yaml_utils import extract_yaml
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
# Prompts
|
|
26
|
+
"load_prompt",
|
|
27
|
+
"PromptLoader",
|
|
28
|
+
# Tools
|
|
29
|
+
"get_tools",
|
|
30
|
+
"handle_tool_call",
|
|
31
|
+
"TOOL_RENDER_DASHBOARD",
|
|
32
|
+
"TOOL_EXECUTE_QUERY",
|
|
33
|
+
"TOOL_SCHEMA",
|
|
34
|
+
"TOOL_SEARCH_DASHBOARDS",
|
|
35
|
+
# Schema context
|
|
36
|
+
"get_schema_context",
|
|
37
|
+
# YAML utilities
|
|
38
|
+
"extract_yaml",
|
|
39
|
+
]
|
dataface/ai/agent.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Provider-neutral agent loop for the terminal agent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from collections.abc import Generator
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
from dataface.agent_api.docs import read_full_text as _read_dataface_syntax
|
|
10
|
+
from dataface.ai.context import DatafaceAIContext
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from dataface.ai.external_mcp import ExternalMCPManager
|
|
14
|
+
|
|
15
|
+
from dataface.ai.events import (
|
|
16
|
+
AgentDone,
|
|
17
|
+
AgentError,
|
|
18
|
+
AgentEvent,
|
|
19
|
+
ContentDelta,
|
|
20
|
+
ToolCallEvent,
|
|
21
|
+
ToolResultEvent,
|
|
22
|
+
)
|
|
23
|
+
from dataface.ai.llm import LLMClient, LLMClientError
|
|
24
|
+
from dataface.ai.memories import format_memories_prompt, load_memories
|
|
25
|
+
from dataface.ai.prompts import load_shared_prompt
|
|
26
|
+
from dataface.ai.schema_context import get_schema_context
|
|
27
|
+
from dataface.ai.tool_schemas import ALL_TOOLS
|
|
28
|
+
from dataface.ai.tools import dispatch_tool_call
|
|
29
|
+
|
|
30
|
+
_TOOL_GUIDANCE = """## Tool Use
|
|
31
|
+
|
|
32
|
+
- Use `schema` (drill from sources → schema → table → column) and `execute_query` to inspect real data before making claims.
|
|
33
|
+
- Use `search_dashboards` to reuse existing patterns when relevant.
|
|
34
|
+
- Use `render_dashboard` to validate dashboard YAML and inspect resolved chart/data semantics before treating it as finished.
|
|
35
|
+
- Use `render_dashboard(path=..., as_link=true)` to surface a localhost URL the user can open to view a saved dashboard in their browser.
|
|
36
|
+
- If a tool returns an error, explain it clearly instead of hiding it.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build_agent_system_prompt(context: DatafaceAIContext) -> str:
|
|
41
|
+
"""Build the terminal agent system prompt from shared skills and schema context."""
|
|
42
|
+
parts = [
|
|
43
|
+
load_shared_prompt("dashboard-build"),
|
|
44
|
+
load_shared_prompt("dashboard-design"),
|
|
45
|
+
load_shared_prompt("dashboard-review"),
|
|
46
|
+
_read_dataface_syntax(),
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
schema_context = get_schema_context(
|
|
50
|
+
adapter_registry=context.adapter_registry,
|
|
51
|
+
)
|
|
52
|
+
if schema_context and not schema_context.startswith(
|
|
53
|
+
"No database connection available"
|
|
54
|
+
):
|
|
55
|
+
parts.append(schema_context)
|
|
56
|
+
|
|
57
|
+
memory_block = format_memories_prompt(load_memories(context.default_project_dir))
|
|
58
|
+
if memory_block:
|
|
59
|
+
parts.append(memory_block)
|
|
60
|
+
|
|
61
|
+
parts.append(_TOOL_GUIDANCE)
|
|
62
|
+
return "\n\n---\n\n".join(part for part in parts if part)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def run_agent(
|
|
66
|
+
prompt: str,
|
|
67
|
+
*,
|
|
68
|
+
client: LLMClient,
|
|
69
|
+
context: DatafaceAIContext,
|
|
70
|
+
messages: list[dict[str, Any]] | None = None,
|
|
71
|
+
max_iterations: int = 12,
|
|
72
|
+
tools: list[dict[str, Any]] | None = None,
|
|
73
|
+
external_manager: ExternalMCPManager | None = None,
|
|
74
|
+
) -> Generator[AgentEvent, None, None]:
|
|
75
|
+
"""Run the agent loop and stream typed events.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
tools: Tool list to pass to the LLM. Defaults to ALL_TOOLS (built-in only).
|
|
79
|
+
Pass a merged list to include external MCP tools.
|
|
80
|
+
external_manager: ExternalMCPManager instance for routing 'server__tool' calls.
|
|
81
|
+
Must be provided when tools contains external (namespaced) entries.
|
|
82
|
+
"""
|
|
83
|
+
effective_tools = tools if tools is not None else ALL_TOOLS
|
|
84
|
+
conversation = messages if messages is not None else []
|
|
85
|
+
conversation.append({"role": "user", "content": prompt})
|
|
86
|
+
system_prompt = build_agent_system_prompt(context)
|
|
87
|
+
|
|
88
|
+
for _ in range(max_iterations):
|
|
89
|
+
response_text = ""
|
|
90
|
+
tool_calls: list[ToolCallEvent] = []
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
for event in client.stream_with_tools(
|
|
94
|
+
messages=conversation,
|
|
95
|
+
system_prompt=system_prompt,
|
|
96
|
+
tools=effective_tools,
|
|
97
|
+
):
|
|
98
|
+
if isinstance(event, ContentDelta):
|
|
99
|
+
response_text += event.delta
|
|
100
|
+
elif isinstance(event, ToolCallEvent):
|
|
101
|
+
tool_calls.append(event)
|
|
102
|
+
yield event
|
|
103
|
+
except LLMClientError as exc:
|
|
104
|
+
yield AgentError(message=str(exc))
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
conversation.append(
|
|
108
|
+
{
|
|
109
|
+
"role": "assistant",
|
|
110
|
+
"content": response_text,
|
|
111
|
+
"tool_calls": [
|
|
112
|
+
{"id": tc.id, "name": tc.name, "arguments": tc.arguments}
|
|
113
|
+
for tc in tool_calls
|
|
114
|
+
],
|
|
115
|
+
}
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if not tool_calls:
|
|
119
|
+
yield AgentDone(response=response_text)
|
|
120
|
+
return
|
|
121
|
+
|
|
122
|
+
for tc in tool_calls:
|
|
123
|
+
result = dispatch_tool_call(
|
|
124
|
+
tc.name,
|
|
125
|
+
tc.arguments,
|
|
126
|
+
context=context,
|
|
127
|
+
external_manager=external_manager,
|
|
128
|
+
)
|
|
129
|
+
conversation.append(
|
|
130
|
+
{
|
|
131
|
+
"role": "tool",
|
|
132
|
+
"tool_call_id": tc.id,
|
|
133
|
+
"name": tc.name,
|
|
134
|
+
"content": json.dumps(result, default=str),
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
yield ToolResultEvent(id=tc.id, name=tc.name, result=result)
|
|
138
|
+
|
|
139
|
+
yield AgentError(message="Agent stopped after reaching max iterations.")
|
dataface/ai/context.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Shared scoping context for Dataface AI and MCP surfaces."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from dataface.core.execute.adapters import AdapterRegistry
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class DatafaceAIContext:
|
|
15
|
+
"""Scope shared AI/MCP helpers to a specific source boundary."""
|
|
16
|
+
|
|
17
|
+
adapter_registry: AdapterRegistry
|
|
18
|
+
dashboards_directory: Path | None = None
|
|
19
|
+
default_project_dir: Path | None = None
|
|
20
|
+
default_source: str | None = None
|
|
21
|
+
# Port of the embedded HTTP preview server. Set by `dft mcp serve` and
|
|
22
|
+
# `dft chat` after binding; consumed by `_view_url` to build clickable
|
|
23
|
+
# localhost URLs in `render_dashboard` responses (including as_link=True).
|
|
24
|
+
server_port: int | None = None
|
|
25
|
+
|
|
26
|
+
def resolve_dashboard_path(self, path: Path) -> Path:
|
|
27
|
+
"""Resolve a dashboard path inside the scoped dashboards directory.
|
|
28
|
+
|
|
29
|
+
When no explicit dashboards directory is configured, paths default to the
|
|
30
|
+
project's ``faces/`` directory under the current working directory.
|
|
31
|
+
"""
|
|
32
|
+
if path.is_absolute():
|
|
33
|
+
raise ValueError(f"Dashboard path must be relative: {path}")
|
|
34
|
+
if self.dashboards_directory is None:
|
|
35
|
+
base_dir = (Path.cwd() / "faces").resolve()
|
|
36
|
+
else:
|
|
37
|
+
base_dir = self.dashboards_directory.resolve()
|
|
38
|
+
resolved = (base_dir / path).resolve()
|
|
39
|
+
try:
|
|
40
|
+
resolved.relative_to(base_dir)
|
|
41
|
+
except ValueError as exc:
|
|
42
|
+
raise ValueError(
|
|
43
|
+
f"Dashboard path escapes scoped directory: {path}"
|
|
44
|
+
) from exc
|
|
45
|
+
return resolved
|
dataface/ai/events.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Typed event protocol for the terminal agent loop."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
# -- Stream events (yielded by LLM provider adapters) -----------------------
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(slots=True)
|
|
12
|
+
class ContentDelta:
|
|
13
|
+
"""Incremental text chunk from the model."""
|
|
14
|
+
|
|
15
|
+
delta: str
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(slots=True)
|
|
19
|
+
class ThinkingStatus:
|
|
20
|
+
"""Reasoning/thinking status from the model."""
|
|
21
|
+
|
|
22
|
+
status: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(slots=True)
|
|
26
|
+
class ToolCallEvent:
|
|
27
|
+
"""Model requested a tool invocation."""
|
|
28
|
+
|
|
29
|
+
id: str
|
|
30
|
+
name: str
|
|
31
|
+
arguments: dict[str, Any]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
StreamEvent = ContentDelta | ThinkingStatus | ToolCallEvent
|
|
35
|
+
|
|
36
|
+
# -- Agent-level events (yielded by the agent loop) -------------------------
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(slots=True)
|
|
40
|
+
class ToolResultEvent:
|
|
41
|
+
"""Result of executing a tool call."""
|
|
42
|
+
|
|
43
|
+
id: str
|
|
44
|
+
name: str
|
|
45
|
+
result: Any
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(slots=True)
|
|
49
|
+
class AgentDone:
|
|
50
|
+
"""Agent finished with a final text response."""
|
|
51
|
+
|
|
52
|
+
response: str
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(slots=True)
|
|
56
|
+
class AgentError:
|
|
57
|
+
"""Agent encountered an error."""
|
|
58
|
+
|
|
59
|
+
message: str
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
AgentEvent = StreamEvent | ToolResultEvent | AgentDone | AgentError
|