Skip to content

Commit 2f93b87

Browse files
bartovalstratoula
andauthored
[ES|QL] Add context-aware suggestion ordering with categorization (elastic#243312)
**Work in progress** ## Summary elastic#197113 - Add priority rules by new suggestItem prop called category. - rules take precedence and the lowest wins - You can increase or decrease the priority of certain rules on a per-command basis. - the final priority is the base priority + boost commands priority - monaco editor receives a **new sequence of numbers normalized** and based on the priority roles system (no more A, B, 1C..) **Notes:** - We don't currently prioritize commands by preference (I don't know if it's needed, but it's easily extendable in the system) - The system is static for now --------- Co-authored-by: Stratou <[email protected]>
1 parent 5f9b685 commit 2f93b87

File tree

24 files changed

+539
-36
lines changed

24 files changed

+539
-36
lines changed

src/platform/packages/shared/kbn-esql-ast/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,7 @@ export { TIME_SYSTEM_PARAMS } from './src/definitions/utils/literals';
7474
export { withAutoSuggest } from './src/definitions/utils/autocomplete/helpers';
7575

7676
export { getNoValidCallSignatureError } from './src/definitions/utils/validation/utils';
77+
78+
export { SuggestionOrderingEngine } from './src/sorting';
79+
export { SuggestionCategory } from './src/sorting';
80+
export type { SortingContext } from './src/sorting';

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/commands/completion/autocomplete.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
import { ESQL_VARIABLES_PREFIX } from '../../constants';
4646
import { getExpressionType, isExpressionComplete } from '../../../definitions/utils/expressions';
4747
import { getFunctionDefinition } from '../../../definitions/utils/functions';
48+
import { SuggestionCategory } from '../../../sorting/types';
4849

4950
export enum CompletionPosition {
5051
AFTER_COMPLETION = 'after_completion',
@@ -207,7 +208,14 @@ export async function autocomplete(
207208

208209
if (!lastWord) {
209210
suggestions.push({
210-
...buildConstantsDefinitions([promptSnippetText], '', '1')[0],
211+
...buildConstantsDefinitions(
212+
[promptSnippetText],
213+
'',
214+
'1',
215+
undefined,
216+
undefined,
217+
SuggestionCategory.CONSTANT_VALUE
218+
)[0],
211219
label: promptText,
212220
asSnippet: true,
213221
});

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/commands/enrich/util.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { withAutoSuggest } from '../../../definitions/utils/autocomplete/helpers
1111
import type { ESQLAstAllCommands } from '../../../types';
1212
import type { ESQLPolicy, ISuggestionItem } from '../../types';
1313
import { getSafeInsertText } from '../../../definitions/utils/autocomplete/helpers';
14+
import { SuggestionCategory } from '../../../sorting/types';
1415

1516
export const ENRICH_MODES = [
1617
{
@@ -123,6 +124,7 @@ export const noPoliciesAvailableSuggestion: ISuggestionItem = {
123124
defaultMessage: 'Click to create',
124125
}),
125126
sortText: 'D',
127+
category: SuggestionCategory.CUSTOM_ACTION,
126128
command: {
127129
id: 'esql.policies.create',
128130
title: i18n.translate('kbn-esql-ast.esql.autocomplete.createNewPolicy', {
@@ -187,5 +189,6 @@ export const buildMatchingFieldsDefinition = (
187189
},
188190
}),
189191
sortText: 'D',
192+
category: SuggestionCategory.FIELD,
190193
})
191194
);

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/commands/rerank/autocomplete.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import { withAutoSuggest } from '../../../definitions/utils/autocomplete/helpers';
1010
import type { ESQLAstRerankCommand, ESQLSingleAstItem, ESQLAstAllCommands } from '../../../types';
1111
import type { ICommandCallbacks, ISuggestionItem, ICommandContext } from '../../types';
12+
import { SuggestionCategory } from '../../../sorting/types';
1213
import { Location } from '../../types';
1314
import { getPosition, CaretPosition } from './utils';
1415
import {
@@ -60,7 +61,14 @@ export async function autocomplete(
6061
return [
6162
targetField,
6263
{
63-
...buildConstantsDefinitions([QUERY_TEXT_SNIPPET], '', '1')[0],
64+
...buildConstantsDefinitions(
65+
[QUERY_TEXT_SNIPPET],
66+
'',
67+
'1',
68+
undefined,
69+
undefined,
70+
SuggestionCategory.CONSTANT_VALUE
71+
)[0],
6472
label: QUERY_TEXT,
6573
asSnippet: true,
6674
},
@@ -74,7 +82,14 @@ export async function autocomplete(
7482
case CaretPosition.RERANK_AFTER_TARGET_ASSIGNMENT: {
7583
return [
7684
{
77-
...buildConstantsDefinitions([QUERY_TEXT_SNIPPET], '', '1')[0],
85+
...buildConstantsDefinitions(
86+
[QUERY_TEXT_SNIPPET],
87+
'',
88+
'1',
89+
undefined,
90+
undefined,
91+
SuggestionCategory.CONSTANT_VALUE
92+
)[0],
7893
label: QUERY_TEXT,
7994
asSnippet: true,
8095
},

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/complete_items.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { esqlCommandRegistry } from '.';
1212
import { buildDocumentation } from '../definitions/utils/documentation';
1313
import { TIME_SYSTEM_PARAMS } from '../definitions/utils/literals';
1414
import { withAutoSuggest } from '../definitions/utils/autocomplete/helpers';
15+
import { SuggestionCategory } from '../sorting/types';
1516

1617
const techPreviewLabel = i18n.translate('kbn-esql-ast.esql.autocomplete.techPreviewLabel', {
1718
defaultMessage: `Technical Preview`,
@@ -24,7 +25,13 @@ function buildCharCompleteItem(
2425
sortText,
2526
quoted,
2627
advanceCursorAndOpenSuggestions,
27-
}: { sortText?: string; quoted: boolean; advanceCursorAndOpenSuggestions?: boolean } = {
28+
category,
29+
}: {
30+
sortText?: string;
31+
quoted: boolean;
32+
advanceCursorAndOpenSuggestions?: boolean;
33+
category?: SuggestionCategory;
34+
} = {
2835
quoted: false,
2936
}
3037
): ISuggestionItem {
@@ -34,6 +41,7 @@ function buildCharCompleteItem(
3441
kind: 'Keyword',
3542
detail,
3643
sortText,
44+
...(category && { category }),
3745
};
3846
return advanceCursorAndOpenSuggestions ? withAutoSuggest(suggestion) : suggestion;
3947
}
@@ -46,6 +54,7 @@ export const pipeCompleteItem: ISuggestionItem = withAutoSuggest({
4654
defaultMessage: 'Pipe (|)',
4755
}),
4856
sortText: 'C',
57+
category: SuggestionCategory.PIPE,
4958
});
5059

5160
export const allStarConstant: ISuggestionItem = {
@@ -65,7 +74,7 @@ export const commaCompleteItem = buildCharCompleteItem(
6574
i18n.translate('kbn-esql-ast.esql.autocomplete.commaDoc', {
6675
defaultMessage: 'Comma (,)',
6776
}),
68-
{ sortText: 'B', quoted: false }
77+
{ sortText: 'B', quoted: false, category: SuggestionCategory.COMMA }
6978
);
7079

7180
export const byCompleteItem: ISuggestionItem = withAutoSuggest({
@@ -74,6 +83,7 @@ export const byCompleteItem: ISuggestionItem = withAutoSuggest({
7483
kind: 'Reference',
7584
detail: 'By',
7685
sortText: '1',
86+
category: SuggestionCategory.LANGUAGE_KEYWORD,
7787
});
7888

7989
export const whereCompleteItem: ISuggestionItem = withAutoSuggest({
@@ -82,6 +92,7 @@ export const whereCompleteItem: ISuggestionItem = withAutoSuggest({
8292
kind: 'Reference',
8393
detail: 'Where',
8494
sortText: '1',
95+
category: SuggestionCategory.LANGUAGE_KEYWORD,
8596
});
8697

8798
export const onCompleteItem: ISuggestionItem = withAutoSuggest({
@@ -90,6 +101,7 @@ export const onCompleteItem: ISuggestionItem = withAutoSuggest({
90101
kind: 'Reference',
91102
detail: 'On',
92103
sortText: '1',
104+
category: SuggestionCategory.LANGUAGE_KEYWORD,
93105
});
94106

95107
export const withCompleteItem: ISuggestionItem = withAutoSuggest({
@@ -99,6 +111,7 @@ export const withCompleteItem: ISuggestionItem = withAutoSuggest({
99111
kind: 'Reference',
100112
detail: 'With',
101113
sortText: '1',
114+
category: SuggestionCategory.LANGUAGE_KEYWORD,
102115
});
103116

104117
export const withMapCompleteItem: ISuggestionItem = withAutoSuggest({
@@ -119,6 +132,7 @@ export const subqueryCompleteItem: ISuggestionItem = withAutoSuggest({
119132
defaultMessage: 'Adds a nested ES|QL query to your current query',
120133
}),
121134
sortText: '1',
135+
category: SuggestionCategory.CUSTOM_ACTION,
122136
});
123137

124138
export const minMaxValueCompleteItem: ISuggestionItem = {
@@ -127,6 +141,7 @@ export const minMaxValueCompleteItem: ISuggestionItem = {
127141
kind: 'Value',
128142
detail: 'minmax',
129143
sortText: '1',
144+
category: SuggestionCategory.VALUE,
130145
};
131146

132147
export const noneValueCompleteItem: ISuggestionItem = {
@@ -135,6 +150,7 @@ export const noneValueCompleteItem: ISuggestionItem = {
135150
kind: 'Value',
136151
detail: 'none',
137152
sortText: '1',
153+
category: SuggestionCategory.VALUE,
138154
};
139155

140156
export const getNewUserDefinedColumnSuggestion = (label: string): ISuggestionItem => {
@@ -146,6 +162,7 @@ export const getNewUserDefinedColumnSuggestion = (label: string): ISuggestionIte
146162
defaultMessage: 'Define a new column',
147163
}),
148164
sortText: '1',
165+
category: SuggestionCategory.USER_DEFINED_COLUMN,
149166
});
150167
};
151168

@@ -157,6 +174,7 @@ export const assignCompletionItem: ISuggestionItem = withAutoSuggest({
157174
kind: 'Variable',
158175
sortText: '1',
159176
text: '= ',
177+
category: SuggestionCategory.USER_DEFINED_COLUMN,
160178
});
161179

162180
export const asCompletionItem: ISuggestionItem = {
@@ -167,6 +185,7 @@ export const asCompletionItem: ISuggestionItem = {
167185
label: 'AS',
168186
sortText: '1',
169187
text: 'AS ',
188+
category: SuggestionCategory.LANGUAGE_KEYWORD,
170189
};
171190

172191
export const colonCompleteItem = buildCharCompleteItem(
@@ -254,4 +273,5 @@ export const getDateHistogramCompletionItem: (histogramBarTarget?: number) => IS
254273
defaultMessage: 'Add date histogram using bucket()',
255274
}),
256275
sortText: '1',
276+
category: SuggestionCategory.CUSTOM_ACTION,
257277
});

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/options/metadata/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { buildFieldsDefinitions } from '../../../definitions/utils/functions';
1414
import { handleFragment } from '../../../definitions/utils/autocomplete/helpers';
1515
import { commaCompleteItem, pipeCompleteItem } from '../../complete_items';
1616
import { isColumn, isOptionNode } from '../../../ast/is';
17+
import { SuggestionCategory } from '../../../sorting/types';
1718

1819
export const METADATA_FIELDS = [
1920
'_version',
@@ -33,6 +34,7 @@ export const metadataSuggestion: ISuggestionItem = withAutoSuggest({
3334
defaultMessage: 'Metadata',
3435
}),
3536
sortText: 'C',
37+
category: SuggestionCategory.VALUE,
3638
});
3739

3840
export const getMetadataSuggestions = (command: ESQLAstAllCommands, queryText: string) => {

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/options/recommended_queries/index.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,21 @@ import type { RecommendedQuery, RecommendedField } from '@kbn/esql-types';
1111
import type { GetColumnsByTypeFn, ISuggestionItem } from '../../types';
1212
import { METADATA_FIELDS } from '../metadata';
1313
import { prettifyQueryTemplate, prettifyQuery } from './utils';
14+
import { SuggestionCategory } from '../../../sorting/types';
1415

1516
export interface EditorExtensions {
1617
recommendedQueries: RecommendedQuery[];
1718
recommendedFields: RecommendedField[];
1819
}
1920

21+
interface QueryTemplate {
22+
label: string;
23+
description: string;
24+
queryString: string;
25+
sortText?: string;
26+
category?: SuggestionCategory;
27+
}
28+
2029
// Order starts with the simple ones and goes to more complex ones
2130

2231
export const getRecommendedQueriesTemplates = ({
@@ -27,8 +36,8 @@ export const getRecommendedQueriesTemplates = ({
2736
fromCommand: string;
2837
timeField?: string;
2938
categorizationField?: string;
30-
}) => {
31-
const queries = [
39+
}): QueryTemplate[] => {
40+
const queries: QueryTemplate[] = [
3241
{
3342
label: i18n.translate('kbn-esql-ast.recommendedQueries.searchExample.label', {
3443
defaultMessage: 'Search all fields',
@@ -38,6 +47,7 @@ export const getRecommendedQueriesTemplates = ({
3847
}),
3948
queryString: `${fromCommand}\n | WHERE KQL("term") /* Search all fields using KQL – e.g. WHERE KQL("debug") */`,
4049
sortText: 'D',
50+
category: SuggestionCategory.RECOMMENDED_QUERY_WITH_PRIORITY,
4151
},
4252
{
4353
label: i18n.translate('kbn-esql-ast.recommendedQueries.aggregateExample.label', {
@@ -201,6 +211,7 @@ export const getRecommendedQueriesSuggestionsFromStaticTemplates = async (
201211
kind: 'Issue',
202212
detail: query.description,
203213
sortText: query?.sortText ?? 'E',
214+
category: query.category ?? SuggestionCategory.RECOMMENDED_QUERY,
204215
command: {
205216
id: 'esql.recommendedQuery.accept',
206217
title: 'Accept recommended query',
@@ -239,6 +250,7 @@ export const getRecommendedQueriesTemplatesFromExtensions = (
239250
: {}),
240251
kind: 'Issue',
241252
sortText: 'D',
253+
category: SuggestionCategory.RECOMMENDED_QUERY_WITH_PRIORITY,
242254
};
243255
}
244256
);

src/platform/packages/shared/kbn-esql-ast/src/commands_registry/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import type { PricingProduct } from '@kbn/core-pricing-common/src/types';
1818
import type { ESQLLocation } from '../types';
1919
import type { FieldType, SupportedDataType } from '../definitions/types';
2020
import type { EditorExtensions } from './options/recommended_queries';
21+
import type { SuggestionCategory } from '../sorting/types';
2122

2223
// This is a subset of the Monaco's editor CompletitionItemKind type
2324
export type ItemKind =
@@ -65,6 +66,10 @@ export interface ISuggestionItem {
6566
* A string to use for sorting the suggestion within the suggestions list
6667
*/
6768
sortText?: string;
69+
/**
70+
* The category of the suggestion, used for sorting and prioritization
71+
*/
72+
category?: SuggestionCategory;
6873
/**
6974
* Suggestions can trigger a command by id. This is useful to trigger specific actions in some contexts
7075
*/

src/platform/packages/shared/kbn-esql-ast/src/definitions/utils/autocomplete/helpers.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import type { FunctionDefinition } from '../../types';
2828
import type { SupportedDataType } from '../../types';
2929
import { argMatchesParamType, getExpressionType, getParamAtPosition } from '../expressions';
3030
import { filterFunctionDefinitions, getAllFunctions, getFunctionSuggestion } from '../functions';
31+
import { SuggestionCategory } from '../../../sorting/types';
3132
import { buildConstantsDefinitions, getCompatibleLiterals, getDateLiterals } from '../literals';
3233
import { getColumnByName } from '../shared';
3334

@@ -53,6 +54,7 @@ export const buildUserDefinedColumnsDefinitions = (
5354
defaultMessage: `Column specified by the user within the ES|QL query`,
5455
}),
5556
sortText: 'D',
57+
category: SuggestionCategory.USER_DEFINED_COLUMN,
5658
}));
5759

5860
export function pushItUpInTheList(suggestions: ISuggestionItem[], shouldPromote: boolean) {
@@ -327,6 +329,7 @@ export function getControlSuggestion(
327329
defaultMessage: 'Click to create',
328330
}),
329331
sortText: '1',
332+
category: SuggestionCategory.CUSTOM_ACTION,
330333
command: {
331334
id: `esql.control.${type}.create`,
332335
title: i18n.translate('kbn-esql-ast.esql.autocomplete.createControlDetailLabel', {
@@ -341,7 +344,10 @@ export function getControlSuggestion(
341344
i18n.translate('kbn-esql-ast.esql.autocomplete.namedParamDefinition', {
342345
defaultMessage: 'Named parameter',
343346
}),
344-
'1A'
347+
'1A',
348+
undefined,
349+
undefined,
350+
SuggestionCategory.USER_DEFINED_COLUMN
345351
)
346352
: []),
347353
];
@@ -519,6 +525,7 @@ export function createInferenceEndpointToCompletionItem(
519525
label: inferenceEndpoint.inference_id,
520526
sortText: '1',
521527
text: inferenceEndpoint.inference_id,
528+
category: SuggestionCategory.VALUE,
522529
};
523530
}
524531

0 commit comments

Comments
 (0)