Skip to content

Commit c9475c2

Browse files
committed
fix(ui): eliminate all unwanted suggestion popups while typing
- Disable quickSuggestions and suggestOnTriggerCharacters entirely - All suggestion triggering is now controlled by our cursor listener - Only auto-trigger for: blank lines (property suggestions) and short strings ≤2 chars (enum/path/evaluator browsing) - Typing in long strings never shows popups - contentJustChanged only flags small single-char edits as "typing"
1 parent 5a2ac6d commit c9475c2

1 file changed

Lines changed: 26 additions & 30 deletions

File tree

‎ui/src/core/page-components/agent-detail/modals/edit-control/json-editor-view.tsx‎

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ if (typeof document !== 'undefined') {
7474
const EDITOR_OPTIONS: import('monaco-editor').editor.IStandaloneEditorConstructionOptions =
7575
{
7676
automaticLayout: true,
77-
quickSuggestions: { other: true, strings: false, comments: false },
78-
suggestOnTriggerCharacters: true,
77+
quickSuggestions: false,
78+
suggestOnTriggerCharacters: false,
7979
wordBasedSuggestions: 'off',
8080
suggest: {
8181
showWords: false,
@@ -146,34 +146,33 @@ function tryFormat(text: string): string | null {
146146
function shouldAutoTriggerSuggest(
147147
line: string | undefined,
148148
column: number,
149-
hasDomainSuggestions: () => boolean
149+
skipStringTrigger: boolean
150150
): boolean {
151151
if (!line) return false;
152152
const beforeCursor = line.substring(0, column - 1);
153153
const afterCursor = line.substring(column - 1);
154154

155-
// Blank / comma-only line — likely inside an object needing a property
155+
// Blank / comma-only line — always trigger (even after Enter)
156156
if (/^\s*,?\s*$/.test(line)) return true;
157157

158-
// Check if inside a string
158+
// Don't trigger string suggestions after typing
159+
if (skipStringTrigger) return false;
160+
161+
// Check if inside a string value (not a property key)
159162
const quotesBefore = beforeCursor.split('"').length - 1;
160163
const isInString = quotesBefore % 2 === 1 && /^[^"]*"/.test(afterCursor);
161164
if (!isInString) return false;
162-
163-
// Don't trigger on property keys (have ":" after closing quote)
164165
if (/^\s*:/.test(afterCursor.replace(/^[^"]*"/, ''))) return false;
165166

166-
// Short strings: always trigger
167+
// Only auto-trigger for short strings (≤ 2 chars) — user is browsing options.
168+
// For longer strings, user can Ctrl+Space manually.
167169
const openIdx = beforeCursor.lastIndexOf('"');
168170
const closeIdx = afterCursor.indexOf('"');
169171
const contentLen =
170172
openIdx >= 0 && closeIdx >= 0
171173
? beforeCursor.length - openIdx - 1 + closeIdx
172174
: 999;
173-
if (contentLen <= 2) return true;
174-
175-
// Longer strings: only if we have domain-specific suggestions
176-
return hasDomainSuggestions();
175+
return contentLen <= 2;
177176
}
178177

179178
// ---------------------------------------------------------------------------
@@ -425,20 +424,22 @@ export const JsonEditorView = ({
425424
const editor = editorRef.current;
426425
if (!editor || !mounted) return;
427426

428-
// Track content changes to distinguish typing (content+cursor change)
429-
// from navigation (cursor change only). Don't auto-trigger after typing.
427+
// Track content changes to suppress string-value auto-trigger after typing.
428+
// Blank line triggers still fire (Enter creates a new line → want suggestions).
430429
let contentJustChanged = false;
431-
const contentDisposable = editor.onDidChangeModelContent(() => {
432-
contentJustChanged = true;
430+
const contentDisposable = editor.onDidChangeModelContent((e) => {
431+
// Only flag as "typing" for small single-char edits, not large replacements
432+
// (setValue, code actions, reformat). This prevents suppressing auto-trigger
433+
// after programmatic content changes.
434+
const isSmallEdit =
435+
e.changes.length === 1 &&
436+
e.changes[0].text.length <= 2 &&
437+
!e.changes[0].text.includes('\n');
438+
contentJustChanged = isSmallEdit;
433439
});
434440

435441
let timeout: number | null = null;
436442
const disposable = editor.onDidChangeCursorPosition(() => {
437-
if (contentJustChanged) {
438-
contentJustChanged = false;
439-
return;
440-
}
441-
442443
if (timeout) window.clearTimeout(timeout);
443444
timeout = window.setTimeout(() => {
444445
try {
@@ -448,18 +449,13 @@ export const JsonEditorView = ({
448449
if (pos.lineNumber < 1 || pos.lineNumber > model.getLineCount())
449450
return;
450451

452+
const wasTyping = contentJustChanged;
453+
contentJustChanged = false;
454+
451455
const trigger = shouldAutoTriggerSuggest(
452456
model.getLineContent(pos.lineNumber),
453457
pos.column,
454-
() =>
455-
monacoRef.current
456-
? getJsonEditorCompletionItems(
457-
monacoRef.current,
458-
model,
459-
pos,
460-
autocompleteContext
461-
).length > 0
462-
: false
458+
wasTyping
463459
);
464460
if (trigger) {
465461
editor.trigger('cursor', 'editor.action.triggerSuggest', {});

0 commit comments

Comments
 (0)