Files
signoz/frontend/src/lib/newQueryBuilder/transformQueryBuilderDataModel.ts
Gaurav Tewari 4a0c34c236 feat(querybuilder): support builder_ai_query envelope type
Adds the plumbing the AI o11y explorer needs from the query builder,
with every addition defaulted so existing behaviour is unchanged. No
caller sets the new options yet, so this is a no-op for all nine
current QueryBuilderV2 call sites.

Payload:
- add 'builder_ai_query' to the QueryType union, plus a narrowed
  BuilderQueryEnvelopeType alias. Narrow on purpose: the other members
  take a different spec shape and the backend decodes with
  DisallowUnknownFields, so passing one with a builder spec is a 400.
- convertBuilderQueriesToV5 takes the envelope type as a defaulted 4th
  param instead of hardcoding 'builder_query'.
- GetQueryResultsProps gains builderQueryType, threaded through
  prepareQueryRangePayloadV5 (which destructures explicitly, so it has
  to be named there — a spread does not reach it).

Response:
- mapQueryFromV5 is an if/else-if chain with no fallback, so an
  unrecognised envelope type was silently dropped rather than defaulted.
  builder_ai_query shares the builder-query spec shape and name
  namespace, so it now hydrates into queryData the same way.

Query builder props:
- showSpanScopeSelector (default true) lets a page hide the
  All/Root/Entrypoint select. Gated in QueryV2's memo so both render
  sites are covered. QueryProps already declared this prop and nothing
  read it; this gives that declaration meaning.
- fieldKeysQueryType is forwarded verbatim to /fields/keys as `type` so
  the backend can scope the suggested key set. Appended to the URL only
  when set, keeping every existing request byte-identical.

Deliberately not included: the AI explorer page itself, per-query AI
state, and 'trace' as a field context (the last needs a backend
decision — see frontend/docs/ai-explorer-qb-changeset.md).
2026-08-06 17:06:08 +05:30

54 lines
1.6 KiB
TypeScript

import {
initialFormulaBuilderFormValues,
initialQueryBuilderFormValuesMap,
} from 'constants/queryBuilder';
import { FORMULA_REGEXP, TRACE_OPERATOR_REGEXP } from 'constants/regExp';
import {
BuilderQueryDataResourse,
IBuilderFormula,
IBuilderQuery,
IBuilderTraceOperator,
} from 'types/api/queryBuilder/queryBuilderData';
import { QueryBuilderData } from 'types/common/queryBuilder';
export const transformQueryBuilderDataModel = (
data: BuilderQueryDataResourse,
queryTypes?: Record<
string,
| 'builder_query'
| 'builder_ai_query'
| 'builder_formula'
| 'builder_trace_operator'
>,
): QueryBuilderData => {
const queryData: QueryBuilderData['queryData'] = [];
const queryFormulas: QueryBuilderData['queryFormulas'] = [];
const queryTraceOperator: QueryBuilderData['queryTraceOperator'] = [];
Object.entries(data).forEach(([key, value]) => {
const isFormula = queryTypes
? queryTypes[key] === 'builder_formula'
: FORMULA_REGEXP.test(value.queryName);
const isTraceOperator = queryTypes
? queryTypes[key] === 'builder_trace_operator'
: TRACE_OPERATOR_REGEXP.test(value.queryName);
if (isFormula) {
const formula = value as IBuilderFormula;
queryFormulas.push({ ...initialFormulaBuilderFormValues, ...formula });
} else if (isTraceOperator) {
const traceOperator = value as IBuilderTraceOperator;
queryTraceOperator.push({ ...traceOperator });
} else {
const queryFromData = value as IBuilderQuery;
queryData.push({
...initialQueryBuilderFormValuesMap.metrics,
...queryFromData,
});
}
});
return { queryData, queryFormulas, queryTraceOperator };
};