@opensumi/ide-ai-native 3.1.2-next-1718960862.0 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/lib/browser/ai-core.contribution.d.ts +0 -1
  2. package/lib/browser/ai-core.contribution.d.ts.map +1 -1
  3. package/lib/browser/ai-core.contribution.js +11 -26
  4. package/lib/browser/ai-core.contribution.js.map +1 -1
  5. package/lib/browser/ai-editor.contribution.d.ts +1 -10
  6. package/lib/browser/ai-editor.contribution.d.ts.map +1 -1
  7. package/lib/browser/ai-editor.contribution.js +16 -81
  8. package/lib/browser/ai-editor.contribution.js.map +1 -1
  9. package/lib/browser/contextkey/ai-native.contextkey.service.d.ts +0 -2
  10. package/lib/browser/contextkey/ai-native.contextkey.service.d.ts.map +1 -1
  11. package/lib/browser/contextkey/ai-native.contextkey.service.js +0 -2
  12. package/lib/browser/contextkey/ai-native.contextkey.service.js.map +1 -1
  13. package/lib/browser/contrib/code-action/code-action.handler.d.ts.map +1 -1
  14. package/lib/browser/contrib/code-action/code-action.handler.js +0 -5
  15. package/lib/browser/contrib/code-action/code-action.handler.js.map +1 -1
  16. package/lib/browser/contrib/inline-completions/completeProvider.d.ts +0 -2
  17. package/lib/browser/contrib/inline-completions/completeProvider.d.ts.map +1 -1
  18. package/lib/browser/contrib/inline-completions/completeProvider.js +9 -18
  19. package/lib/browser/contrib/inline-completions/completeProvider.js.map +1 -1
  20. package/lib/browser/contrib/inline-completions/inline-completions.handler.d.ts +4 -0
  21. package/lib/browser/contrib/inline-completions/inline-completions.handler.d.ts.map +1 -1
  22. package/lib/browser/contrib/inline-completions/inline-completions.handler.js +51 -11
  23. package/lib/browser/contrib/inline-completions/inline-completions.handler.js.map +1 -1
  24. package/lib/browser/contrib/inline-completions/model/competionModel.d.ts +1 -0
  25. package/lib/browser/contrib/inline-completions/model/competionModel.d.ts.map +1 -1
  26. package/lib/browser/contrib/inline-completions/promptCache.d.ts +3 -1
  27. package/lib/browser/contrib/inline-completions/promptCache.d.ts.map +1 -1
  28. package/lib/browser/contrib/inline-completions/promptCache.js.map +1 -1
  29. package/lib/browser/contrib/inline-completions/service/ai-completions.service.d.ts +2 -5
  30. package/lib/browser/contrib/inline-completions/service/ai-completions.service.d.ts.map +1 -1
  31. package/lib/browser/contrib/inline-completions/service/ai-completions.service.js +9 -11
  32. package/lib/browser/contrib/inline-completions/service/ai-completions.service.js.map +1 -1
  33. package/lib/browser/layout/ai-layout.js +1 -1
  34. package/lib/browser/layout/ai-layout.js.map +1 -1
  35. package/lib/browser/layout/tabbar.view.d.ts.map +1 -1
  36. package/lib/browser/layout/tabbar.view.js +2 -2
  37. package/lib/browser/layout/tabbar.view.js.map +1 -1
  38. package/lib/browser/types.d.ts +4 -26
  39. package/lib/browser/types.d.ts.map +1 -1
  40. package/lib/browser/types.js +1 -5
  41. package/lib/browser/types.js.map +1 -1
  42. package/lib/browser/widget/inline-chat/inline-chat-controller.js +1 -1
  43. package/lib/browser/widget/inline-chat/inline-chat-controller.js.map +1 -1
  44. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.d.ts +1 -6
  45. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.d.ts.map +1 -1
  46. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.js +6 -29
  47. package/lib/browser/widget/inline-chat/inline-chat.feature.registry.js.map +1 -1
  48. package/lib/browser/widget/inline-chat/inline-chat.handler.d.ts +1 -0
  49. package/lib/browser/widget/inline-chat/inline-chat.handler.d.ts.map +1 -1
  50. package/lib/browser/widget/inline-chat/inline-chat.handler.js +26 -27
  51. package/lib/browser/widget/inline-chat/inline-chat.handler.js.map +1 -1
  52. package/lib/browser/widget/inline-chat/inline-chat.module.less +2 -2
  53. package/lib/browser/widget/inline-chat/inline-chat.service.d.ts +14 -6
  54. package/lib/browser/widget/inline-chat/inline-chat.service.d.ts.map +1 -1
  55. package/lib/browser/widget/inline-chat/inline-chat.service.js +25 -0
  56. package/lib/browser/widget/inline-chat/inline-chat.service.js.map +1 -1
  57. package/lib/browser/widget/inline-chat/inline-content-widget.d.ts +18 -15
  58. package/lib/browser/widget/inline-chat/inline-content-widget.d.ts.map +1 -1
  59. package/lib/browser/widget/inline-chat/inline-content-widget.js +54 -41
  60. package/lib/browser/widget/inline-chat/inline-content-widget.js.map +1 -1
  61. package/lib/browser/widget/inline-diff/inline-diff-widget.d.ts +1 -1
  62. package/lib/browser/widget/inline-diff/inline-diff-widget.d.ts.map +1 -1
  63. package/lib/browser/widget/inline-diff/inline-diff-widget.js.map +1 -1
  64. package/lib/browser/widget/light-bulb/index.d.ts.map +1 -1
  65. package/lib/browser/widget/light-bulb/index.js +3 -2
  66. package/lib/browser/widget/light-bulb/index.js.map +1 -1
  67. package/package.json +19 -19
  68. package/src/browser/ai-core.contribution.ts +13 -29
  69. package/src/browser/ai-editor.contribution.ts +29 -104
  70. package/src/browser/contextkey/ai-native.contextkey.service.ts +1 -10
  71. package/src/browser/contrib/code-action/code-action.handler.ts +0 -6
  72. package/src/browser/contrib/inline-completions/completeProvider.ts +21 -27
  73. package/src/browser/contrib/inline-completions/inline-completions.handler.ts +57 -13
  74. package/src/browser/contrib/inline-completions/model/competionModel.ts +1 -0
  75. package/src/browser/contrib/inline-completions/promptCache.ts +1 -1
  76. package/src/browser/contrib/inline-completions/service/ai-completions.service.ts +9 -18
  77. package/src/browser/layout/ai-layout.tsx +1 -1
  78. package/src/browser/layout/tabbar.view.tsx +1 -2
  79. package/src/browser/types.ts +3 -25
  80. package/src/browser/widget/inline-chat/inline-chat-controller.ts +1 -1
  81. package/src/browser/widget/inline-chat/inline-chat.feature.registry.ts +8 -34
  82. package/src/browser/widget/inline-chat/inline-chat.handler.ts +36 -35
  83. package/src/browser/widget/inline-chat/inline-chat.module.less +2 -2
  84. package/src/browser/widget/inline-chat/inline-chat.service.ts +33 -8
  85. package/src/browser/widget/inline-chat/inline-content-widget.tsx +66 -65
  86. package/src/browser/widget/inline-diff/inline-diff-widget.tsx +2 -1
  87. package/src/browser/widget/light-bulb/index.ts +2 -1
  88. package/lib/browser/widget/inline-actions/result-items/index.d.ts +0 -7
  89. package/lib/browser/widget/inline-actions/result-items/index.d.ts.map +0 -1
  90. package/lib/browser/widget/inline-actions/result-items/index.js +0 -31
  91. package/lib/browser/widget/inline-actions/result-items/index.js.map +0 -1
  92. package/lib/browser/widget/inline-hint/inline-hint-line-widget.d.ts +0 -11
  93. package/lib/browser/widget/inline-hint/inline-hint-line-widget.d.ts.map +0 -1
  94. package/lib/browser/widget/inline-hint/inline-hint-line-widget.js +0 -43
  95. package/lib/browser/widget/inline-hint/inline-hint-line-widget.js.map +0 -1
  96. package/lib/browser/widget/inline-hint/inline-hint.handler.d.ts +0 -10
  97. package/lib/browser/widget/inline-hint/inline-hint.handler.d.ts.map +0 -1
  98. package/lib/browser/widget/inline-hint/inline-hint.handler.js +0 -96
  99. package/lib/browser/widget/inline-hint/inline-hint.handler.js.map +0 -1
  100. package/lib/browser/widget/inline-hint/inline-hint.module.less +0 -15
  101. package/lib/browser/widget/inline-input/inline-input-widget.d.ts +0 -11
  102. package/lib/browser/widget/inline-input/inline-input-widget.d.ts.map +0 -1
  103. package/lib/browser/widget/inline-input/inline-input-widget.js +0 -77
  104. package/lib/browser/widget/inline-input/inline-input-widget.js.map +0 -1
  105. package/lib/browser/widget/inline-input/inline-input.handler.d.ts +0 -14
  106. package/lib/browser/widget/inline-input/inline-input.handler.d.ts.map +0 -1
  107. package/lib/browser/widget/inline-input/inline-input.handler.js +0 -198
  108. package/lib/browser/widget/inline-input/inline-input.handler.js.map +0 -1
  109. package/lib/browser/widget/inline-input/inline-input.module.less +0 -7
  110. package/lib/browser/widget/inline-input/inline-input.service.d.ts +0 -11
  111. package/lib/browser/widget/inline-input/inline-input.service.d.ts.map +0 -1
  112. package/lib/browser/widget/inline-input/inline-input.service.js +0 -29
  113. package/lib/browser/widget/inline-input/inline-input.service.js.map +0 -1
  114. package/lib/browser/widget/internal.type.d.ts +0 -5
  115. package/lib/browser/widget/internal.type.d.ts.map +0 -1
  116. package/lib/browser/widget/internal.type.js +0 -8
  117. package/lib/browser/widget/internal.type.js.map +0 -1
  118. package/src/browser/widget/inline-actions/result-items/index.tsx +0 -40
  119. package/src/browser/widget/inline-hint/inline-hint-line-widget.tsx +0 -41
  120. package/src/browser/widget/inline-hint/inline-hint.handler.ts +0 -127
  121. package/src/browser/widget/inline-hint/inline-hint.module.less +0 -15
  122. package/src/browser/widget/inline-input/inline-input-widget.tsx +0 -122
  123. package/src/browser/widget/inline-input/inline-input.handler.ts +0 -276
  124. package/src/browser/widget/inline-input/inline-input.module.less +0 -7
  125. package/src/browser/widget/inline-input/inline-input.service.ts +0 -25
  126. package/src/browser/widget/internal.type.ts +0 -4
@@ -1,40 +0,0 @@
1
- import React, { useMemo } from 'react';
2
-
3
- import { ContentWidgetContainerPanel } from '@opensumi/ide-core-browser/lib/components/ai-native/content-widget/containerPanel';
4
- import { AIInlineResult } from '@opensumi/ide-core-browser/lib/components/ai-native/index';
5
- import { localize } from '@opensumi/ide-core-common';
6
-
7
- import { EResultKind } from '../../inline-chat/inline-chat.service';
8
-
9
- export interface IInlineResultActionProps {
10
- onResultClick: (k: EResultKind) => void;
11
- }
12
-
13
- export const InlineResultAction = ({ onResultClick }: IInlineResultActionProps) => {
14
- const iconResultItems = useMemo(
15
- () => [
16
- {
17
- icon: 'check',
18
- text: localize('aiNative.inline.chat.operate.check.title'),
19
- onClick: () => onResultClick(EResultKind.ACCEPT),
20
- },
21
- {
22
- icon: 'discard',
23
- text: localize('aiNative.operate.discard.title'),
24
- onClick: () => onResultClick(EResultKind.DISCARD),
25
- },
26
- {
27
- icon: 'afresh',
28
- text: localize('aiNative.operate.afresh.title'),
29
- onClick: () => onResultClick(EResultKind.REGENERATE),
30
- },
31
- ],
32
- [onResultClick],
33
- );
34
-
35
- return (
36
- <ContentWidgetContainerPanel style={{ transform: 'translateY(4px)' }}>
37
- <AIInlineResult iconItems={iconResultItems} />
38
- </ContentWidgetContainerPanel>
39
- );
40
- };
@@ -1,41 +0,0 @@
1
- import React, { ReactNode } from 'react';
2
-
3
- import { Autowired, Injectable } from '@opensumi/di';
4
- import { KeybindingRegistry } from '@opensumi/ide-core-browser';
5
- import { AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE } from '@opensumi/ide-core-browser/lib/ai-native/command';
6
- import { AIInlineHintLineContentWidgetId, formatLocalize } from '@opensumi/ide-core-common';
7
- import { ReactInlineContentWidget } from '@opensumi/ide-monaco/lib/browser/ai-native/BaseInlineContentWidget';
8
- import { ContentWidgetPositionPreference } from '@opensumi/ide-monaco/lib/browser/monaco-exports/editor';
9
-
10
- import styles from './inline-hint.module.less';
11
-
12
- @Injectable({ multiple: true })
13
- export class InlineHintLineWidget extends ReactInlineContentWidget {
14
- positionPreference = [ContentWidgetPositionPreference.EXACT];
15
-
16
- @Autowired(KeybindingRegistry)
17
- private readonly keybindingRegistry: KeybindingRegistry;
18
-
19
- override id(): string {
20
- return AIInlineHintLineContentWidgetId;
21
- }
22
-
23
- private getSequenceKeyString() {
24
- const keybindings = this.keybindingRegistry.getKeybindingsForCommand(AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE.id);
25
- const resolved = keybindings[0]?.resolved;
26
- if (!resolved) {
27
- return '';
28
- }
29
- return this.keybindingRegistry.acceleratorForSequence(resolved, '+');
30
- }
31
-
32
- override renderView(): ReactNode {
33
- return (
34
- <div className={styles.hint_line_widget}>
35
- <span className={styles.text}>
36
- {formatLocalize('aiNative.inline.hint.widget.placeholder', this.getSequenceKeyString())}
37
- </span>
38
- </div>
39
- );
40
- }
41
- }
@@ -1,127 +0,0 @@
1
- import { Autowired, INJECTOR_TOKEN, Injectable, Injector } from '@opensumi/di';
2
- import { KeybindingRegistry, KeybindingScope } from '@opensumi/ide-core-browser';
3
- import { AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE } from '@opensumi/ide-core-browser/lib/ai-native/command';
4
- import { InlineHintWidgetIsVisible } from '@opensumi/ide-core-browser/lib/contextkey/ai-native';
5
- import { Disposable, IDisposable } from '@opensumi/ide-core-common';
6
- import { IEditor } from '@opensumi/ide-editor/lib/browser';
7
- import * as monaco from '@opensumi/ide-monaco';
8
- import { Position } from '@opensumi/ide-monaco';
9
- import { empty } from '@opensumi/ide-utils/lib/strings';
10
-
11
- import { AINativeContextKey } from '../../contextkey/ai-native.contextkey.service';
12
- import { AICompletionsService } from '../../contrib/inline-completions/service/ai-completions.service';
13
- import { InlineInputPreviewDecorationID } from '../internal.type';
14
-
15
- import { InlineHintLineWidget } from './inline-hint-line-widget';
16
-
17
- @Injectable()
18
- export class InlineHintHandler extends Disposable {
19
- @Autowired(INJECTOR_TOKEN)
20
- private readonly injector: Injector;
21
-
22
- @Autowired(AICompletionsService)
23
- private readonly inlineCompletionsService: AICompletionsService;
24
-
25
- @Autowired(KeybindingRegistry)
26
- private readonly keybindingRegistry: KeybindingRegistry;
27
-
28
- private aiNativeContextKey: AINativeContextKey;
29
-
30
- public registerHintLineFeature(editor: IEditor): IDisposable {
31
- const { monacoEditor } = editor;
32
- const hintDisposable = new Disposable();
33
- this.aiNativeContextKey = this.injector.get(AINativeContextKey, [editor.monacoEditor.contextKeyService]);
34
-
35
- let currentVisiblePosition: Position | undefined;
36
-
37
- const hideHint = () => {
38
- hintDisposable.dispose();
39
- };
40
-
41
- const showHint = (position: monaco.Position) => {
42
- const model = monacoEditor.getModel();
43
- if (!model) {
44
- return;
45
- }
46
-
47
- if (this.inlineCompletionsService.isVisibleCompletion) {
48
- return;
49
- }
50
-
51
- const content = model.getLineContent(position.lineNumber);
52
- const decorations = model.getLineDecorations(position.lineNumber);
53
-
54
- const isEmpty = content?.trim() === empty;
55
- const isEmptySelection = monacoEditor.getSelection()?.isEmpty();
56
- const hasPreviewDecoration = decorations.some(
57
- (dec) => dec.options.description === InlineInputPreviewDecorationID,
58
- );
59
-
60
- if (isEmpty && isEmptySelection && !hasPreviewDecoration) {
61
- const inlineHintLineWidget = this.injector.get(InlineHintLineWidget, [monacoEditor]);
62
- inlineHintLineWidget.show({ position });
63
- currentVisiblePosition = position;
64
-
65
- this.aiNativeContextKey.inlineHintWidgetIsVisible.set(true);
66
-
67
- hintDisposable.addDispose(
68
- inlineHintLineWidget.onDispose(() => {
69
- currentVisiblePosition = undefined;
70
- this.aiNativeContextKey.inlineHintWidgetIsVisible.set(false);
71
- }),
72
- );
73
-
74
- hintDisposable.addDispose(inlineHintLineWidget);
75
- }
76
- };
77
-
78
- this.addDispose(
79
- monacoEditor.onDidChangeCursorPosition((e: monaco.editor.ICursorPositionChangedEvent) => {
80
- hideHint();
81
- showHint(e.position);
82
- }),
83
- );
84
-
85
- this.addDispose(
86
- monacoEditor.onDidFocusEditorWidget(() => {
87
- const currentPosition = monacoEditor.getPosition();
88
-
89
- if (currentPosition) {
90
- hideHint();
91
- showHint(currentPosition);
92
- }
93
- }),
94
- );
95
-
96
- this.addDispose(
97
- monacoEditor.onDidBlurEditorWidget(() => {
98
- hideHint();
99
- }),
100
- );
101
-
102
- this.addDispose(
103
- this.inlineCompletionsService.onVisibleCompletion((v) => {
104
- if (v) {
105
- hideHint();
106
- }
107
- }),
108
- );
109
-
110
- this.addDispose(hintDisposable);
111
-
112
- this.addDispose(
113
- this.keybindingRegistry.registerKeybinding(
114
- {
115
- command: AI_INLINE_CHAT_INTERACTIVE_INPUT_VISIBLE.id,
116
- keybinding: 'ctrlcmd+k',
117
- args: () => currentVisiblePosition,
118
- priority: 0,
119
- when: `editorTextFocus && ${InlineHintWidgetIsVisible.raw}`,
120
- },
121
- KeybindingScope.USER,
122
- ),
123
- );
124
-
125
- return this;
126
- }
127
- }
@@ -1,15 +0,0 @@
1
- .hint_line_widget {
2
- width: max-content;
3
- height: 100%;
4
- padding-left: 12px;
5
- user-select: none;
6
- pointer-events: none;
7
- position: absolute;
8
-
9
- .text {
10
- color: var(--input-placeholderForeground) !important;
11
- opacity: 0.5;
12
- user-select: none;
13
- pointer-events: none;
14
- }
15
- }
@@ -1,122 +0,0 @@
1
- import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
2
-
3
- import { Autowired, Injectable } from '@opensumi/di';
4
- import { AIAction, InteractiveInput } from '@opensumi/ide-core-browser/lib/components/ai-native/index';
5
- import { AIInlineInputChatContentWidgetId, Disposable, Event, localize } from '@opensumi/ide-core-common';
6
- import { ContentWidgetPositionPreference } from '@opensumi/ide-monaco/lib/browser/monaco-exports/editor';
7
-
8
- import { InlineResultAction } from '../inline-actions/result-items/index';
9
- import { EInlineChatStatus, EResultKind } from '../inline-chat/inline-chat.service';
10
- import { AIInlineContentWidget } from '../inline-chat/inline-content-widget';
11
-
12
- import styles from './inline-input.module.less';
13
- import { InlineInputChatService } from './inline-input.service';
14
-
15
- interface IInlineInputWidgetRenderProps {
16
- onLayoutChange: (height: number) => void;
17
- onClose?: () => void;
18
- onInteractiveInputSend?: (value: string) => void;
19
- onChatStatus: Event<EInlineChatStatus>;
20
- onResultClick: (k: EResultKind) => void;
21
- }
22
-
23
- const InlineInputWidgetRender = (props: IInlineInputWidgetRenderProps) => {
24
- const { onClose, onInteractiveInputSend, onLayoutChange, onChatStatus, onResultClick } = props;
25
- const [status, setStatus] = useState<EInlineChatStatus>(EInlineChatStatus.READY);
26
- const [inputValue, setInputValue] = useState<string>('');
27
-
28
- useEffect(() => {
29
- const dis = new Disposable();
30
- dis.addDispose(onChatStatus((s) => setStatus(s)));
31
-
32
- return () => {
33
- dis.dispose();
34
- };
35
- }, [onChatStatus]);
36
-
37
- const isLoading = useMemo(() => status === EInlineChatStatus.THINKING, [status]);
38
- const isDone = useMemo(() => status === EInlineChatStatus.DONE, [status]);
39
- const isError = useMemo(() => status === EInlineChatStatus.ERROR, [status]);
40
-
41
- const handleClose = useCallback(() => {
42
- onClose?.();
43
- }, [onClose]);
44
-
45
- const handleInteractiveInputSend = useCallback(
46
- (value: string) => {
47
- onInteractiveInputSend?.(value);
48
- },
49
- [onInteractiveInputSend],
50
- );
51
-
52
- const handleValueChange = useCallback((value) => {
53
- setInputValue(value);
54
- }, []);
55
-
56
- if (isError) {
57
- return null;
58
- }
59
-
60
- if (isDone) {
61
- return <InlineResultAction onResultClick={onResultClick} />;
62
- }
63
-
64
- return (
65
- <AIAction
66
- loadingShowOperation
67
- onClose={handleClose}
68
- loading={isLoading}
69
- customOperationRender={
70
- <InteractiveInput
71
- autoFocus
72
- onHeightChange={(height) => onLayoutChange(height)}
73
- size='small'
74
- placeholder={localize('aiNative.inline.chat.input.placeholder.default')}
75
- width={320}
76
- value={inputValue}
77
- onValueChange={handleValueChange}
78
- disabled={isLoading}
79
- onSend={handleInteractiveInputSend}
80
- />
81
- }
82
- />
83
- );
84
- };
85
-
86
- @Injectable({ multiple: true })
87
- export class InlineInputChatWidget extends AIInlineContentWidget {
88
- @Autowired(InlineInputChatService)
89
- private inlineInputChatService: InlineInputChatService;
90
-
91
- positionPreference = [ContentWidgetPositionPreference.ABOVE];
92
-
93
- override dispose(): void {
94
- super.dispose();
95
- this.inlineInputChatService.hide();
96
- }
97
-
98
- override id(): string {
99
- return AIInlineInputChatContentWidgetId;
100
- }
101
-
102
- override renderView(): ReactNode {
103
- return (
104
- <div className={styles.input_wrapper}>
105
- <InlineInputWidgetRender
106
- onClose={() => this.dispose()}
107
- onChatStatus={this.onStatusChange.bind(this)}
108
- onLayoutChange={() => {
109
- this.editor.layoutContentWidget(this);
110
- }}
111
- onInteractiveInputSend={(value) => {
112
- this.launchChatStatus(EInlineChatStatus.THINKING);
113
- this._onInteractiveInputValue.fire(value);
114
- }}
115
- onResultClick={(k: EResultKind) => {
116
- this._onResultClick.fire(k);
117
- }}
118
- />
119
- </div>
120
- );
121
- }
122
- }
@@ -1,276 +0,0 @@
1
- import { Autowired, INJECTOR_TOKEN, Injectable, Injector } from '@opensumi/di';
2
- import {
3
- CancelResponse,
4
- CancellationTokenSource,
5
- Disposable,
6
- Event,
7
- IDisposable,
8
- InlineChatFeatureRegistryToken,
9
- ReplyResponse,
10
- } from '@opensumi/ide-core-common';
11
- import { IEditor } from '@opensumi/ide-editor/lib/browser';
12
- import * as monaco from '@opensumi/ide-monaco';
13
- import { ICodeEditor } from '@opensumi/ide-monaco';
14
- import { empty } from '@opensumi/ide-utils/lib/strings';
15
- import { EditOperation } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/editOperation';
16
- import { LineRange } from '@opensumi/monaco-editor-core/esm/vs/editor/common/core/lineRange';
17
-
18
- import { AINativeContextKey } from '../../contextkey/ai-native.contextkey.service';
19
- import { AICompletionsService } from '../../contrib/inline-completions/service/ai-completions.service';
20
- import { ERunStrategy } from '../../types';
21
- import { InlineChatController } from '../inline-chat/inline-chat-controller';
22
- import { InlineChatFeatureRegistry } from '../inline-chat/inline-chat.feature.registry';
23
- import { EInlineChatStatus, EResultKind } from '../inline-chat/inline-chat.service';
24
- import { InlineInputPreviewDecorationID } from '../internal.type';
25
-
26
- import { InlineInputChatWidget } from './inline-input-widget';
27
- import styles from './inline-input.module.less';
28
- import { InlineInputChatService } from './inline-input.service';
29
-
30
- @Injectable()
31
- export class InlineInputHandler extends Disposable {
32
- @Autowired(INJECTOR_TOKEN)
33
- private readonly injector: Injector;
34
-
35
- @Autowired(AICompletionsService)
36
- private readonly inlineCompletionsService: AICompletionsService;
37
-
38
- @Autowired(InlineInputChatService)
39
- private readonly inlineInputChatService: InlineInputChatService;
40
-
41
- @Autowired(InlineChatFeatureRegistryToken)
42
- private readonly inlineChatFeatureRegistry: InlineChatFeatureRegistry;
43
-
44
- private aiNativeContextKey: AINativeContextKey;
45
- private cancelIndicator = new CancellationTokenSource();
46
-
47
- private cancelToken() {
48
- this.cancelIndicator.cancel();
49
- this.cancelIndicator = new CancellationTokenSource();
50
- }
51
-
52
- private async doRequestReadable(
53
- value: string,
54
- widget: InlineInputChatWidget,
55
- monacoEditor: ICodeEditor,
56
- inputDisposable: Disposable,
57
- decoration: monaco.editor.IEditorDecorationsCollection,
58
- hideInput: () => void,
59
- ): Promise<void> {
60
- const handler = this.inlineChatFeatureRegistry.getInteractiveInputHandler();
61
- const model = monacoEditor.getModel();
62
-
63
- if (!handler || !model) {
64
- return;
65
- }
66
-
67
- widget.launchChatStatus(EInlineChatStatus.THINKING);
68
-
69
- const strategy = await this.inlineChatFeatureRegistry.getInteractiveInputStrategyHandler()(monacoEditor, value);
70
-
71
- if (strategy === ERunStrategy.EXECUTE && handler.execute) {
72
- handler.execute(monacoEditor, value, this.cancelIndicator.token);
73
- widget.launchChatStatus(EInlineChatStatus.DONE);
74
- hideInput();
75
- return;
76
- }
77
-
78
- if (strategy === ERunStrategy.PREVIEW && handler.providerPreviewStrategy) {
79
- const previewResponse = await handler.providerPreviewStrategy(monacoEditor, value, this.cancelIndicator.token);
80
-
81
- if (CancelResponse.is(previewResponse)) {
82
- widget.launchChatStatus(EInlineChatStatus.READY);
83
- hideInput();
84
- return;
85
- }
86
-
87
- if (InlineChatController.is(previewResponse)) {
88
- const controller = previewResponse as InlineChatController;
89
-
90
- controller.deffered.resolve();
91
-
92
- inputDisposable.addDispose([
93
- controller.onData(async (data) => {
94
- if (!ReplyResponse.is(data)) {
95
- return;
96
- }
97
-
98
- const { message } = data;
99
-
100
- model.pushEditOperations(
101
- null,
102
- [
103
- // 直接用 EditOperation.insert 会有问题
104
- {
105
- range: monaco.Range.fromPositions(decoration.getRange(0)!.getEndPosition()),
106
- text: message,
107
- },
108
- ],
109
- () => null,
110
- );
111
- }),
112
- controller.onError((error) => {
113
- widget.launchChatStatus(EInlineChatStatus.ERROR);
114
- }),
115
- controller.onAbort(() => {
116
- widget.launchChatStatus(EInlineChatStatus.READY);
117
- }),
118
- controller.onEnd(() => {
119
- widget.launchChatStatus(EInlineChatStatus.DONE);
120
- }),
121
- ]);
122
- }
123
- }
124
- }
125
-
126
- public registerInlineInputFeature(editor: IEditor): IDisposable {
127
- const { monacoEditor } = editor;
128
- const inputDisposable = new Disposable();
129
- this.aiNativeContextKey = this.injector.get(AINativeContextKey, [editor.monacoEditor.contextKeyService]);
130
-
131
- const hideInput = () => {
132
- inputDisposable.dispose();
133
- };
134
-
135
- this.addDispose(
136
- this.inlineInputChatService.onInteractiveInputVisibleInPosition((position) => {
137
- hideInput();
138
-
139
- if (position) {
140
- showInput(position);
141
- }
142
- }),
143
- );
144
-
145
- const showInput = (position: monaco.Position) => {
146
- const model = monacoEditor.getModel();
147
- if (!model) {
148
- return;
149
- }
150
-
151
- if (this.inlineCompletionsService.isVisibleCompletion) {
152
- return;
153
- }
154
-
155
- const content = model.getLineContent(position.lineNumber);
156
- const isEmpty = content?.trim() === empty;
157
- const isEmptySelection = monacoEditor.getSelection()?.isEmpty();
158
-
159
- if (isEmpty && isEmptySelection) {
160
- const inlineInputChatWidget = this.injector.get(InlineInputChatWidget, [monacoEditor]);
161
-
162
- const collection = monacoEditor.createDecorationsCollection();
163
- collection.append([
164
- {
165
- range: monaco.Range.fromPositions(position),
166
- options: {
167
- description: InlineInputPreviewDecorationID,
168
- isWholeLine: true,
169
- className: styles.input_decoration_readable_container,
170
- inlineClassName: styles.inline_chat_inserted_range,
171
- },
172
- },
173
- ]);
174
-
175
- const decorationRange = collection.getRange(0)!;
176
- let preLineRange: LineRange = LineRange.fromRange(decorationRange);
177
-
178
- inlineInputChatWidget.show({ position: decorationRange.getStartPosition() });
179
-
180
- this.aiNativeContextKey.inlineInputWidgetIsVisible.set(true);
181
-
182
- inputDisposable.addDispose(
183
- inlineInputChatWidget.onDispose(() => {
184
- this.cancelToken();
185
- collection.clear();
186
- this.aiNativeContextKey.inlineInputWidgetIsVisible.set(false);
187
- }),
188
- );
189
-
190
- inputDisposable.addDispose(
191
- inlineInputChatWidget.onResultClick(async (kind: EResultKind) => {
192
- const clear = () => {
193
- const curPosi = collection.getRange(0)!;
194
-
195
- model.pushStackElement();
196
- model.pushEditOperations(null, [EditOperation.delete(curPosi)], () => null);
197
- model.pushStackElement();
198
- };
199
-
200
- switch (kind) {
201
- case EResultKind.ACCEPT:
202
- hideInput();
203
- break;
204
- case EResultKind.DISCARD:
205
- clear();
206
- hideInput();
207
- break;
208
- case EResultKind.REGENERATE:
209
- clear();
210
- await this.doRequestReadable(
211
- inlineInputChatWidget.interactiveInputValue,
212
- inlineInputChatWidget,
213
- monacoEditor,
214
- inputDisposable,
215
- collection,
216
- hideInput,
217
- );
218
- break;
219
-
220
- default:
221
- break;
222
- }
223
- }),
224
- );
225
-
226
- inputDisposable.addDispose(
227
- Event.debounce(
228
- collection.onDidChange.bind(collection),
229
- () => {},
230
- 16 * 3,
231
- )(() => {
232
- if (!collection.getRange(0)) {
233
- return;
234
- }
235
-
236
- const range = collection.getRange(0)!;
237
- const curLineRange = LineRange.fromRange(range);
238
- if (!preLineRange.equals(curLineRange)) {
239
- inlineInputChatWidget.setOptions({
240
- position: range.getStartPosition(),
241
- });
242
-
243
- inlineInputChatWidget.layoutContentWidget();
244
- }
245
- preLineRange = curLineRange;
246
- }),
247
- );
248
-
249
- inputDisposable.addDispose(
250
- inlineInputChatWidget.onInteractiveInputValue(async (value) => {
251
- await this.doRequestReadable(
252
- value,
253
- inlineInputChatWidget,
254
- monacoEditor,
255
- inputDisposable,
256
- collection,
257
- hideInput,
258
- );
259
- }),
260
- );
261
-
262
- inputDisposable.addDispose(inlineInputChatWidget);
263
- }
264
- };
265
-
266
- this.addDispose(inputDisposable);
267
-
268
- this.addDispose(
269
- monacoEditor.onWillChangeModel(() => {
270
- hideInput();
271
- }),
272
- );
273
-
274
- return this;
275
- }
276
- }
@@ -1,7 +0,0 @@
1
- .input_decoration_readable_container {
2
- background-color: var(--vscode-diffEditor-insertedLineBackground, var(--vscode-diffEditor-insertedTextBackground));
3
- }
4
-
5
- .input_wrapper {
6
- transform: translateY(-4px);
7
- }
@@ -1,25 +0,0 @@
1
- import { Injectable } from '@opensumi/di';
2
- import { Emitter, Event } from '@opensumi/ide-core-common';
3
- import { Position } from '@opensumi/ide-monaco';
4
-
5
- @Injectable()
6
- export class InlineInputChatService {
7
- private _interactiveInputVisible: boolean = false;
8
- public get interactiveInputVisible(): boolean {
9
- return this._interactiveInputVisible;
10
- }
11
-
12
- private readonly _onInteractiveInputVisibleInPosition = new Emitter<Position | undefined>();
13
- public readonly onInteractiveInputVisibleInPosition: Event<Position | undefined> =
14
- this._onInteractiveInputVisibleInPosition.event;
15
-
16
- public visibleInPosition(position: Position): void {
17
- this._interactiveInputVisible = true;
18
- this._onInteractiveInputVisibleInPosition.fire(position);
19
- }
20
-
21
- public hide(): void {
22
- this._interactiveInputVisible = false;
23
- this._onInteractiveInputVisibleInPosition.fire(undefined);
24
- }
25
- }
@@ -1,4 +0,0 @@
1
- /**
2
- * @internal
3
- */
4
- export const InlineInputPreviewDecorationID = 'InlineInputPreviewDecorationID';