agnes-the-ai-analyst/app/api
ZdenekSrotyr 5458ccc41b
hygiene: BQ error hint dispatch + catalog ENTITY column (#274)
Two analyst-UX papercuts surfaced by the v0.53.4 onboarding smoke test.

1) /api/query remote_estimate_failed hint now branches on the BigQuery
   error class instead of always claiming a column doesn't exist. The
   previous hardcoded "Most often this means a column referenced …
   doesn't exist" misled analysts whenever BigQuery actually rejected
   on syntax — concretely, `SELECT COUNT(*) AS rows FROM …` fails with
   `Syntax error: Unexpected keyword ROWS at [1:20]` (`rows` is a BQ
   reserved word) and the hint pointed at non-existent columns.

   New _hint_for_bq_bad_request() helper dispatches:
   - "Syntax error" / "Unexpected keyword" → reserved-keyword alias hint
     with `AS row_count` workaround
   - "Unrecognized name" / "not found inside" → `agnes schema <id>`
   - "Table not found" → `agnes catalog`
   - fallback → enumerate all three

   4 unit tests in TestHintForBqBadRequest pin each branch. Existing
   guardrail tests (test_fallback_fails_fast_on_pure_duckdb_syntax,
   test_remote_estimate_failed_surfaces_first_error_when_attempts_differ)
   continue to pass — both hint substrings they assert on still appear in
   the relevant branches.

2) `agnes catalog` replaces the FLAVOR column with ENTITY. FLAVOR
   rendered t['sql_flavor'] which duplicated SOURCE for any catalog
   dominated by one source type — analysts saw `SOURCE=bigquery
   FLAVOR=bigquery` on every row. ENTITY instead surfaces the upstream
   BigQuery entity_type (BASE TABLE / VIEW / MATERIALIZED_VIEW) for
   remote rows; non-remote rows render `-`. The distinction matters
   operationally: views don't support predicate pushdown, so `agnes
   query --remote` against a view trips the cost guardrail where the
   same query against a BASE TABLE pushes down cleanly. The
   entity_type field has been in the v2 catalog response since 0.51.0;
   this PR just stops hiding it behind a column header that conveyed
   no information.

JSON output (`agnes catalog --json`) is unchanged — only the human-
readable column changed. No DB migration; no API change.

Verified: 4161 tests pass locally; 25 in test_api_query_guardrail.py
green; the 4 new TestHintForBqBadRequest cases pin each branch.
2026-05-12 18:32:29 +00:00
..
__init__.py feat: add FastAPI server with auth, RBAC, and all API endpoints 2026-03-27 15:19:18 +01:00
_metadata_models.py feat(catalog): entity_type + validated where_examples + view-aware cost-guard + scheduler hygiene 2026-05-12 10:37:35 +02:00
access.py System plugins (schema v39) + marketplace UX polish + drop legacy pages (#241) 2026-05-10 19:15:41 +00:00
admin.py Flea-market upload guardrails + soft delete + JOIN-based admin queue (#233) 2026-05-09 17:32:53 +04:00
admin_bigquery_test.py feat(admin): #160 BQ test-connection endpoint + billing_project placeholder UI 2026-05-04 10:31:35 +02:00
bq_metadata_refresh.py release: 0.52.0 — UX/hygiene round (5 fixes from 0.51.0 retro) 2026-05-12 15:09:14 +02:00
cache_warmup.py release: 0.50.0 — persistent BQ metadata cache + scheduled refresh; catalog never blocks on BigQuery 2026-05-11 20:37:17 +02:00
catalog.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
claude_md.py chore(cli-rename): replace stale da verbs in active code paths 2026-05-04 21:10:43 +02:00
cli_artifacts.py chore: rename stale 'da' references to 'agnes' + CHANGELOG 2026-05-06 23:23:59 +02:00
data.py feat(caddy): file_server for parquet downloads — bypass uvicorn 2026-05-05 16:41:33 +02:00
health.py Extract session-pipeline framework + UsageProcessor skeleton (#232) 2026-05-08 19:47:46 +02:00
jira_webhooks.py fix(security): close Jira webhook fail-open + path traversal (#83) (#93) 2026-04-27 19:53:55 +02:00
marketplace.py Marketplace UX overhaul: rich plugin/skill/agent detail + filename rename (#251) 2026-05-12 08:38:39 +00:00
marketplaces.py System plugins (schema v39) + marketplace UX polish + drop legacy pages (#241) 2026-05-10 19:15:41 +00:00
me.py feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
me_debug.py feat(auth): /me/debug self-only auth diagnostic page (#116) 2026-04-29 06:36:28 +02:00
memory.py feat(memory): admin Edit + MEMORY_DOMAIN RBAC + ai-section UI (#141) 2026-04-30 11:04:41 +02:00
metadata.py feat(rbac+marketplace): RBAC v13 + Claude Code marketplace + #81/#83/#44 hardening 2026-04-28 14:25:04 +02:00
metrics.py feat(rbac+marketplace): RBAC v13 + Claude Code marketplace + #81/#83/#44 hardening 2026-04-28 14:25:04 +02:00
my_stack.py System plugins (schema v39) + marketplace UX polish + drop legacy pages (#241) 2026-05-10 19:15:41 +00:00
news.py feat(home): state-aware /home + /setup-advanced + schema v26 (#228) 2026-05-08 18:28:47 +02:00
query.py hygiene: BQ error hint dispatch + catalog ENTITY column (#274) 2026-05-12 18:32:29 +00:00
query_hybrid.py feat(rbac+marketplace): RBAC v13 + Claude Code marketplace + #81/#83/#44 hardening 2026-04-28 14:25:04 +02:00
scripts.py feat(scheduler): re-wire sync_schedule + script.schedule; tune via env; OpenMetadata TLS (#135) 2026-04-29 22:06:30 +02:00
settings.py feat(rbac): drop dataset_permissions + users.role + is_public; v19 migration (#150) 2026-04-30 22:02:16 +02:00
store.py Flea-market edit feature with version history (schema v37) (#239) 2026-05-10 00:14:33 +04:00
sync.py release: 0.47.1 — Keboola connector v27 (incremental, partitioned, where_filters, typed parquet) (#217) 2026-05-07 19:01:27 +02:00
telegram.py feat: complete system — web UI, all API endpoints, governance, admin, CLI commands 2026-03-27 16:52:22 +01:00
tokens.py chore(lint): final ruff fixes 2026-05-04 19:32:52 +02:00
upload.py fix(security+ops) + release(0.12.1): #82 #85 #87 hardening + cut 0.12.1 (#104) 2026-04-28 19:57:30 +02:00
users.py System plugins (schema v39) + marketplace UX polish + drop legacy pages (#241) 2026-05-10 19:15:41 +00:00
v2_arrow.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
v2_cache.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00
v2_catalog.py feat(catalog): entity_type + validated where_examples + view-aware cost-guard + scheduler hygiene 2026-05-12 10:37:35 +02:00
v2_quota.py refactor(quota): #160 relocate _build_quota_tracker to v2_quota.py 2026-05-04 10:31:35 +02:00
v2_sample.py release: 0.46.5 — agnes describe -n parses, server sanitizes NaN (#224) 2026-05-07 18:16:21 +02:00
v2_scan.py perf: Tier 1 event-loop unblocking — async def → def on BQ-bound handlers 2026-05-05 17:44:08 +02:00
v2_schema.py release: 0.53.0 — close Tier B trackers (#259-#261) + admin UI fix (#265) (#267) 2026-05-12 16:28:41 +02:00
welcome.py fix(devin-review): dashboard CTA respects override; PUT validates anon path 2026-05-03 21:45:32 +02:00
where_validator.py feat(v2): claude-driven fetch primitives + 0.14.0 (#102) 2026-04-29 01:07:19 +02:00