feat(reporting): AI chat reporting module + plugin analytics engine#97
Draft
StephanieJKS wants to merge 4 commits into
Draft
feat(reporting): AI chat reporting module + plugin analytics engine#97StephanieJKS wants to merge 4 commits into
StephanieJKS wants to merge 4 commits into
Conversation
…tics operators, DownloadCsv. The reporting additions from the ai-chat-reporting design: - ReportingData connection with the single read-only AnalyticsQuery request: validate an AI-composed query spec against the data dictionary (field allowlist + dataset roles) → compile to a $match/$group/$project/$sort/ $limit-only aggregation (values typed literals, limit clamped to 1000, maxTimeMS cap) → execute against the dataset's collection. Reuses the package's shared getMongoDb client cache. - _analytics server operators (new operators/server export): validateReportSpec, validateChartSpec, validateExportSpec, querySections, compileReport (report spec + resolve-time rows → Lowdefy blocks with deferred __state/__api/ __if_none filter wiring, failed sections as Alert cards), and buildDataParts (chart/download dataParts for the emit-data-parts hook, capped at 8/turn). - DownloadCsv client action: rows → CSV in the browser (RFC-4180 quoting, formula-injection guard), no storage round-trip. - Charts use the ECharts dataset+encode form so the data source is exactly the query rows — the compiler swaps in a deferred __state source on filtered sections without touching series config. - Null-valued filters are dropped by the validator: an unset report filter control means "no constraint", letting controls bind state directly into filter values. 52 new tests, including an in-memory-Mongo end-to-end run of the design's example query and a roles-gate rejection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jGT2SkTpc2JSkKAeT3vYJ
… report renderer. The module half of the ai-chat-reporting design: pages, api endpoints, connections and the bundled agent, installable as config. - Agent (reporting-assistant): data dictionary embedded in instructions at build time; explicit LLM-safe tool names (query_data, render_chart, export_data, generate_report); save-conversation + emit-data-parts onFinish hooks. Requires module-level agents support in the framework. - Query engine: the query-data endpoint serves the agent tool, report filter re-queries and panel downloads through the single AnalyticsQuery boundary. - Chat page: AgentChat + AgentConversations with an adjacent results panel that accumulates chart/download dataParts per turn (onDataPart → state arrays → List of ECharts and download buttons). - Report generation: generate-report validates and persists the raw spec (userId-scoped) and returns the report URL; generate-oneshot runs the agent headlessly (CallAgent) and returns the new report's id. - Report rendering: a Dynamic page resolved by resolve-report — per-section queries inside :try (failed sections render as Alert cards), blocks compiled by _analytics.compileReport with deferred __state/__api filter wiring; fallback slot for whole-report failures. - Conversations upsert with a title derived from the first user message; list endpoints are userId-scoped; delete-report guards deletion. Verified by building a test app against the local lowdefy build with module-level agents: agent ids, connection ids, tool endpoints, hook references, CallAgent agentId, Dynamic endpointId and client _api keys all resolve to entry-scoped ids. Deviation from design: generate-report stores sourceConversationId: null — tool endpoints receive only the tool input, so the conversation id does not reach them in the current agent system. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jGT2SkTpc2JSkKAeT3vYJ
Updates the demo and workflows-test apps (lowdefy.yaml + package.json) and the lockfile to the 2026-07-07 experimental release. The matching peerDependency bumps in @lowdefy/modules-mongodb-plugins landed with the reporting plugin commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017jGT2SkTpc2JSkKAeT3vYJ
This reverts commit e647a8f.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The AI chat reporting module and its plugin support, from the
ai-chat-reportingdesign (lowdefy-design/designs/ai-chat-reporting): chat to your data and generate saved, navigable reports, installable as config. The AI never runs uncontrolled queries or emits uncontrolled UI — every path from natural language to data goes through one validated, authorization-gated request, and reports are declarative specs compiled to blocks by trusted server code.Requires the module-level agents framework change (companion PR on
lowdefy/lowdefy, branchfeat/module-agents).Plugin additions (
@lowdefy/modules-mongodb-plugins)ReportingDataconnection with the single read-onlyAnalyticsQueryrequest: validate an AI-composed query spec against the app's data dictionary (field allowlist + per-dataset roles) → compile to a$match/$group/$project/$sort/$limit-only aggregation (typed literal values, limit clamped to 1,000,maxTimeMScap) → execute against the dataset's collection. Reuses the package's shared mongo client cache._analyticsserver operators (new./operators/serverexport — the package's first operators): spec validators (query/chart/export/report, with caps from the design's security model),querySections,compileReport(report spec + resolve-time rows → Lowdefy blocks, with deferred__state/__api/__if_nonefilter wiring and failed sections rendered as Alert cards), andbuildDataParts(chart/download dataParts for the chat panel, ≤ 8 specs/turn).DownloadCsvclient action: rows → CSV in the browser (RFC-4180 quoting, formula-injection guard). No storage round-trip.dataset+encodeform so the data source is exactly the query's row array — the compiler swaps in a deferred__statesource on filtered sections without touching series config.The reporting module (
modules/reporting)reporting-assistant): the data dictionary embedded in instructions at build time; LLM-safe tool names (query_data,render_chart,export_data,generate_report);save-conversation+emit-data-partsonFinish hooks (both no-op headlessly).CallAgentruns the assistant headlessly and navigates to the finished report).generate-reportvalidates and persists the raw spec (userId-scoped) and returns the report URL; the report page is a Dynamic block resolved byresolve-report— per-section queries inside:try(dictionary drift degrades a section to an Alert card, not the report), filters re-query throughquery-datavia compiledCallAPI/SetStatewiring.0.0.0-experimental-20260707071904for the apps and lockfile.Tests & verification
_secretin compiled output). Full plugin suite green (813 tests).CallAgentagentId, DynamicendpointId, client_apikeys, report URL) resolves to entry-scoped ids.Notes
sourceConversationIdis stored asnullin v1 — tool endpoints receive only the tool input as payload, so the conversationId never reachesgenerate_report.🤖 Generated with Claude Code
https://claude.ai/code/session_017jGT2SkTpc2JSkKAeT3vYJ