Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: interactive input handle api adds selection parameter #4346

Merged
merged 2 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/ai-native/src/browser/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
MaybePromise,
MergeConflictEditorMode,
} from '@opensumi/ide-core-common';
import { ICodeEditor, IRange, ITextModel, NewSymbolNamesProvider, Position } from '@opensumi/ide-monaco';
import { ICodeEditor, IRange, ISelection, ITextModel, NewSymbolNamesProvider, Position } from '@opensumi/ide-monaco';
import { SumiReadableStream } from '@opensumi/ide-utils/lib/stream';
import { IMarker } from '@opensumi/monaco-editor-core/esm/vs/platform/markers/common/markers';

Expand Down Expand Up @@ -44,7 +44,7 @@ interface IBaseInlineChatHandler<T extends any[]> {

export type IEditorInlineChatHandler = IBaseInlineChatHandler<[editor: ICodeEditor, token: CancellationToken]>;
export type IInteractiveInputHandler = IBaseInlineChatHandler<
[editor: ICodeEditor, value: string, token: CancellationToken]
[editor: ICodeEditor, selection: ISelection, value: string, token: CancellationToken]
>;

export enum ERunStrategy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,10 +383,14 @@ export class LiveInlineDiffPreviewer extends BaseInlineDiffPreviewer<InlineStrea
const firstRemovedWidgetLineNumber = firstRemovedWidget.getLastPosition()?.lineNumber;
if (firstRemovedWidgetLineNumber <= lineNumber) {
const lineHeight = this.inlineContentWidget.getLineHeight();
const len = firstRemovedWidget.height;
const len = firstRemovedWidget.height + 1;
this.inlineContentWidget.setOffsetTop(-lineHeight * len - 4);
} else {
this.inlineContentWidget.setOffsetTop(0);
}
}
} else {
this.inlineContentWidget.setOffsetTop(0);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ export class InlineInputController extends BaseAIMonacoEditorController {

private inputValue: ISettableObservable<string>;
private modelChangeObs: IObservable<monaco.editor.ITextModel, unknown>;
private inlineInputWidgetStore = new Map<
private inlineInputWidgetStore: Map<
string,
InlineInputWidgetStoreInEmptyLine | InlineInputWidgetStoreInSelection | null
>();
>;

mount(): IDisposable {
this.inputDisposable = new Disposable();
Expand All @@ -85,6 +85,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
this.monacoEditor.onDidChangeModel,
() => this.monacoEditor.getModel()!,
);
this.inlineInputWidgetStore = new Map();

this.featureDisposable.addDispose(
/**
Expand Down Expand Up @@ -320,16 +321,17 @@ export class InlineInputController extends BaseAIMonacoEditorController {
inlineInputWidget.launchChatStatus(EInlineChatStatus.THINKING);

const strategy = await this.inlineInputService.getInteractiveInputStrategyHandler()(monacoEditor, value);
const selection = monaco.Selection.fromPositions(position);

if (strategy === ERunStrategy.EXECUTE && handler.execute) {
handler.execute(monacoEditor, value, this.token);
handler.execute(monacoEditor, selection, value, this.token);
inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
this.hideInput();
return;
}

if (strategy === ERunStrategy.PREVIEW && handler.providePreviewStrategy) {
const previewResponse = await handler.providePreviewStrategy(monacoEditor, value, this.token);
const previewResponse = await handler.providePreviewStrategy(monacoEditor, selection, value, this.token);

if (CancelResponse.is(previewResponse)) {
inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
Expand Down Expand Up @@ -365,7 +367,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {
}),
controller.onError((error) => {
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
inlineInputWidget.launchChatStatus(EInlineChatStatus.ERROR);
inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
}),
controller.onAbort(() => {
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
Expand Down Expand Up @@ -399,9 +401,6 @@ export class InlineInputController extends BaseAIMonacoEditorController {
return;
}

this.inputValue.set(defaultValue || '', undefined);
this.inlineInputWidgetStore.set(model.id, new InlineInputWidgetStoreInSelection(selection, defaultValue));

const decorationsCollection = monacoEditor.createDecorationsCollection();
decorationsCollection.set([
{
Expand All @@ -419,9 +418,16 @@ export class InlineInputController extends BaseAIMonacoEditorController {
}),
},
]);
const decorationSelection = monaco.Selection.fromRange(
decorationsCollection.getRange(0)!,
selection.getDirection(),
);

this.inputValue.set(defaultValue || '', undefined);
this.inlineInputWidgetStore.set(model.id, new InlineInputWidgetStoreInSelection(decorationSelection, defaultValue));

const inlineInputWidget = this.injector.get(InlineInputWidget, [monacoEditor, this.inputValue.get()]);
inlineInputWidget.show({ selection });
inlineInputWidget.show({ selection: decorationSelection });

this.aiNativeContextKey.inlineInputWidgetIsVisible.set(true);
this.inlineDiffController.destroyPreviewer(monacoEditor.getModel()?.uri.toString());
Expand Down Expand Up @@ -459,7 +465,6 @@ export class InlineInputController extends BaseAIMonacoEditorController {
this.inputDisposable.addDispose(
inlineInputWidget.onSend(async (value) => {
monacoEditor.focus();
decorationsCollection.clear();

const handler = this.inlineInputService.getInteractiveInputHandler();

Expand All @@ -471,16 +476,18 @@ export class InlineInputController extends BaseAIMonacoEditorController {

const strategy = await this.inlineInputService.getInteractiveInputStrategyHandler()(monacoEditor, value);

const crossSelection = selection
.setStartPosition(selection.startLineNumber, 1)
.setEndPosition(selection.endLineNumber, monacoEditor.getModel()!.getLineMaxColumn(selection.endLineNumber));

if (strategy === ERunStrategy.PREVIEW && handler.providePreviewStrategy) {
const previewResponse = await handler.providePreviewStrategy(monacoEditor, value, this.token);
const previewResponse = await handler.providePreviewStrategy(
monacoEditor,
decorationSelection,
value,
this.token,
);

if (CancelResponse.is(previewResponse)) {
inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
this.hideInput();
decorationsCollection.clear();
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
return;
}

Expand All @@ -489,19 +496,22 @@ export class InlineInputController extends BaseAIMonacoEditorController {

this.inputDisposable.addDispose([
chatResponse.onData((data) => {
decorationsCollection.clear();
if (ReplyResponse.is(data)) {
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(true);
}
}),
chatResponse.onError((error) => {
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
inlineInputWidget.launchChatStatus(EInlineChatStatus.ERROR);
inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
}),
chatResponse.onAbort(() => {
decorationsCollection.clear();
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
}),
chatResponse.onEnd(() => {
decorationsCollection.clear();
this.aiNativeContextKey.inlineInputWidgetIsStreaming.set(false);
inlineInputWidget.launchChatStatus(EInlineChatStatus.DONE);
}),
Expand All @@ -510,12 +520,14 @@ export class InlineInputController extends BaseAIMonacoEditorController {
chatResponse.listen();

const diffPreviewer = this.inlineDiffController.showPreviewerByStream(monacoEditor, {
crossSelection,
crossSelection: decorationSelection,
chatResponse,
});

diffPreviewer.mount(inlineInputWidget);
}
} else {
decorationsCollection.clear();
inlineInputWidget.launchChatStatus(EInlineChatStatus.READY);
this.hideInput();
}
Expand All @@ -529,7 +541,7 @@ export class InlineInputController extends BaseAIMonacoEditorController {

if (kind === EResultKind.REGENERATE) {
requestAnimationFrame(() => {
this.showInputInSelection(selection, monacoEditor, this.inputValue.get());
this.showInputInSelection(decorationSelection, monacoEditor, this.inputValue.get());
});
}
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ export class InlineStreamDiffHandler extends Disposable implements IInlineDiffPr
preRemovedLen += removedLinesOriginalRange.length - addedRange.length;
}

this.livePreviewDiffDecorationModel.touchRemovedWidget(states);
this.livePreviewDiffDecorationModel.touchRemovedWidget(states, () => {
this._onDidEditChange.fire();
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,12 +676,13 @@ export class LivePreviewDiffDecorationModel extends Disposable {
this.recordPartialEditWidgetWithAddedDec();
}

public touchRemovedWidget(states: IRemovedWidgetState[]) {
public touchRemovedWidget(states: IRemovedWidgetState[], cb?: () => void) {
const run = () => {
this.clearRemovedWidgets();
states.forEach(({ textLines, position }) => {
this.showRemovedWidgetByLineNumber(position.lineNumber, textLines, {});
});
cb?.();
};

if (this.options.renderRemovedWidgetImmediately) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
z-index: 1;
left: 18px;
right: 0;
height: 100%;
top: 5px;
bottom: 5px;
border-radius: 4px;
background-color: var(--kt-input-disableBackground);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export class MainThreadChatAgents implements IMainThreadChatAgents {
const d = this.inlineChatFeatureRegistry.registerInteractiveInput(
{ handleStrategy: () => ERunStrategy.PREVIEW },
{
providePreviewStrategy: async (editor, value, token) => {
providePreviewStrategy: async (editor, selection, value, token) => {
const controller = new InlineChatController({ enableCodeblockRender: !!metadata.enableCodeblockRender });
const request = this.chatInternalService!.createRequest(value, name)!;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
ReplyResponse,
getDebugLogger,
} from '@opensumi/ide-core-common';
import { ICodeEditor, NewSymbolName, NewSymbolNameTag, Range } from '@opensumi/ide-monaco';
import { ICodeEditor, NewSymbolName, NewSymbolNameTag, Range, Selection } from '@opensumi/ide-monaco';
import { MarkdownString } from '@opensumi/monaco-editor-core/esm/vs/base/common/htmlContent';

import { SlashCommand } from './SlashCommand';
Expand Down Expand Up @@ -102,8 +102,8 @@ export class AINativeContribution implements AINativeCoreContribution {
},
{
execute: async (editor, value, token) => {},
providePreviewStrategy: async (editor, value, token) => {
const crossCode = this.getCrossCode(editor);
providePreviewStrategy: async (editor, selection, value, token) => {
const crossCode = editor.getModel()?.getValueInRange(Selection.liftSelection(selection));
const prompt = `Comment the code: \`\`\`\n ${crossCode}\`\`\`. It is required to return only the code results without explanation.`;
const controller = new InlineChatController({ enableCodeblockRender: true });
const stream = await this.aiBackService.requestStream(prompt, {}, token);
Expand Down
Loading