@opensumi/ide-ai-native 3.0.3 → 3.0.4-next-1716367246.0

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 (77) hide show
  1. package/lib/browser/inline-completions/completeProvider.d.ts +5 -3
  2. package/lib/browser/inline-completions/completeProvider.d.ts.map +1 -1
  3. package/lib/browser/inline-completions/completeProvider.js +16 -30
  4. package/lib/browser/inline-completions/completeProvider.js.map +1 -1
  5. package/lib/browser/inline-completions/constants.d.ts +2 -6
  6. package/lib/browser/inline-completions/constants.d.ts.map +1 -1
  7. package/lib/browser/inline-completions/constants.js +81 -4
  8. package/lib/browser/inline-completions/constants.js.map +1 -1
  9. package/lib/browser/inline-completions/prompt/const.d.ts +9 -0
  10. package/lib/browser/inline-completions/prompt/const.d.ts.map +1 -0
  11. package/lib/browser/inline-completions/prompt/const.js +284 -0
  12. package/lib/browser/inline-completions/prompt/const.js.map +1 -0
  13. package/lib/browser/inline-completions/prompt/importedFiles.d.ts +6 -0
  14. package/lib/browser/inline-completions/prompt/importedFiles.d.ts.map +1 -0
  15. package/lib/browser/inline-completions/prompt/importedFiles.js +77 -0
  16. package/lib/browser/inline-completions/prompt/importedFiles.js.map +1 -0
  17. package/lib/browser/inline-completions/prompt/jaccardMatcher.d.ts +31 -0
  18. package/lib/browser/inline-completions/prompt/jaccardMatcher.d.ts.map +1 -0
  19. package/lib/browser/inline-completions/prompt/jaccardMatcher.js +75 -0
  20. package/lib/browser/inline-completions/prompt/jaccardMatcher.js.map +1 -0
  21. package/lib/browser/inline-completions/prompt/languages.d.ts +4 -0
  22. package/lib/browser/inline-completions/prompt/languages.d.ts.map +1 -0
  23. package/lib/browser/inline-completions/prompt/languages.js +67 -0
  24. package/lib/browser/inline-completions/prompt/languages.js.map +1 -0
  25. package/lib/browser/inline-completions/prompt/matcher.d.ts +42 -0
  26. package/lib/browser/inline-completions/prompt/matcher.d.ts.map +1 -0
  27. package/lib/browser/inline-completions/prompt/matcher.js +279 -0
  28. package/lib/browser/inline-completions/prompt/matcher.js.map +1 -0
  29. package/lib/browser/inline-completions/prompt/prompt.d.ts +24 -0
  30. package/lib/browser/inline-completions/prompt/prompt.d.ts.map +1 -0
  31. package/lib/browser/inline-completions/prompt/prompt.js +242 -0
  32. package/lib/browser/inline-completions/prompt/prompt.js.map +1 -0
  33. package/lib/browser/inline-completions/prompt/similarSnippets.d.ts +9 -0
  34. package/lib/browser/inline-completions/prompt/similarSnippets.d.ts.map +1 -0
  35. package/lib/browser/inline-completions/prompt/similarSnippets.js +110 -0
  36. package/lib/browser/inline-completions/prompt/similarSnippets.js.map +1 -0
  37. package/lib/browser/inline-completions/prompt/tokenizer.d.ts +4 -0
  38. package/lib/browser/inline-completions/prompt/tokenizer.d.ts.map +1 -0
  39. package/lib/browser/inline-completions/prompt/tokenizer.js +18 -0
  40. package/lib/browser/inline-completions/prompt/tokenizer.js.map +1 -0
  41. package/lib/browser/inline-completions/provider.d.ts +5 -12
  42. package/lib/browser/inline-completions/provider.d.ts.map +1 -1
  43. package/lib/browser/inline-completions/provider.js +79 -44
  44. package/lib/browser/inline-completions/provider.js.map +1 -1
  45. package/lib/browser/inline-completions/types.d.ts +154 -0
  46. package/lib/browser/inline-completions/types.d.ts.map +1 -0
  47. package/lib/browser/inline-completions/types.js +59 -0
  48. package/lib/browser/inline-completions/types.js.map +1 -0
  49. package/lib/browser/languages/parser.d.ts +6 -0
  50. package/lib/browser/languages/parser.d.ts.map +1 -1
  51. package/lib/browser/languages/parser.js +140 -1
  52. package/lib/browser/languages/parser.js.map +1 -1
  53. package/lib/browser/languages/tree-sitter/language-facts/types.d.ts +1 -1
  54. package/lib/browser/languages/tree-sitter/wasm-manager.d.ts +2 -2
  55. package/lib/browser/languages/tree-sitter/wasm-manager.d.ts.map +1 -1
  56. package/lib/browser/languages/tree-sitter/wasm-manager.js +2 -2
  57. package/lib/browser/languages/tree-sitter/wasm-manager.js.map +1 -1
  58. package/lib/common/utils.d.ts +5 -0
  59. package/lib/common/utils.d.ts.map +1 -0
  60. package/lib/common/utils.js +26 -0
  61. package/lib/common/utils.js.map +1 -0
  62. package/package.json +20 -19
  63. package/src/browser/inline-completions/completeProvider.ts +26 -35
  64. package/src/browser/inline-completions/constants.ts +87 -7
  65. package/src/browser/inline-completions/prompt/const.ts +286 -0
  66. package/src/browser/inline-completions/prompt/importedFiles.ts +92 -0
  67. package/src/browser/inline-completions/prompt/jaccardMatcher.ts +98 -0
  68. package/src/browser/inline-completions/prompt/languages.ts +65 -0
  69. package/src/browser/inline-completions/prompt/matcher.ts +328 -0
  70. package/src/browser/inline-completions/prompt/prompt.ts +297 -0
  71. package/src/browser/inline-completions/prompt/similarSnippets.ts +130 -0
  72. package/src/browser/inline-completions/prompt/tokenizer.ts +16 -0
  73. package/src/browser/inline-completions/provider.ts +107 -42
  74. package/src/browser/inline-completions/types.ts +169 -0
  75. package/src/browser/languages/parser.ts +147 -0
  76. package/src/browser/languages/tree-sitter/wasm-manager.ts +3 -3
  77. package/src/common/utils.ts +23 -0
@@ -1,6 +1,6 @@
1
1
  import { Autowired, INJECTOR_TOKEN, Injectable, Injector } from '@opensumi/di';
2
2
  import { AI_INLINE_COMPLETION_REPORTER } from '@opensumi/ide-core-browser/lib/ai-native/command';
3
- import { WithEventBus, uuid } from '@opensumi/ide-core-common';
3
+ import { URI, WithEventBus, uuid } from '@opensumi/ide-core-common';
4
4
  import { IAICompletionResultModel } from '@opensumi/ide-core-common/lib/types/ai-native';
5
5
  import { AISerivceType, IAIReporter } from '@opensumi/ide-core-common/lib/types/ai-native/reporter';
6
6
  import { IEditor } from '@opensumi/ide-editor';
@@ -8,12 +8,13 @@ import * as monaco from '@opensumi/ide-monaco';
8
8
 
9
9
  import { AINativeContextKey } from '../contextkey/ai-native.contextkey.service';
10
10
 
11
+ import { DEFAULT_COMPLECTION_MODEL } from './constants';
11
12
  import { CompletionRequestBean, InlayList, InlineCompletionItem } from './model/competionModel';
12
13
  import { PromptCache } from './promptCache';
13
- import { prePromptHandler, preSuffixHandler } from './provider';
14
+ import { getPrefixPrompt, getSuffixPrompt } from './provider';
14
15
  import { AICompletionsService } from './service/ai-completions.service';
16
+ import { ICompletionContext } from './types';
15
17
 
16
- let lastRequestId: any;
17
18
  let timer: any;
18
19
  let accept = 0;
19
20
 
@@ -29,7 +30,7 @@ export const getAcceptText = (cuont: number) => {
29
30
  accept = accept + cuont;
30
31
  };
31
32
 
32
- class RequestImp {
33
+ class CompletionRequest {
33
34
  isCancelFlag: boolean;
34
35
  // todo
35
36
  constructor(
@@ -37,6 +38,7 @@ class RequestImp {
37
38
  public _isManual: boolean,
38
39
  public aiCompletionsService: AICompletionsService,
39
40
  public promptCache: PromptCache,
41
+ public injector: Injector,
40
42
  ) {
41
43
  this.isCancelFlag = false;
42
44
  }
@@ -48,18 +50,12 @@ class RequestImp {
48
50
  token: monaco.CancellationToken,
49
51
  ) {
50
52
  const { model: editor } = this;
51
- const beginRequestTime = Date.now();
52
53
  if (!editor) {
53
54
  return [];
54
55
  }
55
56
 
56
57
  const startRange = new monaco.Range(0, 0, position.lineNumber, position.column);
57
- let prompt = model.getValueInRange(startRange!);
58
-
59
- // 如果是空白页面,默认加个回车符?
60
- if (this.model.getValue() === '') {
61
- prompt += '\n';
62
- }
58
+ const prefix = model.getValueInRange(startRange);
63
59
 
64
60
  const endRange = new monaco.Range(
65
61
  position.lineNumber,
@@ -69,19 +65,18 @@ class RequestImp {
69
65
  );
70
66
  let suffix = model.getValueInRange(endRange);
71
67
 
72
- // 改用analysisCodeFuseLanguage 现在目前后端需要语言小写
73
68
  const languageId = model.getLanguageId();
74
- // if (completionRtModel !== undefined && completionRtModel.sessionId === null) {
75
- // //此处未采纳上一个补全结果,那么设置endtime,并提交到服务端
76
- // completionRtModel.endRenderingTime = Date.now();
77
- // submitCompleteRtData(completionRtModel);
78
- // }
79
- // TODO 缺少数据前处理
80
- // prompt = prePromptHandler(prompt);
81
- // suffix = preSuffixHandler(suffix);
82
-
83
- prompt = prePromptHandler(prompt);
84
- suffix = preSuffixHandler(suffix);
69
+ const context: ICompletionContext = {
70
+ filename: model.uri.toString().split('/').pop()!,
71
+ language: languageId,
72
+ prefix,
73
+ suffix,
74
+ prompt: '',
75
+ uri: URI.from(model.uri),
76
+ };
77
+
78
+ const prompt = await getPrefixPrompt(context, DEFAULT_COMPLECTION_MODEL, this.injector, token);
79
+ suffix = await getSuffixPrompt(context, DEFAULT_COMPLECTION_MODEL, this.injector, token);
85
80
 
86
81
  // 组装请求参数,向远程发起请求
87
82
  const completionRequestBean: CompletionRequestBean = {
@@ -94,7 +89,6 @@ class RequestImp {
94
89
 
95
90
  this.aiCompletionsService.updateStatusBarItem('running', true);
96
91
  const beginAlgTime = Date.now();
97
- let status = 0; // 0: 远程请求的结果 1: 网络缓存中的结果
98
92
  if (this.isCancelFlag) {
99
93
  return [];
100
94
  }
@@ -107,7 +101,6 @@ class RequestImp {
107
101
  // 如果存在缓存
108
102
  if (cacheData) {
109
103
  rs = cacheData;
110
- status = 1;
111
104
  } else {
112
105
  try {
113
106
  rs = await this.aiCompletionsService.complete(completionRequestBean, model, position, token);
@@ -120,7 +113,6 @@ class RequestImp {
120
113
  this.aiCompletionsService.hideStatusBarItem();
121
114
  return [];
122
115
  }
123
- status = 0;
124
116
  }
125
117
 
126
118
  if (!(rs && rs.sessionId)) {
@@ -146,11 +138,6 @@ class RequestImp {
146
138
  if (rs && rs.codeModelList && rs.codeModelList.length > 0) {
147
139
  this.promptCache.setCache(prompt, rs);
148
140
  }
149
- let codeModelSize = 0;
150
- if (rs.codeModelList !== null) {
151
- codeModelSize = rs.codeModelList.length;
152
- }
153
-
154
141
  // 返回补全结果为空直接返回
155
142
  if (rs.codeModelList.length === 0) {
156
143
  this.aiCompletionsService.reporterEnd(relationId, {
@@ -225,7 +212,6 @@ class RequestImp {
225
212
  },
226
213
  });
227
214
  }
228
- lastRequestId = rs.sessionId;
229
215
  return result;
230
216
  }
231
217
  cancelRequest() {
@@ -238,7 +224,7 @@ class ReqStack {
238
224
  constructor(private readonly aiReporter) {
239
225
  this.queue = [];
240
226
  }
241
- addReq(reqRequest: RequestImp) {
227
+ addReq(reqRequest: CompletionRequest) {
242
228
  this.queue.push(reqRequest);
243
229
  }
244
230
  runReq(position: monaco.Position, model: monaco.editor.ITextModel, token: monaco.CancellationToken) {
@@ -287,7 +273,6 @@ export class AIInlineCompletionsProvider extends WithEventBus {
287
273
  this.reqStack = new ReqStack(this.aiReporter);
288
274
  }
289
275
 
290
- // 取消请求
291
276
  cancelRequest() {
292
277
  this.aiCompletionsService.cancelRequest();
293
278
  if (this.reqStack) {
@@ -349,7 +334,13 @@ export class AIInlineCompletionsProvider extends WithEventBus {
349
334
  };
350
335
  }
351
336
  // 放入队列
352
- const requestImp = new RequestImp(model, _isManual, this.aiCompletionsService, this.promptCache);
337
+ const requestImp = new CompletionRequest(
338
+ model,
339
+ _isManual,
340
+ this.aiCompletionsService,
341
+ this.promptCache,
342
+ this.injector,
343
+ );
353
344
  this.reqStack.addReq(requestImp);
354
345
  // 如果是自动补全等待300ms
355
346
  if (!_isManual) {
@@ -1,9 +1,89 @@
1
- interface ICompletionModel {
2
- completionPromptMaxLineSize: number;
3
- completionSuffixMaxLineSize: number;
4
- }
1
+ import {
2
+ ICompletionModel,
3
+ NeighboringTabsOption,
4
+ SnippetSelectionOption,
5
+ StrategyType,
6
+ TokenizerName,
7
+ WishListAttributeName,
8
+ } from './types';
5
9
 
6
- export const completionModel: ICompletionModel = {
7
- completionPromptMaxLineSize: 1024,
8
- completionSuffixMaxLineSize: 500,
10
+ export const DEFAULT_COMPLECTION_MODEL: ICompletionModel = {
11
+ maxPromptTokenSize: 3000,
12
+ maxExecuteTimeMillSecond: 1000,
13
+ tokenizerName: TokenizerName.cl100k_base,
14
+ wishList: {
15
+ afterCursor: {
16
+ enable: true,
17
+ attributeName: WishListAttributeName.afterCursor,
18
+ extOption: {
19
+ suffixPercent: 0.25,
20
+ minBlockSize: 25,
21
+ },
22
+ priority: 1,
23
+ strategy: StrategyType.InterceptBasedOnLine,
24
+ },
25
+ beforeCursor: {
26
+ enable: true,
27
+ attributeName: WishListAttributeName.beforeCursor,
28
+ extOption: {
29
+ prefixPercent: 0.75,
30
+ minBlockSize: 75,
31
+ },
32
+ priority: 0,
33
+ strategy: StrategyType.InterceptBasedOnLine,
34
+ },
35
+ importedFile: {
36
+ attributeName: WishListAttributeName.importedFile,
37
+ enable: true,
38
+ extOption: {
39
+ maxTime: 200,
40
+ importedFilesMaxNum: 10,
41
+ language: ['typescript'],
42
+ maxPercent: 0.8,
43
+ patternPrefix: 'Import Files from ',
44
+ patternSuffix: '\n',
45
+ },
46
+ priority: 3,
47
+ strategy: StrategyType.InterceptBasedOnLine,
48
+ },
49
+ languageMarker: {
50
+ attributeName: WishListAttributeName.languageMarker,
51
+ enable: true,
52
+ extOption: {
53
+ language: ['python', 'html'],
54
+ maxPercent: 0,
55
+ },
56
+ priority: 4,
57
+ strategy: StrategyType.InterceptBasedOnLine,
58
+ },
59
+ pathMarker: {
60
+ attributeName: WishListAttributeName.pathMarker,
61
+ enable: true,
62
+ priority: 1,
63
+ strategy: StrategyType.InterceptBasedOnLine,
64
+ },
65
+ similarFile: {
66
+ attributeName: WishListAttributeName.similarFile,
67
+ enable: true,
68
+ extOption: {
69
+ maxTime: 200,
70
+ fileMaxLength: 5000,
71
+ maxPercent: 0.3,
72
+ neighboringTabsMaxNum: 20,
73
+ neighboringTabsOption: [
74
+ NeighboringTabsOption.openFileHistory,
75
+ NeighboringTabsOption.editFileRecent,
76
+ NeighboringTabsOption.editFileHistory,
77
+ ],
78
+ patternPrefix: 'Compare this snippet from ',
79
+ patternSuffix: '\n',
80
+ similarityThreshold: 0.6,
81
+ snippetMaxNum: 4,
82
+ windowSize: 60,
83
+ snippetSelectionMode: SnippetSelectionOption.BestMatch,
84
+ },
85
+ priority: 2,
86
+ strategy: StrategyType.InterceptBasedOnLine,
87
+ },
88
+ },
9
89
  };
@@ -0,0 +1,286 @@
1
+ export const LANGUAGE_COMMENT_MARKERS: {
2
+ [key: string]: {
3
+ start: string;
4
+ end: string;
5
+ };
6
+ } = {
7
+ abap: {
8
+ start: '"',
9
+ end: '',
10
+ },
11
+ bat: {
12
+ start: 'REM',
13
+ end: '',
14
+ },
15
+ bibtex: {
16
+ start: '%',
17
+ end: '',
18
+ },
19
+ blade: {
20
+ start: '#',
21
+ end: '',
22
+ },
23
+ c: {
24
+ start: '//',
25
+ end: '',
26
+ },
27
+ clojure: {
28
+ start: ';',
29
+ end: '',
30
+ },
31
+ coffeescript: {
32
+ start: '//',
33
+ end: '',
34
+ },
35
+ cpp: {
36
+ start: '//',
37
+ end: '',
38
+ },
39
+ csharp: {
40
+ start: '//',
41
+ end: '',
42
+ },
43
+ css: {
44
+ start: '/*',
45
+ end: '*/',
46
+ },
47
+ dart: {
48
+ start: '//',
49
+ end: '',
50
+ },
51
+ dockerfile: {
52
+ start: '#',
53
+ end: '',
54
+ },
55
+ elixir: {
56
+ start: '#',
57
+ end: '',
58
+ },
59
+ erb: {
60
+ start: '<%#',
61
+ end: '%>',
62
+ },
63
+ erlang: {
64
+ start: '%',
65
+ end: '',
66
+ },
67
+ fsharp: {
68
+ start: '//',
69
+ end: '',
70
+ },
71
+ go: {
72
+ start: '//',
73
+ end: '',
74
+ },
75
+ groovy: {
76
+ start: '//',
77
+ end: '',
78
+ },
79
+ haml: {
80
+ start: '-#',
81
+ end: '',
82
+ },
83
+ handlebars: {
84
+ start: '{{!',
85
+ end: '}}',
86
+ },
87
+ haskell: {
88
+ start: '--',
89
+ end: '',
90
+ },
91
+ html: {
92
+ start: '\x3c!--',
93
+ end: '--\x3e',
94
+ },
95
+ ini: {
96
+ start: ';',
97
+ end: '',
98
+ },
99
+ java: {
100
+ start: '//',
101
+ end: '',
102
+ },
103
+ javascript: {
104
+ start: '//',
105
+ end: '',
106
+ },
107
+ javascriptreact: {
108
+ start: '//',
109
+ end: '',
110
+ },
111
+ jsonc: {
112
+ start: '//',
113
+ end: '',
114
+ },
115
+ jsx: {
116
+ start: '//',
117
+ end: '',
118
+ },
119
+ julia: {
120
+ start: '#',
121
+ end: '',
122
+ },
123
+ kotlin: {
124
+ start: '//',
125
+ end: '',
126
+ },
127
+ latex: {
128
+ start: '%',
129
+ end: '',
130
+ },
131
+ less: {
132
+ start: '//',
133
+ end: '',
134
+ },
135
+ lua: {
136
+ start: '--',
137
+ end: '',
138
+ },
139
+ makefile: {
140
+ start: '#',
141
+ end: '',
142
+ },
143
+ markdown: {
144
+ start: '[]: #',
145
+ end: '',
146
+ },
147
+ 'objective-c': {
148
+ start: '//',
149
+ end: '',
150
+ },
151
+ 'objective-cpp': {
152
+ start: '//',
153
+ end: '',
154
+ },
155
+ perl: {
156
+ start: '#',
157
+ end: '',
158
+ },
159
+ php: {
160
+ start: '//',
161
+ end: '',
162
+ },
163
+ powershell: {
164
+ start: '#',
165
+ end: '',
166
+ },
167
+ pug: {
168
+ start: '//',
169
+ end: '',
170
+ },
171
+ python: {
172
+ start: '#',
173
+ end: '',
174
+ },
175
+ ql: {
176
+ start: '//',
177
+ end: '',
178
+ },
179
+ r: {
180
+ start: '#',
181
+ end: '',
182
+ },
183
+ razor: {
184
+ start: '\x3c!--',
185
+ end: '--\x3e',
186
+ },
187
+ ruby: {
188
+ start: '#',
189
+ end: '',
190
+ },
191
+ rust: {
192
+ start: '//',
193
+ end: '',
194
+ },
195
+ sass: {
196
+ start: '//',
197
+ end: '',
198
+ },
199
+ scala: {
200
+ start: '//',
201
+ end: '',
202
+ },
203
+ scss: {
204
+ start: '//',
205
+ end: '',
206
+ },
207
+ shellscript: {
208
+ start: '#',
209
+ end: '',
210
+ },
211
+ slim: {
212
+ start: '/',
213
+ end: '',
214
+ },
215
+ solidity: {
216
+ start: '//',
217
+ end: '',
218
+ },
219
+ sql: {
220
+ start: '--',
221
+ end: '',
222
+ },
223
+ stylus: {
224
+ start: '//',
225
+ end: '',
226
+ },
227
+ svelte: {
228
+ start: '\x3c!--',
229
+ end: '--\x3e',
230
+ },
231
+ swift: {
232
+ start: '//',
233
+ end: '',
234
+ },
235
+ terraform: {
236
+ start: '#',
237
+ end: '',
238
+ },
239
+ tex: {
240
+ start: '%',
241
+ end: '',
242
+ },
243
+ typescript: {
244
+ start: '//',
245
+ end: '',
246
+ },
247
+ typescriptreact: {
248
+ start: '//',
249
+ end: '',
250
+ },
251
+ vb: {
252
+ start: "'",
253
+ end: '',
254
+ },
255
+ verilog: {
256
+ start: '//',
257
+ end: '',
258
+ },
259
+ 'vue-html': {
260
+ start: '\x3c!--',
261
+ end: '--\x3e',
262
+ },
263
+ vue: {
264
+ start: '//',
265
+ end: '',
266
+ },
267
+ xml: {
268
+ start: '\x3c!--',
269
+ end: '--\x3e',
270
+ },
271
+ xsl: {
272
+ start: '\x3c!--',
273
+ end: '--\x3e',
274
+ },
275
+ yaml: {
276
+ start: '#',
277
+ end: '',
278
+ },
279
+ diff: {
280
+ start: '#',
281
+ end: '',
282
+ },
283
+ };
284
+
285
+ export const EXCLUDED_NEIGHBORS = ['node_modules', 'dist', 'site-packages'];
286
+ export const MAX_NEIGHBOR_AGGREGATE_LENGTH = 2e5;
@@ -0,0 +1,92 @@
1
+ import { Injector } from '@opensumi/di';
2
+ import { URI } from '@opensumi/ide-core-common';
3
+ import { IFileServiceClient } from '@opensumi/ide-file-service';
4
+ import { Path } from '@opensumi/ide-utils/lib/path';
5
+ import { IWorkspaceService } from '@opensumi/ide-workspace';
6
+
7
+ import { LanguageParserService } from '../../languages/service';
8
+ import { ICompletionContext, ImportedFileOptions, ResourceDocument } from '../types';
9
+
10
+ import { LANGUAGE_TO_SUFFIX } from './languages';
11
+
12
+ export const getImportedFilesInterface = async (
13
+ code: string,
14
+ resource: ResourceDocument,
15
+ options: ImportedFileOptions,
16
+ injector: Injector,
17
+ ): Promise<(string | string[])[][]> => {
18
+ const languageParserService = injector.get(LanguageParserService) as LanguageParserService;
19
+ let matches: string[] = [];
20
+ const snippets: (string | string[])[][] = [];
21
+ const languageParser = languageParserService.createParser(resource.languageId);
22
+ if (languageParser) {
23
+ matches = await languageParser.extractImportPaths(code);
24
+ }
25
+ const maxPromptTime = options.maxTime ?? 200;
26
+ const startTime = Date.now();
27
+ for (const file of matches) {
28
+ let filePath = '';
29
+ const basePath = resource.uri.parent.codeUri.fsPath;
30
+ if (file.startsWith('@/') || file.startsWith('~') || !file.startsWith('.')) {
31
+ // skip alias
32
+ continue;
33
+ }
34
+ if (file === '.') {
35
+ filePath = new Path(basePath).join('index.ts').toString();
36
+ } else {
37
+ filePath = new Path(basePath).join(`${file}${LANGUAGE_TO_SUFFIX[resource.languageId]}`).toString();
38
+ }
39
+ try {
40
+ const fileService = injector.get(IFileServiceClient) as IFileServiceClient;
41
+ const workspaceService = injector.get(IWorkspaceService) as IWorkspaceService;
42
+ const fileUri = URI.file(filePath);
43
+ const content = await fileService.readFile(fileUri.codeUri.fsPath);
44
+ const interfaceCode = await languageParser?.extractInterfaceOrTypeCode(content.content.toString());
45
+ if (interfaceCode && interfaceCode.length > 0) {
46
+ const relative = await workspaceService.asRelativePath(fileUri);
47
+ if (relative?.path) {
48
+ snippets.push([relative.path, interfaceCode]);
49
+ }
50
+ }
51
+ } catch {}
52
+ if (Date.now() - startTime > maxPromptTime) {
53
+ break;
54
+ }
55
+ }
56
+ return snippets;
57
+ };
58
+
59
+ export const extractLocalImportContext = async (
60
+ resource: ResourceDocument,
61
+ options: ImportedFileOptions,
62
+ injector: Injector,
63
+ ): Promise<(string | string[])[][]> => {
64
+ // 从代码中提取出所有的 import 语句,并进一步提取 interface 相关代码声明
65
+ const { source } = resource;
66
+
67
+ if (resource.languageId === 'typescript') {
68
+ return getImportedFilesInterface(source, resource, options, injector);
69
+ }
70
+ return [];
71
+ };
72
+
73
+ export const getImportedFile = async (
74
+ context: ICompletionContext,
75
+ options: ImportedFileOptions,
76
+ injector: Injector,
77
+ ): Promise<(string | string[])[][]> => {
78
+ if (context.language && !options.language.includes(context.language)) {
79
+ return [];
80
+ }
81
+ const content = context.prefix;
82
+ return extractLocalImportContext(
83
+ {
84
+ source: content,
85
+ uri: context.uri,
86
+ languageId: context.language,
87
+ offset: content.length,
88
+ },
89
+ options,
90
+ injector,
91
+ );
92
+ };