Skip to content

Commit 66c28e3

Browse files
committed
fix: better code
1 parent 2531e60 commit 66c28e3

File tree

6 files changed

+259
-16
lines changed

6 files changed

+259
-16
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"@hookform/resolvers": "^3.10.0",
2929
"@reduxjs/toolkit": "^2.5.0",
3030
"@tanstack/react-table": "^8.20.6",
31-
"@ydb-platform/monaco-ghost": "^0.1.8",
31+
"@ydb-platform/monaco-ghost": "^0.1.10",
3232
"axios": "^1.7.9",
3333
"axios-retry": "^4.5.0",
3434
"colord": "^2.9.3",

src/containers/Tenant/Query/QueryEditor/YqlEditor.tsx

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import throttle from 'lodash/throttle';
66
import type Monaco from 'monaco-editor';
77

88
import {MonacoEditor} from '../../../../components/MonacoEditor/MonacoEditor';
9-
import {codeAssistApi} from '../../../../store/reducers/codeAssist/codeAssist';
109
import {
1110
goToNextQuery,
1211
goToPreviousQuery,
@@ -26,8 +25,9 @@ import {useUpdateErrorsHighlighting} from '../../../../utils/monaco/highlightErr
2625
import {QUERY_ACTIONS} from '../../../../utils/query';
2726
import {SAVE_QUERY_DIALOG} from '../SaveQuery/SaveQuery';
2827
import i18n from '../i18n';
28+
import {useSavedQueries} from '../utils/useSavedQueries';
2929

30-
import {useEditorOptions} from './helpers';
30+
import {useCodeAssist, useEditorOptions} from './helpers';
3131
import {getKeyBindings} from './keybindings';
3232

3333
const CONTEXT_MENU_GROUP_ID = 'navigation';
@@ -48,6 +48,7 @@ export function YqlEditor({
4848
const input = useTypedSelector(selectUserInput);
4949
const dispatch = useTypedDispatch();
5050
const historyQueries = useTypedSelector(selectQueriesHistory);
51+
const savedQueries = useSavedQueries();
5152
const editorOptions = useEditorOptions();
5253
const updateErrorsHighlighting = useUpdateErrorsHighlighting();
5354

@@ -72,21 +73,24 @@ export function YqlEditor({
7273
window.ydbEditor = undefined;
7374
};
7475

75-
const [sendCodeAssistPrompt] = codeAssistApi.useLazyGetCodeAssistSuggestionsQuery();
76+
const {
77+
getCodeAssistSuggestions,
78+
onCompletionAccept,
79+
onCompletionDecline,
80+
onCompletionIgnore,
81+
prepareUserQueriesCache,
82+
} = useCodeAssist();
7683

7784
const {registerMonacoGhost, dispose} = useMonacoGhost({
7885
api: {
79-
getCodeAssistSuggestions: async (prompt) => {
80-
try {
81-
return await sendCodeAssistPrompt(prompt).unwrap();
82-
} catch {
83-
return {items: []};
84-
}
85-
},
86+
getCodeAssistSuggestions,
8687
},
8788
config: {
8889
language: YQL_LANGUAGE_ID,
8990
},
91+
onCompletionAccept,
92+
onCompletionDecline,
93+
onCompletionIgnore,
9094
});
9195

9296
const editorDidMount = React.useCallback(
@@ -105,6 +109,16 @@ export function YqlEditor({
105109

106110
if (window.api.codeAssist) {
107111
registerMonacoGhost(editor);
112+
prepareUserQueriesCache([
113+
...historyQueries.map((query, index) => ({
114+
name: `query${index}.yql`,
115+
text: query.queryText,
116+
})),
117+
...savedQueries.map((query) => ({
118+
name: query.name,
119+
text: query.body,
120+
})),
121+
]);
108122
}
109123
initResizeHandler(editor);
110124
initUserPrompt(editor, getLastQueryText);
@@ -198,7 +212,10 @@ export function YqlEditor({
198212
getLastQueryText,
199213
handleSendExecuteClick,
200214
handleSendQuery,
215+
historyQueries,
216+
prepareUserQueriesCache,
201217
registerMonacoGhost,
218+
savedQueries,
202219
],
203220
);
204221

src/containers/Tenant/Query/QueryEditor/helpers.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React from 'react';
22

3+
import type {AcceptEvent, DeclineEvent, IgnoreEvent, PromptFile} from '@ydb-platform/monaco-ghost';
34
import type Monaco from 'monaco-editor';
45

6+
import type {TelemetryOpenTabs} from '../../../../services/api/codeAssist';
7+
import {codeAssistApi} from '../../../../store/reducers/codeAssist/codeAssist';
58
import {AUTOCOMPLETE_ON_ENTER, ENABLE_AUTOCOMPLETE} from '../../../../utils/constants';
69
import {useSetting} from '../../../../utils/hooks';
710

@@ -32,3 +35,80 @@ export function useEditorOptions() {
3235

3336
return options;
3437
}
38+
39+
export function useCodeAssist() {
40+
const [sendCodeAssistPrompt] = codeAssistApi.useLazyGetCodeAssistSuggestionsQuery();
41+
const [acceptSuggestion] = codeAssistApi.useLazyAcceptSuggestionQuery();
42+
const [discardSuggestion] = codeAssistApi.useLazyDiscardSuggestionQuery();
43+
const [ignoreSuggestion] = codeAssistApi.useLazyIgnoreSuggestionQuery();
44+
const [sendUserQueriesData] = codeAssistApi.useLazySendUserQueriesDataQuery();
45+
46+
const getCodeAssistSuggestions = React.useCallback(
47+
async (prompt: PromptFile[]) => {
48+
try {
49+
const {items} = await sendCodeAssistPrompt(prompt).unwrap();
50+
51+
return {items};
52+
} catch {
53+
return {items: []};
54+
}
55+
},
56+
[sendCodeAssistPrompt],
57+
);
58+
59+
const onCompletionAccept = React.useCallback(
60+
async (event: AcceptEvent) => {
61+
try {
62+
return await acceptSuggestion(event).unwrap();
63+
} catch {
64+
return {items: []};
65+
}
66+
},
67+
[acceptSuggestion],
68+
);
69+
70+
const onCompletionDecline = React.useCallback(
71+
async (event: DeclineEvent) => {
72+
try {
73+
return await discardSuggestion(event).unwrap();
74+
} catch {
75+
return {items: []};
76+
}
77+
},
78+
[discardSuggestion],
79+
);
80+
81+
const onCompletionIgnore = React.useCallback(
82+
async (event: IgnoreEvent) => {
83+
try {
84+
return await ignoreSuggestion(event).unwrap();
85+
} catch {
86+
return {items: []};
87+
}
88+
},
89+
[ignoreSuggestion],
90+
);
91+
92+
const prepareUserQueriesCache = React.useCallback(
93+
async (queries: {text: string; name?: string}[]) => {
94+
const preparedData: TelemetryOpenTabs = queries.map((query, index) => ({
95+
FileName: query.name || `query${index}.yql`,
96+
Text: query.text,
97+
}));
98+
try {
99+
return await sendUserQueriesData(preparedData).unwrap();
100+
} catch {
101+
return {items: []};
102+
}
103+
},
104+
[sendUserQueriesData],
105+
);
106+
107+
return {
108+
getCodeAssistSuggestions,
109+
onCompletionAccept,
110+
onCompletionDecline,
111+
onCompletionIgnore,
112+
prepareUserQueriesCache,
113+
};
114+
}

src/services/api/codeAssist.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,40 @@ const ideInfo = {
99
PluginFamily: 'ydb',
1010
PluginVersion: '0.2',
1111
};
12+
13+
interface AcceptSuggestionEvent {
14+
Accepted: {
15+
RequestId: string;
16+
Timestamp: number;
17+
AcceptedText: string;
18+
ConvertedText: string;
19+
};
20+
}
21+
interface DiscardSuggestionEvent {
22+
Discarded: {
23+
RequestId: string;
24+
Timestamp: number;
25+
DiscardReason: 'OnCancel';
26+
DiscardedText: string;
27+
CacheHitCount: number;
28+
};
29+
}
30+
interface IgnoreSuggestionEvent {
31+
Ignored: {
32+
RequestId: string;
33+
Timestamp: number;
34+
IgnoredText: string;
35+
};
36+
}
37+
38+
type OpenTab = {
39+
FileName: string;
40+
Text: string;
41+
};
42+
43+
export type TelemetryOpenTabs = OpenTab[];
44+
45+
export type TelemetryEvent = AcceptSuggestionEvent | DiscardSuggestionEvent | IgnoreSuggestionEvent;
1246
export class CodeAssistAPI extends BaseYdbAPI {
1347
getPath(path: string) {
1448
return `${CODE_ASSISTANT_BACKEND ?? ''}${path}`;
@@ -29,4 +63,23 @@ export class CodeAssistAPI extends BaseYdbAPI {
2963
},
3064
);
3165
}
66+
67+
sendCodeAssistTelemetry(data: TelemetryEvent) {
68+
return this.post('/code-assist-telemetry', data, null, {
69+
concurrentId: 'code-assist-telemetry',
70+
collectRequest: true,
71+
});
72+
}
73+
74+
sendCodeAssistOpenTabs(data: TelemetryOpenTabs) {
75+
return this.post(
76+
'/code-assist-telemetry',
77+
{OpenTabs: {Tabs: data, IdeInfo: ideInfo}},
78+
null,
79+
{
80+
concurrentId: 'code-assist-telemetry',
81+
collectRequest: false,
82+
},
83+
);
84+
}
3285
}

src/store/reducers/codeAssist/codeAssist.ts

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
1-
import type {PromptFile, Suggestions} from '@ydb-platform/monaco-ghost';
1+
import type {
2+
AcceptEvent,
3+
DeclineEvent,
4+
IgnoreEvent,
5+
PromptFile,
6+
Suggestions,
7+
} from '@ydb-platform/monaco-ghost';
28

9+
import type {TelemetryOpenTabs} from '../../../services/api/codeAssist';
310
import {api} from '../api';
411

512
export const codeAssistApi = api.injectEndpoints({
@@ -19,6 +26,92 @@ export const codeAssistApi = api.injectEndpoints({
1926
},
2027
providesTags: ['All'],
2128
}),
29+
30+
acceptSuggestion: builder.query({
31+
queryFn: async (event: AcceptEvent) => {
32+
try {
33+
if (window.api.codeAssist) {
34+
const data = await window.api.codeAssist.sendCodeAssistTelemetry({
35+
Accepted: {
36+
AcceptedText: event.acceptedText,
37+
ConvertedText: event.acceptedText,
38+
Timestamp: Date.now(),
39+
RequestId: event.requestId,
40+
},
41+
});
42+
return {data};
43+
} else {
44+
throw new Error('Method is not implemented.');
45+
}
46+
} catch (error) {
47+
return {error};
48+
}
49+
},
50+
providesTags: ['All'],
51+
}),
52+
53+
discardSuggestion: builder.query({
54+
queryFn: async (event: DeclineEvent) => {
55+
try {
56+
if (window.api.codeAssist) {
57+
const data = await window.api.codeAssist.sendCodeAssistTelemetry({
58+
Discarded: {
59+
RequestId: event.requestId,
60+
Timestamp: Date.now(),
61+
DiscardReason: 'OnCancel',
62+
DiscardedText: event.suggestionText,
63+
CacheHitCount: event.hitCount,
64+
},
65+
});
66+
return {data};
67+
} else {
68+
throw new Error('Method is not implemented.');
69+
}
70+
} catch (error) {
71+
return {error};
72+
}
73+
},
74+
providesTags: ['All'],
75+
}),
76+
77+
ignoreSuggestion: builder.query({
78+
queryFn: async (event: IgnoreEvent) => {
79+
try {
80+
if (window.api.codeAssist) {
81+
const data = await window.api.codeAssist.sendCodeAssistTelemetry({
82+
Ignored: {
83+
RequestId: event.requestId,
84+
Timestamp: Date.now(),
85+
IgnoredText: event.suggestionText,
86+
},
87+
});
88+
return {data};
89+
} else {
90+
throw new Error('Method is not implemented.');
91+
}
92+
} catch (error) {
93+
return {error};
94+
}
95+
},
96+
providesTags: ['All'],
97+
}),
98+
99+
sendUserQueriesData: builder.query({
100+
queryFn: async (userQueries: TelemetryOpenTabs) => {
101+
try {
102+
if (window.api.codeAssist) {
103+
const data =
104+
await window.api.codeAssist.sendCodeAssistOpenTabs(userQueries);
105+
return {data};
106+
} else {
107+
throw new Error('Method is not implemented.');
108+
}
109+
} catch (error) {
110+
return {error};
111+
}
112+
},
113+
providesTags: ['All'],
114+
}),
22115
}),
23116
overrideExisting: 'throw',
24117
});

0 commit comments

Comments
 (0)