@opensumi/ide-ai-native 2.26.9-next-1695201123.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 (194) hide show
  1. package/LICENSE +21 -0
  2. package/lib/browser/ai-chat.contribution.d.ts +26 -0
  3. package/lib/browser/ai-chat.contribution.d.ts.map +1 -0
  4. package/lib/browser/ai-chat.contribution.js +228 -0
  5. package/lib/browser/ai-chat.contribution.js.map +1 -0
  6. package/lib/browser/ai-chat.module.less +174 -0
  7. package/lib/browser/ai-chat.service.d.ts +30 -0
  8. package/lib/browser/ai-chat.service.d.ts.map +1 -0
  9. package/lib/browser/ai-chat.service.js +129 -0
  10. package/lib/browser/ai-chat.service.js.map +1 -0
  11. package/lib/browser/ai-chat.view.d.ts +4 -0
  12. package/lib/browser/ai-chat.view.d.ts.map +1 -0
  13. package/lib/browser/ai-chat.view.js +292 -0
  14. package/lib/browser/ai-chat.view.js.map +1 -0
  15. package/lib/browser/ai-editor.contribution.d.ts +26 -0
  16. package/lib/browser/ai-editor.contribution.d.ts.map +1 -0
  17. package/lib/browser/ai-editor.contribution.js +430 -0
  18. package/lib/browser/ai-editor.contribution.js.map +1 -0
  19. package/lib/browser/ai-project/generate.service.d.ts +34 -0
  20. package/lib/browser/ai-project/generate.service.d.ts.map +1 -0
  21. package/lib/browser/ai-project/generate.service.js +460 -0
  22. package/lib/browser/ai-project/generate.service.js.map +1 -0
  23. package/lib/browser/ai-sumi/sumi.service.d.ts +11 -0
  24. package/lib/browser/ai-sumi/sumi.service.d.ts.map +1 -0
  25. package/lib/browser/ai-sumi/sumi.service.js +64 -0
  26. package/lib/browser/ai-sumi/sumi.service.js.map +1 -0
  27. package/lib/browser/code-widget/ai-code-document.provider.d.ts +10 -0
  28. package/lib/browser/code-widget/ai-code-document.provider.d.ts.map +1 -0
  29. package/lib/browser/code-widget/ai-code-document.provider.js +26 -0
  30. package/lib/browser/code-widget/ai-code-document.provider.js.map +1 -0
  31. package/lib/browser/code-widget/ai-code-widget.d.ts +20 -0
  32. package/lib/browser/code-widget/ai-code-widget.d.ts.map +1 -0
  33. package/lib/browser/code-widget/ai-code-widget.js +164 -0
  34. package/lib/browser/code-widget/ai-code-widget.js.map +1 -0
  35. package/lib/browser/components/AIImprove.d.ts +9 -0
  36. package/lib/browser/components/AIImprove.d.ts.map +1 -0
  37. package/lib/browser/components/AIImprove.js +34 -0
  38. package/lib/browser/components/AIImprove.js.map +1 -0
  39. package/lib/browser/components/AIInput.d.ts +5 -0
  40. package/lib/browser/components/AIInput.d.ts.map +1 -0
  41. package/lib/browser/components/AIInput.js +22 -0
  42. package/lib/browser/components/AIInput.js.map +1 -0
  43. package/lib/browser/components/ChatEditor.d.ts +5 -0
  44. package/lib/browser/components/ChatEditor.d.ts.map +1 -0
  45. package/lib/browser/components/ChatEditor.js +85 -0
  46. package/lib/browser/components/ChatEditor.js.map +1 -0
  47. package/lib/browser/components/ChatInput.d.ts +6 -0
  48. package/lib/browser/components/ChatInput.d.ts.map +1 -0
  49. package/lib/browser/components/ChatInput.js +126 -0
  50. package/lib/browser/components/ChatInput.js.map +1 -0
  51. package/lib/browser/components/ChatMoreActions.d.ts +5 -0
  52. package/lib/browser/components/ChatMoreActions.d.ts.map +1 -0
  53. package/lib/browser/components/ChatMoreActions.js +26 -0
  54. package/lib/browser/components/ChatMoreActions.js.map +1 -0
  55. package/lib/browser/components/Thinking.d.ts +3 -0
  56. package/lib/browser/components/Thinking.d.ts.map +1 -0
  57. package/lib/browser/components/Thinking.js +19 -0
  58. package/lib/browser/components/Thinking.js.map +1 -0
  59. package/lib/browser/components/components.module.less +261 -0
  60. package/lib/browser/components/lineVertical.d.ts +4 -0
  61. package/lib/browser/components/lineVertical.d.ts.map +1 -0
  62. package/lib/browser/components/lineVertical.js +22 -0
  63. package/lib/browser/components/lineVertical.js.map +1 -0
  64. package/lib/browser/content-widget/ai-content-widget.d.ts +38 -0
  65. package/lib/browser/content-widget/ai-content-widget.d.ts.map +1 -0
  66. package/lib/browser/content-widget/ai-content-widget.js +97 -0
  67. package/lib/browser/content-widget/ai-content-widget.js.map +1 -0
  68. package/lib/browser/content-widget/ai-inline-chat-panel.d.ts +6 -0
  69. package/lib/browser/content-widget/ai-inline-chat-panel.d.ts.map +1 -0
  70. package/lib/browser/content-widget/ai-inline-chat-panel.js +108 -0
  71. package/lib/browser/content-widget/ai-inline-chat-panel.js.map +1 -0
  72. package/lib/browser/content-widget/ai-inline-chat.module.less +81 -0
  73. package/lib/browser/content-widget/ai-inline-chat.service.d.ts +23 -0
  74. package/lib/browser/content-widget/ai-inline-chat.service.d.ts.map +1 -0
  75. package/lib/browser/content-widget/ai-inline-chat.service.js +47 -0
  76. package/lib/browser/content-widget/ai-inline-chat.service.js.map +1 -0
  77. package/lib/browser/diff-widget/ai-diff-document.provider.d.ts +10 -0
  78. package/lib/browser/diff-widget/ai-diff-document.provider.d.ts.map +1 -0
  79. package/lib/browser/diff-widget/ai-diff-document.provider.js +26 -0
  80. package/lib/browser/diff-widget/ai-diff-document.provider.js.map +1 -0
  81. package/lib/browser/diff-widget/ai-diff-widget.d.ts +20 -0
  82. package/lib/browser/diff-widget/ai-diff-widget.d.ts.map +1 -0
  83. package/lib/browser/diff-widget/ai-diff-widget.js +158 -0
  84. package/lib/browser/diff-widget/ai-diff-widget.js.map +1 -0
  85. package/lib/browser/index.d.ts +11 -0
  86. package/lib/browser/index.d.ts.map +1 -0
  87. package/lib/browser/index.js +82 -0
  88. package/lib/browser/index.js.map +1 -0
  89. package/lib/browser/inline-completions/constants.d.ts +62 -0
  90. package/lib/browser/inline-completions/constants.d.ts.map +1 -0
  91. package/lib/browser/inline-completions/constants.js +69 -0
  92. package/lib/browser/inline-completions/constants.js.map +1 -0
  93. package/lib/browser/inline-completions/provider.d.ts +27 -0
  94. package/lib/browser/inline-completions/provider.d.ts.map +1 -0
  95. package/lib/browser/inline-completions/provider.js +63 -0
  96. package/lib/browser/inline-completions/provider.js.map +1 -0
  97. package/lib/browser/override/ai-editor-tab.service.d.ts +6 -0
  98. package/lib/browser/override/ai-editor-tab.service.d.ts.map +1 -0
  99. package/lib/browser/override/ai-editor-tab.service.js +22 -0
  100. package/lib/browser/override/ai-editor-tab.service.js.map +1 -0
  101. package/lib/browser/override/ai-marker.service.d.ts +11 -0
  102. package/lib/browser/override/ai-marker.service.d.ts.map +1 -0
  103. package/lib/browser/override/ai-marker.service.js +56 -0
  104. package/lib/browser/override/ai-marker.service.js.map +1 -0
  105. package/lib/browser/override/layout/layout-config.d.ts +11 -0
  106. package/lib/browser/override/layout/layout-config.d.ts.map +1 -0
  107. package/lib/browser/override/layout/layout-config.js +17 -0
  108. package/lib/browser/override/layout/layout-config.js.map +1 -0
  109. package/lib/browser/override/layout/layout.module.less +261 -0
  110. package/lib/browser/override/layout/main-slot-renderer.d.ts +4 -0
  111. package/lib/browser/override/layout/main-slot-renderer.d.ts.map +1 -0
  112. package/lib/browser/override/layout/main-slot-renderer.js +23 -0
  113. package/lib/browser/override/layout/main-slot-renderer.js.map +1 -0
  114. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.d.ts +8 -0
  115. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.d.ts.map +1 -0
  116. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.js +32 -0
  117. package/lib/browser/override/layout/menu-bar/menu-bar.contribution.js.map +1 -0
  118. package/lib/browser/override/layout/menu-bar/menu-bar.module.less +41 -0
  119. package/lib/browser/override/layout/menu-bar/menu-bar.view.d.ts +3 -0
  120. package/lib/browser/override/layout/menu-bar/menu-bar.view.d.ts.map +1 -0
  121. package/lib/browser/override/layout/menu-bar/menu-bar.view.js +62 -0
  122. package/lib/browser/override/layout/menu-bar/menu-bar.view.js.map +1 -0
  123. package/lib/browser/override/layout/tabbar.view.d.ts +19 -0
  124. package/lib/browser/override/layout/tabbar.view.d.ts.map +1 -0
  125. package/lib/browser/override/layout/tabbar.view.js +38 -0
  126. package/lib/browser/override/layout/tabbar.view.js.map +1 -0
  127. package/lib/browser/override/override.module.less +32 -0
  128. package/lib/browser/override/theme/default-theme.d.ts +315 -0
  129. package/lib/browser/override/theme/default-theme.d.ts.map +1 -0
  130. package/lib/browser/override/theme/default-theme.js +821 -0
  131. package/lib/browser/override/theme/default-theme.js.map +1 -0
  132. package/lib/browser/run/run.service.d.ts +52 -0
  133. package/lib/browser/run/run.service.d.ts.map +1 -0
  134. package/lib/browser/run/run.service.js +176 -0
  135. package/lib/browser/run/run.service.js.map +1 -0
  136. package/lib/common/command.d.ts +17 -0
  137. package/lib/common/command.d.ts.map +1 -0
  138. package/lib/common/command.js +21 -0
  139. package/lib/common/command.js.map +1 -0
  140. package/lib/common/index.d.ts +47 -0
  141. package/lib/common/index.d.ts.map +1 -0
  142. package/lib/common/index.js +33 -0
  143. package/lib/common/index.js.map +1 -0
  144. package/lib/index.d.ts +2 -0
  145. package/lib/index.d.ts.map +1 -0
  146. package/lib/index.js +5 -0
  147. package/lib/index.js.map +1 -0
  148. package/lib/node/index.d.ts +10 -0
  149. package/lib/node/index.d.ts.map +1 -0
  150. package/lib/node/index.js +32 -0
  151. package/lib/node/index.js.map +1 -0
  152. package/package.json +38 -0
  153. package/src/browser/ai-chat.contribution.ts +300 -0
  154. package/src/browser/ai-chat.module.less +174 -0
  155. package/src/browser/ai-chat.service.ts +146 -0
  156. package/src/browser/ai-chat.view.tsx +410 -0
  157. package/src/browser/ai-editor.contribution.ts +564 -0
  158. package/src/browser/ai-project/generate.service.ts +515 -0
  159. package/src/browser/ai-sumi/sumi.service.ts +65 -0
  160. package/src/browser/code-widget/ai-code-document.provider.ts +22 -0
  161. package/src/browser/code-widget/ai-code-widget.tsx +202 -0
  162. package/src/browser/components/AIImprove.tsx +45 -0
  163. package/src/browser/components/AIInput.tsx +30 -0
  164. package/src/browser/components/ChatEditor.tsx +129 -0
  165. package/src/browser/components/ChatInput.tsx +199 -0
  166. package/src/browser/components/ChatMoreActions.tsx +33 -0
  167. package/src/browser/components/Thinking.tsx +23 -0
  168. package/src/browser/components/components.module.less +261 -0
  169. package/src/browser/components/lineVertical.tsx +19 -0
  170. package/src/browser/content-widget/ai-content-widget.tsx +132 -0
  171. package/src/browser/content-widget/ai-inline-chat-panel.tsx +163 -0
  172. package/src/browser/content-widget/ai-inline-chat.module.less +81 -0
  173. package/src/browser/content-widget/ai-inline-chat.service.ts +46 -0
  174. package/src/browser/diff-widget/ai-diff-document.provider.ts +22 -0
  175. package/src/browser/diff-widget/ai-diff-widget.tsx +196 -0
  176. package/src/browser/index.ts +89 -0
  177. package/src/browser/inline-completions/constants.ts +108 -0
  178. package/src/browser/inline-completions/provider.ts +55 -0
  179. package/src/browser/override/ai-editor-tab.service.tsx +22 -0
  180. package/src/browser/override/ai-marker.service.tsx +61 -0
  181. package/src/browser/override/layout/layout-config.ts +17 -0
  182. package/src/browser/override/layout/layout.module.less +261 -0
  183. package/src/browser/override/layout/main-slot-renderer.tsx +63 -0
  184. package/src/browser/override/layout/menu-bar/menu-bar.contribution.tsx +28 -0
  185. package/src/browser/override/layout/menu-bar/menu-bar.module.less +41 -0
  186. package/src/browser/override/layout/menu-bar/menu-bar.view.tsx +92 -0
  187. package/src/browser/override/layout/tabbar.view.tsx +91 -0
  188. package/src/browser/override/override.module.less +32 -0
  189. package/src/browser/override/theme/default-theme.ts +818 -0
  190. package/src/browser/run/run.service.ts +186 -0
  191. package/src/common/command.ts +21 -0
  192. package/src/common/index.ts +50 -0
  193. package/src/index.ts +1 -0
  194. package/src/node/index.ts +24 -0
@@ -0,0 +1,515 @@
1
+ /* eslint-disable no-console */
2
+ import { Injectable, Autowired } from '@opensumi/di';
3
+ import { ILogServiceClient, ILoggerManagerClient, SupportLogNamespace } from '@opensumi/ide-core-common';
4
+
5
+ import { AiGPTBackSerivcePath } from '../../common';
6
+
7
+ const enum FRAMEWORK {
8
+ minifish = 'minifish',
9
+ bigfish = 'bigfish',
10
+ sofa = 'sofa',
11
+ }
12
+
13
+ export interface Requirements {
14
+ language: string;
15
+ framework: string;
16
+ requirements: string;
17
+ }
18
+
19
+ @Injectable()
20
+ export class AiProjectGenerateService {
21
+ @Autowired(AiGPTBackSerivcePath)
22
+ aiBackService: any;
23
+
24
+ @Autowired(ILoggerManagerClient)
25
+ private readonly loggerManagerClient: ILoggerManagerClient;
26
+
27
+ private logger: ILogServiceClient;
28
+
29
+ constructor() {
30
+ this.logger = this.loggerManagerClient.getLogger(SupportLogNamespace.Browser);
31
+ }
32
+
33
+ private matchFramework(language: string, framework: string) {
34
+ if (/javascript|typescript/i.test(language)) {
35
+ return /minifish/i.test(framework) ? FRAMEWORK.minifish : FRAMEWORK.bigfish;
36
+ }
37
+
38
+ if (/java/i.test(language)) {
39
+ return FRAMEWORK.sofa;
40
+ }
41
+
42
+ return framework;
43
+ }
44
+
45
+ public async switchProjectLanguage(input: string) {
46
+ const prompt = `
47
+ ### 介绍 ###
48
+ 我会提供一份关于编程项目的描述,请基于项目描述提取出项目所使用的编程语言、适合的编程框架,以及分析一下项目的具体需求。
49
+ 如果是支付宝小程序相关的需求,编程语言为 Javascript,编程框架使用: Minifish
50
+ 如果是与前端有关的需求,编程语言为 Typescript,编程框架请使用: Bigfish
51
+ 下面是一个问答示例,请参照示例的格式,给出回答。
52
+
53
+ ### 示例 ###
54
+ 示例提问:创建一个 java 项目,与营销相关
55
+ 示例回答:
56
+ 编程语言: JAVA
57
+ 编程框架: Sofa Boot、Sofa4
58
+ 项目需求:创建一个用于营销的项目
59
+
60
+ ### 需求 ###
61
+ 我的问题: ${input}
62
+ `;
63
+ const res = await this.aiBackService.aiAntGlm(prompt);
64
+ this.logger.log('gen request res: ', res);
65
+ const reg =
66
+ /(编程语言)(:|:)?\s?(?<language>.*)\n*\s*(编程框架)(:|:)?\s?(?<framework>.*)\n*\s*(项目需求)(:|:)?\s?(?<requirements>.*)/i;
67
+ const match = reg.exec(res.data);
68
+
69
+ return (
70
+ match &&
71
+ ({
72
+ ...(match.groups || {}),
73
+ framework: match.groups?.framework.split('、'),
74
+ } as { language: string; framework: string[]; requirements: string })
75
+ );
76
+ }
77
+
78
+ private generateStructurePrompt({ language, framework }: Requirements) {
79
+ switch (this.matchFramework(language, framework)) {
80
+ case FRAMEWORK.minifish:
81
+ return `
82
+ ├──mini.project.json
83
+ ├──app.js
84
+ ├──app.json
85
+ ├──README.md
86
+ ├──.gitignore
87
+ └──pages
88
+ ├──order
89
+ │ ├──index.js
90
+ │ ├──index.axml
91
+ │ ├──index.acss
92
+ │ └──index.json
93
+ └──detail
94
+ ├──index.js
95
+ ├──index.axml
96
+ ├──index.acss
97
+ └──index.json
98
+ `;
99
+ case FRAMEWORK.bigfish:
100
+ return `
101
+ ├──package.json
102
+ ├──app.tsx
103
+ ├──README.md
104
+ ├──.gitignore
105
+ ├──.eslintrc
106
+ ├──src
107
+ │ └──pages
108
+ │ └──order
109
+ │ ├──index.tsx
110
+ │ └──index.less
111
+ └──config
112
+ ├──config.ts
113
+ └──router.config.ts
114
+ `;
115
+ default:
116
+ return `
117
+ ├──.gitignore
118
+ ├──pom.xml
119
+ ├──README.md
120
+ └──app
121
+ ├──bootstrap
122
+ │ ├──src
123
+ │ │ ├──main
124
+ │ │ │ ├──java
125
+ │ │ │ │ └──com
126
+ │ │ │ │ └──alipay
127
+ │ │ │ │ └──order
128
+ │ │ │ │ └──DemoApplication.java
129
+ │ │ │ └──resources
130
+ │ │ │ └──config
131
+ │ │ │ └──application.properties
132
+ │ │ └──test
133
+ │ │ └──java
134
+ │ │ └──com
135
+ │ │ └──alipay
136
+ │ │ └──order
137
+ │ │ └──DemoApplicationTest.java
138
+ │ └──pom.xml
139
+ ├──model
140
+ │ ├──src
141
+ │ │ ├──main
142
+ │ │ │ ├──java
143
+ │ │ │ │ └──com
144
+ │ │ │ │ └──alipay
145
+ │ │ │ │ └──order
146
+ │ │ │ │ └──model
147
+ │ │ └──test
148
+ │ │ └──java
149
+ │ │ └──com
150
+ │ │ └──alipay
151
+ │ │ └──order
152
+ │ │ └──model
153
+ │ └──pom.xml
154
+ ├──service
155
+ │ ├──src
156
+ │ │ ├──main
157
+ │ │ │ ├──java
158
+ │ │ │ │ └──com
159
+ │ │ │ │ └──alipay
160
+ │ │ │ │ └──order
161
+ │ │ │ │ └──service
162
+ │ │ └──test
163
+ │ │ └──java
164
+ │ │ └──com
165
+ │ │ └──alipay
166
+ │ │ └──order
167
+ │ │ └──service
168
+ │ └──pom.xml
169
+ └──utils
170
+ `;
171
+ }
172
+ }
173
+
174
+ codeStructure: string;
175
+
176
+ public async generateProjectStructure(projectInfo: Requirements) {
177
+ const { language, framework, requirements } = projectInfo;
178
+ const prompt = `
179
+ 我会提供一份项目的需求,包含使用的编程语言、编程框架、以及项目的具体需求,请结合具体需求,给出代码目录结构。只给出关键的文件以及文件路径即可。
180
+
181
+ 示例提问:使用 ${language} 的 ${framework} 框架,创建一个关于订单的项目
182
+ 示例回答:\`\`\`${this.generateStructurePrompt(projectInfo)}\`\`\`
183
+
184
+ (请参照示例回答,根据需求按照回答格式返回答案)
185
+ 我的问题:${requirements}
186
+ `;
187
+ const structure = await this.aiBackService.aiCodeLLama(prompt);
188
+ this.logger.log('gen structure res: ', structure);
189
+
190
+ const structureCode = /```\n?(?<code>[\s\S]*?)```/g.exec(structure);
191
+ this.logger.log('gen structure code: ', structureCode);
192
+
193
+ let flag = false;
194
+ let filePathList: string[] = [];
195
+ if (structureCode) {
196
+ filePathList = this.parseFilePath(structureCode.groups?.code || '');
197
+ const filePathRegex = /^([a-zA-Z0-9\s_-]+[\\/])*[a-zA-Z0-9\s_-]*(\.[a-zA-Z0-9]+)+$/;
198
+ if (filePathList.filter((f) => filePathRegex.test(f)).length === filePathList.length) {
199
+ flag = true;
200
+ this.codeStructure = filePathList.join('\n');
201
+ }
202
+ }
203
+
204
+ return flag ? filePathList : await this.generateProjectStructure(projectInfo);
205
+ }
206
+
207
+ private parseFilePath(input: string) {
208
+ const lines = input.split('\n');
209
+ const paths: string[] = [];
210
+ const stack: string[] = [];
211
+
212
+ let lastDepth = 0;
213
+ for (const line of lines) {
214
+ if (!/\w/.test(line)) {
215
+ continue;
216
+ }
217
+ const lineWithoutSpace = line.replace(/(├──|└──)\s/g, '$1');
218
+ const match = lineWithoutSpace.match(/(\s)/g);
219
+ const depth = match ? Math.round(match.length / 2) : 0;
220
+
221
+ // 获取文件或目录的名称
222
+ const name = lineWithoutSpace.replace(/(├──|└──|│\s+)/g, '').trim();
223
+
224
+ // 如果当前深度小于栈的深度,从栈中弹出元素
225
+ if (depth < lastDepth) {
226
+ stack.splice(depth);
227
+ }
228
+ lastDepth = depth;
229
+
230
+ while (depth < stack.length) {
231
+ stack.pop();
232
+ }
233
+
234
+ if (lineWithoutSpace.indexOf('.') !== -1) {
235
+ const path = [...stack, name].join('/');
236
+ paths.push(path);
237
+ } else {
238
+ // 如果是目录,将其添加到栈中
239
+ stack.push(name);
240
+ }
241
+ }
242
+
243
+ return paths.map((path) => path.replace(/^root\//, ''));
244
+ }
245
+
246
+ public async generateFile(filePathList: string[], projectInfo: Requirements, callback: (path: string) => void) {
247
+ switch (this.matchFramework(projectInfo.language, projectInfo.framework)) {
248
+ case FRAMEWORK.minifish:
249
+ return this.generateMinifishProject(filePathList, projectInfo.requirements, callback);
250
+ case FRAMEWORK.bigfish:
251
+ return this.generateBigfishProject(filePathList, projectInfo, callback);
252
+ default:
253
+ return this.generateCommonProject(filePathList, projectInfo, callback);
254
+ }
255
+ }
256
+
257
+ private async generateMinifishProject(fileList: string[], requirements: string, callback: (path: string) => void) {
258
+ const singleFileList: string[] = [];
259
+ const dirMap = new Map<string, string[]>();
260
+
261
+ fileList.forEach((filePath) => {
262
+ const pathArray = filePath.split('/');
263
+ if (pathArray.length > 1) {
264
+ const dir = pathArray.slice(0, -1).join('/');
265
+ if (dirMap.get(dir)) {
266
+ dirMap.get(dir)?.push(filePath);
267
+ } else {
268
+ dirMap.set(dir, [filePath]);
269
+ }
270
+ } else {
271
+ singleFileList.push(filePath);
272
+ }
273
+ });
274
+
275
+ await Promise.all(
276
+ singleFileList.map(async (path) => {
277
+ callback(path);
278
+ await this.generateMinifishSingleFile(path, requirements);
279
+ }),
280
+ );
281
+
282
+ for (const dir of dirMap.values()) {
283
+ dir.forEach((path) => callback(path));
284
+ await this.generateMinifishDirFile(dir, requirements);
285
+ }
286
+ }
287
+
288
+ private pointPrompt = `
289
+ 生成的代码需要注意以下几点:
290
+ 1. 生成的代码需要使用 Markdown 的代码块的语法。例如: \`\`\` // code \`\`\`。
291
+ 2. 支付宝小程序的 axml 语法是 a:xxx 不是 wx:xxx。例如:a:if
292
+ 3. axml文件时间绑定语法请使用 onEvent。例如:onTap、onInput
293
+ `;
294
+
295
+ private requirementPrompt = (requirements: string) => `
296
+ 项目完整需求如下: ${requirements}
297
+ 需求对应的完整的文件目录如下:\`\`\`
298
+ ${this.codeStructure}
299
+ \`\`\`
300
+ `;
301
+
302
+ private async generateMinifishSingleFile(filePath: string, requirements: string) {
303
+ const commonFile = ['mini.project.json', 'README.md', '.gitignore'];
304
+ let code;
305
+ if (commonFile.find((f) => f === filePath)) {
306
+ code = template[filePath];
307
+ } else {
308
+ const prompt = `
309
+ 基于我提供的项目需求与文件路径,生成对应的代码。我的需求可能需要多个文件才能满足,我会提供完整的目录结构,但每次我只会提供一个文件路径。
310
+ 你需要结合我的需求与完整的项目路径,先判断需要生成的文件属于需求中的哪个页面,再生成代码,
311
+ ${this.pointPrompt}
312
+ ${this.requirementPrompt(requirements)}
313
+
314
+ 需要生成的代码文件是: ${filePath}
315
+ `;
316
+
317
+ code = await this.generateFileCode(prompt);
318
+ }
319
+ await this.aiBackService.generateFileByPath(filePath, code || '{}');
320
+
321
+ return code;
322
+ }
323
+
324
+ private async generateMinifishDirFile(filePathList: string[], requirements: string) {
325
+ const axmlFile = filePathList.find((path) => path.endsWith('.axml'));
326
+ if (axmlFile) {
327
+ const axmlCode = await this.generateMinifishSingleFile(axmlFile, requirements);
328
+ const otherFile = filePathList.filter((path) => path !== axmlFile);
329
+ await Promise.all(
330
+ otherFile.map(async (path) => {
331
+ const prompt = `
332
+ 我会给出项目的需求,需求可能需要多个页面才能实现,我会提供完整的项目路径,以及其中单个页面的 axml 文件代码。
333
+ 请帮我基于需要生成的文件路径,先判断属于需求中的哪个页面的文件,再判断文件类型,根据 axml 文件代码,生成对应的 js、acss、json 文件的代码。
334
+ ${this.pointPrompt}
335
+ ${this.requirementPrompt(requirements)}
336
+
337
+ 已有的axml文件路径为: ${axmlFile}
338
+ 已有的axml文件代码为:\`\`\`
339
+ ${axmlCode}
340
+ \`\`\`
341
+
342
+ 需要生成代码文件为:${path}
343
+ `;
344
+ const code = await this.generateFileCode(prompt);
345
+ await this.aiBackService.generateFileByPath(path, code || '{}');
346
+ }),
347
+ );
348
+ } else {
349
+ await Promise.all(filePathList.map((path) => this.generateMinifishSingleFile(path, requirements)));
350
+ }
351
+ }
352
+
353
+ private async generateBigfishProject(
354
+ fileList: string[],
355
+ projectInfo: Requirements,
356
+ callback: (path: string) => void,
357
+ ) {
358
+ const templateFile = ['package.json'];
359
+ while (fileList.length) {
360
+ const part = fileList.splice(0, 1);
361
+ await Promise.all(
362
+ part.map(async (file) => {
363
+ callback(file);
364
+ if (templateFile.find((f) => f === file)) {
365
+ await this.aiBackService.generateFileByPath(file, template[file]);
366
+ } else {
367
+ await this.generateBigfishFile(file, projectInfo);
368
+ }
369
+ }),
370
+ );
371
+ }
372
+ }
373
+
374
+ private async generateBigfishFile(filePath: string, projectInfo: Requirements) {
375
+ const { requirements, language } = projectInfo;
376
+ const prompt = `
377
+ Generate corresponding code based on the project requirements and file path I provided. My requirements may require multiple files to fulfill, and I will provide the complete directory structure, but each time I will only provide one file path.
378
+ You need to combine my requirements with the complete project path, first determine which page the file to be generated belongs to in the requirements, and then generate the code.
379
+ The project uses front-end technologies such as ${language} and less, and framework is Bigfish with React, the generated code should comply with the corresponding file type.
380
+ (The Bigfish framework is an extension of umi.js. The file content can refer to umi.js, but if some function import from umi, it needs to be replaced to bigfish.)
381
+ Project requirements is: ${requirements}
382
+ Project dir strucutre is:\`\`\`
383
+ ${this.codeStructure}
384
+ \`\`\`
385
+
386
+ (The generated code needs to be wrapped in Markdown code block syntax and just reply code only)
387
+ The code need generate is: ${filePath}`;
388
+
389
+ const code = await this.generateFileCode(prompt);
390
+ await this.aiBackService.generateFileByPath(filePath, code || '');
391
+
392
+ return code;
393
+ }
394
+
395
+ private async generateCommonProject(fileList: string[], projectInfo: Requirements, callback: (path: string) => void) {
396
+ while (fileList.length) {
397
+ const part = fileList.splice(0, 1);
398
+ await Promise.all(
399
+ part.map(async (file) => {
400
+ callback(file);
401
+ await this.generateCommonFile(file, projectInfo);
402
+ }),
403
+ );
404
+ }
405
+ }
406
+
407
+ private async generateCommonFile(filePath: string, projectInfo: Requirements) {
408
+ const { requirements, language, framework } = projectInfo;
409
+ const prompt = `
410
+ Generate corresponding code based on the project requirements and file path I provided. My requirements may require multiple files to fulfill, and I will provide the complete directory structure, but each time I will only provide one file path.
411
+ You need to combine my requirements with the complete project path, first determine which page the file to be generated belongs to in the requirements, and then generate the code.
412
+ The project uses ${language}, and framework is ${framework}, the generated code should comply with the corresponding file type.
413
+ Project requirements is: ${requirements}
414
+ Project dir strucutre is:\`\`\`
415
+ ${this.codeStructure}
416
+ \`\`\`
417
+
418
+ (The generated code needs to be wrapped in Markdown code block syntax and just reply code only)
419
+ The code need generate is: ${filePath}`;
420
+
421
+ const code = await this.generateFileCode(prompt);
422
+ await this.aiBackService.generateFileByPath(filePath, code || '');
423
+
424
+ return code;
425
+ }
426
+
427
+ private async generateFileCode(prompt: string) {
428
+ let times = 0;
429
+ let code;
430
+ while (!code && times < 5) {
431
+ const content = await this.aiBackService.aiCodeLLama(prompt);
432
+ this.logger.log('gen file content: ', content);
433
+ const codeMatch = /```\w*\n(\/\/\s.*\n)?(?<code>[\s\S]*?)```/g.exec(content);
434
+ code = codeMatch && codeMatch.groups?.code ? codeMatch.groups?.code : content;
435
+ this.logger.log('gen file code: ', code);
436
+ times++;
437
+ }
438
+
439
+ return code;
440
+ }
441
+
442
+ public async clearWorkspace() {
443
+ await this.aiBackService.clearWorkspace();
444
+ }
445
+ }
446
+
447
+ const template = {
448
+ 'mini.project.json': `
449
+ {
450
+ "enableAppxNg": true
451
+ }
452
+ `,
453
+ 'README.md': `
454
+ 一个简单的示例 Demo
455
+ `,
456
+ '.gitignore': `
457
+ logs
458
+ node_modules
459
+ npm-debug.log
460
+ dist
461
+ public
462
+ .DS_Store
463
+ .nyc_output
464
+ .basement
465
+ .umi
466
+ .umi-production
467
+ .idea
468
+ .history
469
+ .node
470
+ `,
471
+ 'package.json': `
472
+ {
473
+ "name": "new project",
474
+ "version": "1.0.0",
475
+ "private": true,
476
+ "scripts": {
477
+ "build": "bigfish build",
478
+ "ci": "bigfish lint",
479
+ "dev": "bigfish dev",
480
+ "devs": "cross-env MOCK=none bigfish dev",
481
+ "format": "prettier --cache --write .",
482
+ "postinstall": "bigfish setup",
483
+ "lint": "bigfish lint",
484
+ "lint:fix": "bigfish lint --fix",
485
+ "oneapi": "npm run oneapi:service && npm run oneapi:mock",
486
+ "oneapi:mock": "bigfish api generate mock",
487
+ "oneapi:service": "bigfish api generate service",
488
+ "prepare": "husky install",
489
+ "setup": "bigfish setup",
490
+ "test": "bigfish test"
491
+ },
492
+ "dependencies": {
493
+ "@alipay/bigfish": "^4.0.157",
494
+ "@alipay/tech-ui": "^3.2.2",
495
+ "@monaco-editor/react": "^4.4.6",
496
+ "antd": "conch-v5"
497
+ },
498
+ "devDependencies": {
499
+ "@ali/ci": "^4.43.0",
500
+ "cross-env": "^7.0.3",
501
+ "husky": "^8.0.1",
502
+ "lint-staged": "^13.0.3",
503
+ "prettier": "^2.7.1",
504
+ "typescript": "^4.1.2"
505
+ },
506
+ "engines": {
507
+ "install-node": "16"
508
+ },
509
+ "ci": {
510
+ "type": "aci",
511
+ "coverage": false
512
+ }
513
+ }
514
+ `,
515
+ };
@@ -0,0 +1,65 @@
1
+ /* eslint-disable no-console */
2
+ import { Injectable, Autowired } from '@opensumi/di';
3
+ import { CommandService, CommandRegistry, Command } from '@opensumi/ide-core-common';
4
+
5
+ import { AiGPTBackSerivcePath } from '../../common';
6
+
7
+ @Injectable()
8
+ export class AiSumiService {
9
+ @Autowired(AiGPTBackSerivcePath)
10
+ aiBackService: any;
11
+
12
+ @Autowired(CommandService)
13
+ protected readonly commandService: CommandService;
14
+
15
+ @Autowired(CommandRegistry)
16
+ protected readonly commandRegistryService: CommandRegistry;
17
+
18
+ private taskPrompt(command: string[]) {
19
+ return `
20
+ 在我的系统中有一些 Command,通过这些命令可以实现一些功能。请通过分析我的问题,找到我想要实现的功能,匹配适合的 Command。
21
+ 请参照下面的示例问答,按照示例回答的格式返回。如果找不到合适的命令,请返回未找到合适命令。
22
+ 以下是系统内的全部 Command: ${command.join('、')}、workbench.action.openGlobalKeybindings、editor.action.setEncoding`;
23
+ }
24
+
25
+ public async message(input: string): Promise<Command | undefined> {
26
+ const commands = this.commandRegistryService.getCommands();
27
+ const commandIds = commands.filter((c) => !!c.label).map((c) => c.delegate || c.id);
28
+ const step = 50;
29
+ const partCommands = Array.from({ length: Math.round(commandIds.length / step) }, (_, index) => index).map((i) =>
30
+ commandIds.slice(i * step, (i + 1) * step),
31
+ );
32
+
33
+ const res = await Promise.all(partCommands.map((c) => this.requestCommand(c, input)));
34
+ const passibleCommands = res.filter((r) => !!r);
35
+
36
+ let finalCommand = passibleCommands[0];
37
+
38
+ if (passibleCommands.length > 1) {
39
+ finalCommand = await this.requestCommand(passibleCommands, input);
40
+ }
41
+
42
+ return commands.find((c) => c.id === finalCommand || c.delegate === finalCommand);
43
+ }
44
+
45
+ private async requestCommand(commands: string[], question: string) {
46
+ const cotPrompt = `
47
+ ${this.taskPrompt(commands)}
48
+ 提问: 打开全局快捷键配置
49
+ 回答: 通过分析需求「打开全局快捷键配置」, 可以获取到一些关键词: open、keybinding、global。通过这些关键词可以在 Command 的列表内匹配到相关的命令是: \`workbench.action.openGlobalKeybindings\`
50
+ 提问: 增加字体大小
51
+ 回答: 通过分析需求「增加字体大小」,可以获取到一些关键词:font、zoomIn、zoomOut。通过这些关键词,无法在 Command 列表中找到合适的命令。
52
+ 提问: ${question}`;
53
+
54
+ const res = await this.aiBackService.aiAntGlm(cotPrompt);
55
+ const answerCommand = this.matchCommand(res.data);
56
+ return commands.find((c) => c === answerCommand) || '';
57
+ }
58
+
59
+ private matchCommand(answer: string): string {
60
+ const commandReg = /`(?<command>\S+)`/;
61
+ const command = commandReg.exec(answer);
62
+
63
+ return command ? command.groups?.command || '' : '';
64
+ }
65
+ }
@@ -0,0 +1,22 @@
1
+ import { Injectable } from '@opensumi/di';
2
+ import { URI, MaybePromise, Emitter, Event } from '@opensumi/ide-core-browser';
3
+ import { IEditorDocumentModelContentProvider } from '@opensumi/ide-editor/lib/browser/index';
4
+
5
+ @Injectable()
6
+ export class AiCodeDocumentProvider implements IEditorDocumentModelContentProvider {
7
+ private _onDidChangeContent = new Emitter<URI>();
8
+
9
+ onDidChangeContent: Event<URI> = this._onDidChangeContent.event;
10
+
11
+ provideEditorDocumentModelContent(uri: URI, encoding?: string): MaybePromise<string> {
12
+ return '';
13
+ }
14
+
15
+ isReadonly(uri: URI): MaybePromise<boolean> {
16
+ return false;
17
+ }
18
+
19
+ handlesScheme(scheme: string) {
20
+ return scheme === 'AI';
21
+ }
22
+ }