QueryEditor: Add internal coauthoring capability - #308
Draft
NWRichmond wants to merge 9 commits into
Draft
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds experimental PromQL coauthoring support to the Monaco query editor.
Changes:
- Adds selection normalization, validation, metadata context, and diff previews.
- Adds Monaco coauthoring controls and capability registration.
- Hides the legacy assistant when coauthoring is available.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
.changeset/fuzzy-queries-coauthor.md |
Records package patches. |
components/PromQueryField.tsx |
Forwards coauthoring integration. |
components/PromQueryField.test.tsx |
Tests prop forwarding. |
components/types.ts |
Extends editor props. |
components/monaco-query-field/MonacoQueryField.tsx |
Registers and styles coauthoring. |
components/monaco-query-field/MonacoQueryFieldProps.ts |
Adds coauthoring props. |
components/monaco-query-field/QueryCoauthoringWidget.ts |
Implements controls and lifecycle. |
components/monaco-query-field/QueryCoauthoringWidget.test.ts |
Tests widget behavior. |
locales/en-US/grafana-prometheus.json |
Adds control labels. |
query_coauthoring/capability.ts |
Implements the Grafana-facing capability. |
query_coauthoring/capability.test.ts |
Tests context and previews. |
query_coauthoring/structure.ts |
Implements PromQL parsing and diffs. |
query_coauthoring/structure.test.ts |
Tests structural processing. |
querybuilder/components/PromQueryCodeEditor.tsx |
Passes registrar to Monaco. |
querybuilder/components/PromQueryEditorSelector.tsx |
Coordinates assistant visibility. |
querybuilder/components/PromQueryEditorSelector.test.tsx |
Tests assistant visibility. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Suppressed comments (3)
packages/grafana-prometheus/src/query_coauthoring/structure.ts:139
- This fallback does not identify an exact
__name__matcher: for example,{service__name__="api"}is treated as metricapi. It also only decodes\\"and\\\\, so valid PromQL escapes such as__name__="http\\x2erequests"produce the wrong metadata key. Match the complete label name/literal and reuse the existing PromQL string decoder.
const selector = query.slice(node.from, node.to);
const nameMatcher = /__name__\s*=\s*"((?:\\.|[^"\\])*)"/.exec(selector);
if (nameMatcher) {
names.add(nameMatcher[1].replace(/\\"/g, '"').replace(/\\\\/g, '\\'));
}
packages/grafana-prometheus/src/components/monaco-query-field/MonacoQueryField.tsx:223
- Registration is tied to Monaco's one-shot
onMount. If the optional registrar is added, removed, or replaced while this editor remains mounted, the selector reacts to the new prop but this widget does not: enabling can hide Query with Assistant without registering coauthoring, while disabling leaves the old capability active. Keep the editor/Monaco instances in refs and manage registration and disposal from an effect that follows registrar availability.
if (onRegisterQueryEditorCoauthoring && createQueryForCoauthoringRef.current) {
coauthoringDisposeFun.current = registerPrometheusQueryCoauthoring({
packages/grafana-prometheus/src/components/monaco-query-field/QueryCoauthoringWidget.ts:70
queryLabelKeysexpects itsmatchargument to be a PromQL selector (seelanguage_provider.ts:261), but this passes the decoded metric name directly. That works for legacy identifiers only; a supported quoted metric such ashttp.requestsbecomes invalidmatch[]=http.requests, the request fails, and the catch ingetContextsilently drops its labels. Build an escaped{__name__="..."}selector as the other callers do (for exampleVariableQueryEditor.tsx:124-127).
queryMetricLabels: (metricName) => getLanguageProvider().queryLabelKeys(getTimeRange(), metricName, 30),
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.
Motivation
We're testing a query coauthoring flow in Grafana's panel editor for people who are editing existing PromQL but may not feel confident changing it by hand. The UI needs the editor's current selection, PromQL-aware focus boundaries, metric metadata, and a safe way to preview a change before applying it. This PR adds those Prometheus-specific pieces.
What this PR does
This adds the Prometheus-side pieces for an experimental query coauthoring UI in Grafana's panel editor.
When Grafana passes the optional registrar, the Monaco editor can:
Without the registrar, the editor works as it does today.
Grafana handles the UI, Assistant request, proposal checks, and applying an accepted query. The datasource handles Monaco selections and decorations plus the PromQL parsing and metadata it already knows about. The interface does not expose Monaco types outside the datasource.
This is an internal experiment, not a public plugin API. The new contracts are marked
@internaland can change while we work through the design. The datasource does not make AI requests, apply a query, or run it.Validation
npm run test:ci -- --runTestsByPath packages/grafana-prometheus/src/query_coauthoring/capability.test.ts packages/grafana-prometheus/src/query_coauthoring/structure.test.ts packages/grafana-prometheus/src/components/monaco-query-field/QueryCoauthoringWidget.test.ts packages/grafana-prometheus/src/components/PromQueryField.test.tsx packages/grafana-prometheus/src/querybuilder/components/PromQueryEditorSelector.test.tsxnpm run typecheck --workspace=@grafana/prometheusgit diff --check origin/main...HEADWhat I'd like feedback on
The main question is whether this is the right boundary between Grafana and the datasource. The API shape, PromQL selection normalization, Monaco lifecycle, metadata limits, and preview behavior are all still open to change, so I'm starting this as a draft.