Skip to content

QueryEditor: Add internal coauthoring capability - #308

Draft
NWRichmond wants to merge 9 commits into
mainfrom
feature/dpro-247-query-coauthoring
Draft

QueryEditor: Add internal coauthoring capability#308
NWRichmond wants to merge 9 commits into
mainfrom
feature/dpro-247-query-coauthoring

Conversation

@NWRichmond

@NWRichmond NWRichmond commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

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:

  • show the selection-anchored Copy / Coauthor controls and keyboard shortcut;
  • share the current query, normalized focus ranges, and a bounded amount of metric metadata;
  • validate proposed PromQL and preview changes with Monaco decorations;
  • keep the editor read-only while a preview is visible, then restore its previous state;
  • hide the existing Query with Assistant action while the new flow is available.

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 @internal and 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.tsx
    • 5 suites passed
    • 55 tests passed
  • npm run typecheck --workspace=@grafana/prometheus
  • git diff --check origin/main...HEAD

What 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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread packages/grafana-prometheus/src/query_coauthoring/structure.ts
Comment thread packages/grafana-prometheus/src/query_coauthoring/capability.ts Outdated
Comment thread packages/grafana-prometheus/src/query_coauthoring/structure.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 metric api. 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

  • queryLabelKeys expects its match argument to be a PromQL selector (see language_provider.ts:261), but this passes the decoded metric name directly. That works for legacy identifiers only; a supported quoted metric such as http.requests becomes invalid match[]=http.requests, the request fails, and the catch in getContext silently drops its labels. Build an escaped {__name__="..."} selector as the other callers do (for example VariableQueryEditor.tsx:124-127).
    queryMetricLabels: (metricName) => getLanguageProvider().queryLabelKeys(getTimeRange(), metricName, 30),

@NWRichmond NWRichmond changed the title Prometheus query editor: add internal coauthoring capability QueryEditor: Add internal coauthoring capability Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants