tabby-ai-assistant 1.0.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 (134) hide show
  1. package/README.md +232 -0
  2. package/dist/components/chat/chat-input.component.d.ts +65 -0
  3. package/dist/components/chat/chat-interface.component.d.ts +71 -0
  4. package/dist/components/chat/chat-message.component.d.ts +53 -0
  5. package/dist/components/chat/chat-settings.component.d.ts +62 -0
  6. package/dist/components/common/error-message.component.d.ts +11 -0
  7. package/dist/components/common/loading-spinner.component.d.ts +4 -0
  8. package/dist/components/security/consent-dialog.component.d.ts +11 -0
  9. package/dist/components/security/password-prompt.component.d.ts +10 -0
  10. package/dist/components/security/risk-confirm-dialog.component.d.ts +36 -0
  11. package/dist/components/settings/ai-settings-tab.component.d.ts +72 -0
  12. package/dist/components/settings/general-settings.component.d.ts +60 -0
  13. package/dist/components/settings/provider-config.component.d.ts +182 -0
  14. package/dist/components/settings/security-settings.component.d.ts +23 -0
  15. package/dist/components/terminal/ai-toolbar-button.component.d.ts +10 -0
  16. package/dist/components/terminal/command-preview.component.d.ts +15 -0
  17. package/dist/components/terminal/command-suggestion.component.d.ts +16 -0
  18. package/dist/index.d.ts +8 -0
  19. package/dist/index.js +2 -0
  20. package/dist/index.js.LICENSE.txt +18 -0
  21. package/dist/main.d.ts +8 -0
  22. package/dist/providers/tabby/ai-config.provider.d.ts +18 -0
  23. package/dist/providers/tabby/ai-hotkey.provider.d.ts +21 -0
  24. package/dist/providers/tabby/ai-settings-tab.provider.d.ts +11 -0
  25. package/dist/providers/tabby/ai-toolbar-button.provider.d.ts +17 -0
  26. package/dist/services/chat/chat-history.service.d.ts +67 -0
  27. package/dist/services/chat/chat-session.service.d.ts +58 -0
  28. package/dist/services/chat/command-generator.service.d.ts +49 -0
  29. package/dist/services/core/ai-assistant.service.d.ts +88 -0
  30. package/dist/services/core/ai-provider-manager.service.d.ts +119 -0
  31. package/dist/services/core/config-provider.service.d.ts +137 -0
  32. package/dist/services/core/logger.service.d.ts +21 -0
  33. package/dist/services/providers/anthropic-provider.service.d.ts +39 -0
  34. package/dist/services/providers/base-provider.service.d.ts +137 -0
  35. package/dist/services/providers/glm-provider.service.d.ts +91 -0
  36. package/dist/services/providers/minimax-provider.service.d.ts +93 -0
  37. package/dist/services/providers/openai-compatible.service.d.ts +39 -0
  38. package/dist/services/providers/openai-provider.service.d.ts +38 -0
  39. package/dist/services/security/consent-manager.service.d.ts +65 -0
  40. package/dist/services/security/password-manager.service.d.ts +67 -0
  41. package/dist/services/security/risk-assessment.service.d.ts +65 -0
  42. package/dist/services/security/security-validator.service.d.ts +36 -0
  43. package/dist/services/terminal/command-analyzer.service.d.ts +20 -0
  44. package/dist/services/terminal/context-menu.service.d.ts +24 -0
  45. package/dist/services/terminal/hotkey.service.d.ts +28 -0
  46. package/dist/services/terminal/terminal-context.service.d.ts +100 -0
  47. package/dist/types/ai.types.d.ts +107 -0
  48. package/dist/types/provider.types.d.ts +105 -0
  49. package/dist/types/security.types.d.ts +85 -0
  50. package/dist/types/terminal.types.d.ts +150 -0
  51. package/dist/utils/encryption.utils.d.ts +83 -0
  52. package/dist/utils/formatting.utils.d.ts +106 -0
  53. package/dist/utils/validation.utils.d.ts +83 -0
  54. package/integration-test-output.txt +50 -0
  55. package/integration-tests/api-integration.test.ts +183 -0
  56. package/jest.config.js +47 -0
  57. package/package.json +73 -0
  58. package/setup-jest.ts +37 -0
  59. package/src/components/chat/chat-input.component.html +61 -0
  60. package/src/components/chat/chat-input.component.scss +183 -0
  61. package/src/components/chat/chat-input.component.ts +149 -0
  62. package/src/components/chat/chat-interface.component.html +119 -0
  63. package/src/components/chat/chat-interface.component.scss +354 -0
  64. package/src/components/chat/chat-interface.component.ts +224 -0
  65. package/src/components/chat/chat-message.component.html +65 -0
  66. package/src/components/chat/chat-message.component.scss +178 -0
  67. package/src/components/chat/chat-message.component.ts +93 -0
  68. package/src/components/chat/chat-settings.component.html +132 -0
  69. package/src/components/chat/chat-settings.component.scss +172 -0
  70. package/src/components/chat/chat-settings.component.ts +168 -0
  71. package/src/components/common/error-message.component.ts +124 -0
  72. package/src/components/common/loading-spinner.component.ts +72 -0
  73. package/src/components/security/consent-dialog.component.ts +77 -0
  74. package/src/components/security/password-prompt.component.ts +79 -0
  75. package/src/components/security/risk-confirm-dialog.component.html +87 -0
  76. package/src/components/security/risk-confirm-dialog.component.scss +360 -0
  77. package/src/components/security/risk-confirm-dialog.component.ts +96 -0
  78. package/src/components/settings/ai-settings-tab.component.html +140 -0
  79. package/src/components/settings/ai-settings-tab.component.scss +371 -0
  80. package/src/components/settings/ai-settings-tab.component.ts +193 -0
  81. package/src/components/settings/general-settings.component.html +103 -0
  82. package/src/components/settings/general-settings.component.scss +285 -0
  83. package/src/components/settings/general-settings.component.ts +123 -0
  84. package/src/components/settings/provider-config.component.html +95 -0
  85. package/src/components/settings/provider-config.component.scss +60 -0
  86. package/src/components/settings/provider-config.component.ts +206 -0
  87. package/src/components/settings/security-settings.component.html +51 -0
  88. package/src/components/settings/security-settings.component.scss +66 -0
  89. package/src/components/settings/security-settings.component.ts +71 -0
  90. package/src/components/terminal/ai-toolbar-button.component.ts +49 -0
  91. package/src/components/terminal/command-preview.component.ts +185 -0
  92. package/src/components/terminal/command-suggestion.component.ts +128 -0
  93. package/src/index.ts +163 -0
  94. package/src/main.ts +16 -0
  95. package/src/providers/tabby/ai-config.provider.ts +70 -0
  96. package/src/providers/tabby/ai-hotkey.provider.ts +55 -0
  97. package/src/providers/tabby/ai-settings-tab.provider.ts +18 -0
  98. package/src/providers/tabby/ai-toolbar-button.provider.ts +49 -0
  99. package/src/services/chat/chat-history.service.ts +239 -0
  100. package/src/services/chat/chat-session.service.spec.ts +249 -0
  101. package/src/services/chat/chat-session.service.ts +180 -0
  102. package/src/services/chat/command-generator.service.ts +301 -0
  103. package/src/services/core/ai-assistant.service.ts +334 -0
  104. package/src/services/core/ai-provider-manager.service.ts +314 -0
  105. package/src/services/core/config-provider.service.ts +347 -0
  106. package/src/services/core/logger.service.ts +104 -0
  107. package/src/services/providers/anthropic-provider.service.ts +373 -0
  108. package/src/services/providers/base-provider.service.ts +369 -0
  109. package/src/services/providers/glm-provider.service.ts +467 -0
  110. package/src/services/providers/minimax-provider.service.ts +427 -0
  111. package/src/services/providers/openai-compatible.service.ts +394 -0
  112. package/src/services/providers/openai-provider.service.ts +376 -0
  113. package/src/services/security/consent-manager.service.ts +332 -0
  114. package/src/services/security/password-manager.service.ts +188 -0
  115. package/src/services/security/risk-assessment.service.ts +340 -0
  116. package/src/services/security/security-validator.service.ts +143 -0
  117. package/src/services/terminal/command-analyzer.service.ts +43 -0
  118. package/src/services/terminal/context-menu.service.ts +45 -0
  119. package/src/services/terminal/hotkey.service.ts +53 -0
  120. package/src/services/terminal/terminal-context.service.ts +317 -0
  121. package/src/styles/ai-assistant.scss +449 -0
  122. package/src/types/ai.types.ts +133 -0
  123. package/src/types/provider.types.ts +147 -0
  124. package/src/types/security.types.ts +103 -0
  125. package/src/types/terminal.types.ts +186 -0
  126. package/src/utils/encryption.utils.spec.ts +250 -0
  127. package/src/utils/encryption.utils.ts +271 -0
  128. package/src/utils/formatting.utils.ts +359 -0
  129. package/src/utils/validation.utils.spec.ts +225 -0
  130. package/src/utils/validation.utils.ts +314 -0
  131. package/tsconfig.json +45 -0
  132. package/webpack-docker.config.js +42 -0
  133. package/webpack.config.js +59 -0
  134. package/webpack.config.js.backup +57 -0
@@ -0,0 +1,301 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Observable, from } from 'rxjs';
3
+ import { map, switchMap } from 'rxjs/operators';
4
+ import { CommandRequest, CommandResponse, ChatRequest, ChatMessage, MessageRole } from '../../types/ai.types';
5
+ import { TerminalContext, TerminalError } from '../../types/terminal.types';
6
+ import { AiAssistantService } from '../core/ai-assistant.service';
7
+ import { TerminalContextService } from '../terminal/terminal-context.service';
8
+ import { SecurityValidatorService } from '../security/security-validator.service';
9
+ import { LoggerService } from '../core/logger.service';
10
+
11
+ @Injectable({ providedIn: 'root' })
12
+ export class CommandGeneratorService {
13
+ constructor(
14
+ private aiService: AiAssistantService,
15
+ private terminalContext: TerminalContextService,
16
+ private securityValidator: SecurityValidatorService,
17
+ private logger: LoggerService
18
+ ) {}
19
+
20
+ /**
21
+ * 生成命令(基于终端上下文)
22
+ */
23
+ async generateCommand(request: CommandRequest): Promise<CommandResponse> {
24
+ this.logger.info('Generating command', { request });
25
+
26
+ try {
27
+ // 获取终端上下文
28
+ const context = this.terminalContext.getCurrentContext();
29
+ const error = this.terminalContext.getLastError();
30
+
31
+ // 构建增强的提示词
32
+ const enhancedPrompt = this.buildEnhancedPrompt(request, context, error);
33
+
34
+ // 构建聊天请求
35
+ const chatRequest: ChatRequest = {
36
+ messages: [
37
+ {
38
+ id: this.generateId(),
39
+ role: MessageRole.SYSTEM,
40
+ content: this.getSystemPrompt(),
41
+ timestamp: new Date()
42
+ },
43
+ {
44
+ id: this.generateId(),
45
+ role: MessageRole.USER,
46
+ content: enhancedPrompt,
47
+ timestamp: new Date()
48
+ }
49
+ ],
50
+ maxTokens: 500,
51
+ temperature: 0.3 // 使用较低温度确保命令的准确性
52
+ };
53
+
54
+ // 调用AI提供商
55
+ const response = await this.aiService.chat(chatRequest);
56
+
57
+ // 解析AI响应
58
+ const commandResponse = this.parseAiResponse(response.message.content);
59
+
60
+ // 安全验证
61
+ const validation = await this.securityValidator.validateAndConfirm(
62
+ commandResponse.command,
63
+ commandResponse.explanation,
64
+ context
65
+ );
66
+
67
+ if (!validation.approved) {
68
+ throw new Error(`Command blocked by security validator: ${validation.reason}`);
69
+ }
70
+
71
+ this.logger.info('Command generated successfully', { commandResponse });
72
+ return commandResponse;
73
+
74
+ } catch (error) {
75
+ this.logger.error('Failed to generate command', error);
76
+ throw error;
77
+ }
78
+ }
79
+
80
+ /**
81
+ * 从选择文本生成命令
82
+ */
83
+ async generateFromSelection(selection: string): Promise<CommandResponse> {
84
+ const request: CommandRequest = {
85
+ naturalLanguage: selection,
86
+ context: this.buildTerminalContext()
87
+ };
88
+
89
+ return this.generateCommand(request);
90
+ }
91
+
92
+ /**
93
+ * 从错误生成修复命令
94
+ */
95
+ async generateFixForError(error: TerminalError): Promise<CommandResponse> {
96
+ const context = this.terminalContext.getCurrentContext();
97
+
98
+ const request: CommandRequest = {
99
+ naturalLanguage: `修复错误:${error.message}`,
100
+ context: {
101
+ currentDirectory: context?.session.cwd,
102
+ operatingSystem: context?.systemInfo.platform,
103
+ shell: context?.session.shell,
104
+ environment: context?.session.environment
105
+ },
106
+ constraints: {
107
+ forbiddenCommands: ['rm -rf /', 'sudo rm -rf /', 'format']
108
+ }
109
+ };
110
+
111
+ return this.generateCommand(request);
112
+ }
113
+
114
+ /**
115
+ * 生成智能建议
116
+ */
117
+ async generateSuggestions(input: string): Promise<string[]> {
118
+ const context = this.terminalContext.getCurrentContext();
119
+
120
+ const prompt = `
121
+ 基于当前终端状态,为输入"${input}"生成3-5个可能的命令建议。
122
+
123
+ 当前上下文:
124
+ - 目录:${context?.session.cwd}
125
+ - Shell:${context?.session.shell}
126
+ - 系统:${context?.systemInfo.platform}
127
+ - 最近命令:${context?.recentCommands.slice(0, 5).join(', ')}
128
+
129
+ 请直接返回命令列表,每行一个,不要解释。
130
+ `;
131
+
132
+ try {
133
+ const response = await this.aiService.chat({
134
+ messages: [
135
+ {
136
+ id: this.generateId(),
137
+ role: MessageRole.USER,
138
+ content: prompt,
139
+ timestamp: new Date()
140
+ }
141
+ ],
142
+ maxTokens: 200,
143
+ temperature: 0.5
144
+ });
145
+
146
+ const suggestions = response.message.content
147
+ .split('\n')
148
+ .map(line => line.trim())
149
+ .filter(line => line.length > 0)
150
+ .slice(0, 5);
151
+
152
+ return suggestions;
153
+
154
+ } catch (error) {
155
+ this.logger.error('Failed to generate suggestions', error);
156
+ return [];
157
+ }
158
+ }
159
+
160
+ /**
161
+ * 构建增强提示词
162
+ */
163
+ private buildEnhancedPrompt(
164
+ request: CommandRequest,
165
+ context: TerminalContext | null,
166
+ error: TerminalError | null
167
+ ): string {
168
+ let prompt = `请将以下自然语言描述转换为准确的命令:\n\n"${request.naturalLanguage}"\n\n`;
169
+
170
+ // 添加终端上下文
171
+ if (context) {
172
+ prompt += `\n当前终端状态:\n`;
173
+ prompt += `- 当前目录:${context.session.cwd}\n`;
174
+ prompt += `- Shell类型:${context.session.shell}\n`;
175
+ prompt += `- 操作系统:${context.systemInfo.platform}\n`;
176
+ prompt += `- 用户:${context.session.user}\n`;
177
+
178
+ if (context.recentCommands.length > 0) {
179
+ prompt += `- 最近执行的命令:${context.recentCommands.slice(0, 3).join(', ')}\n`;
180
+ }
181
+
182
+ if (context.projectInfo) {
183
+ prompt += `- 检测到项目类型:${context.projectInfo.type}\n`;
184
+ prompt += `- 项目根目录:${context.projectInfo.root}\n`;
185
+ }
186
+ }
187
+
188
+ // 添加错误信息(如果有)
189
+ if (error) {
190
+ prompt += `\n当前错误信息:\n`;
191
+ prompt += `- 错误类型:${error.type}\n`;
192
+ prompt += `- 错误消息:${error.message}\n`;
193
+ prompt += `- 失败命令:${error.command}\n`;
194
+ prompt += `- 退出码:${error.exitCode}\n`;
195
+ }
196
+
197
+ // 添加环境变量
198
+ if (context?.session.environment) {
199
+ const importantEnvVars = ['PATH', 'HOME', 'USER', 'PWD', 'SHELL'];
200
+ const envInfo = importantEnvVars
201
+ .filter(key => context.session.environment[key])
202
+ .map(key => `${key}=${context.session.environment[key]}`)
203
+ .join(', ');
204
+
205
+ if (envInfo) {
206
+ prompt += `\n重要环境变量:${envInfo}\n`;
207
+ }
208
+ }
209
+
210
+ // 添加约束
211
+ if (request.constraints) {
212
+ prompt += `\n约束条件:\n`;
213
+ if (request.constraints.maxLength) {
214
+ prompt += `- 命令最大长度:${request.constraints.maxLength}字符\n`;
215
+ }
216
+ if (request.constraints.allowedCommands?.length) {
217
+ prompt += `- 允许使用的命令:${request.constraints.allowedCommands.join(', ')}\n`;
218
+ }
219
+ if (request.constraints.forbiddenCommands?.length) {
220
+ prompt += `- 禁止使用的命令:${request.constraints.forbiddenCommands.join(', ')}\n`;
221
+ }
222
+ }
223
+
224
+ prompt += `\n请按照以下JSON格式返回:\n`;
225
+ prompt += `{\n`;
226
+ prompt += ` "command": "具体的命令",\n`;
227
+ prompt += ` "explanation": "命令的解释说明",\n`;
228
+ prompt += ` "confidence": 0.95\n`;
229
+ prompt += `}\n`;
230
+
231
+ return prompt;
232
+ }
233
+
234
+ /**
235
+ * 获取系统提示词
236
+ */
237
+ private getSystemPrompt(): string {
238
+ return `你是一个专业的终端命令生成助手。你的任务是:
239
+
240
+ 1. 将自然语言描述转换为准确、高效的终端命令
241
+ 2. 考虑当前操作系统和Shell环境
242
+ 3. 优先使用安全、最佳实践的命令
243
+ 4. 提供清晰的命令解释
244
+ 5. 考虑当前工作目录和上下文环境
245
+
246
+ 请始终返回有效的命令,避免危险操作(如删除系统文件、格式化磁盘等)。
247
+ 如果无法确定准确的命令,请明确说明并提供替代方案。`;
248
+ }
249
+
250
+ /**
251
+ * 解析AI响应
252
+ */
253
+ private parseAiResponse(content: string): CommandResponse {
254
+ try {
255
+ // 尝试解析JSON
256
+ const jsonMatch = content.match(/\{[\s\S]*\}/);
257
+ if (jsonMatch) {
258
+ const parsed = JSON.parse(jsonMatch[0]);
259
+ return {
260
+ command: parsed.command || '',
261
+ explanation: parsed.explanation || '',
262
+ confidence: parsed.confidence || 0.5,
263
+ alternatives: parsed.alternatives || []
264
+ };
265
+ }
266
+ } catch (error) {
267
+ this.logger.warn('Failed to parse JSON response, fallback to text parsing', error);
268
+ }
269
+
270
+ // 备用解析:提取命令和解释
271
+ const lines = content.split('\n').map(l => l.trim()).filter(l => l);
272
+ const command = lines[0] || '';
273
+ const explanation = lines.slice(1).join(' ') || 'AI生成的命令建议';
274
+
275
+ return {
276
+ command,
277
+ explanation,
278
+ confidence: 0.5
279
+ };
280
+ }
281
+
282
+ /**
283
+ * 构建终端上下文
284
+ */
285
+ private buildTerminalContext(): CommandRequest['context'] {
286
+ const context = this.terminalContext.getCurrentContext();
287
+ return {
288
+ currentDirectory: context?.session.cwd,
289
+ operatingSystem: context?.systemInfo.platform,
290
+ shell: context?.session.shell,
291
+ environment: context?.session.environment
292
+ };
293
+ }
294
+
295
+ /**
296
+ * 生成唯一ID
297
+ */
298
+ private generateId(): string {
299
+ return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
300
+ }
301
+ }
@@ -0,0 +1,334 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { Observable, from, throwError } from 'rxjs';
3
+ import { map, catchError, tap } from 'rxjs/operators';
4
+ import { ChatMessage, MessageRole, ChatRequest, ChatResponse, CommandRequest, CommandResponse, ExplainRequest, ExplainResponse } from '../../types/ai.types';
5
+ import { AiProviderManagerService } from './ai-provider-manager.service';
6
+ import { ConfigProviderService } from './config-provider.service';
7
+ import { TerminalContextService } from '../terminal/terminal-context.service';
8
+ import { LoggerService } from './logger.service';
9
+
10
+ @Injectable({ providedIn: 'root' })
11
+ export class AiAssistantService {
12
+ constructor(
13
+ private providerManager: AiProviderManagerService,
14
+ private config: ConfigProviderService,
15
+ private terminalContext: TerminalContextService,
16
+ private logger: LoggerService
17
+ ) {}
18
+
19
+ /**
20
+ * 初始化AI助手
21
+ */
22
+ initialize(): void {
23
+ this.logger.info('Initializing AI Assistant...');
24
+
25
+ // 检查是否启用
26
+ if (!this.config.isEnabled()) {
27
+ this.logger.info('AI Assistant is disabled in configuration');
28
+ return;
29
+ }
30
+
31
+ // 设置默认提供商
32
+ const defaultProvider = this.config.getDefaultProvider();
33
+ if (defaultProvider && this.providerManager.hasProvider(defaultProvider)) {
34
+ this.providerManager.setActiveProvider(defaultProvider);
35
+ }
36
+
37
+ this.logger.info('AI Assistant initialized successfully');
38
+ }
39
+
40
+ /**
41
+ * 聊天功能
42
+ */
43
+ async chat(request: ChatRequest): Promise<ChatResponse> {
44
+ const activeProvider = this.providerManager.getActiveProvider();
45
+ if (!activeProvider) {
46
+ throw new Error('No active AI provider available');
47
+ }
48
+
49
+ this.logger.info('Processing chat request', { provider: activeProvider.name });
50
+
51
+ try {
52
+ // 检查提供商能力
53
+ if (!activeProvider.supportsCapability('chat' as any)) {
54
+ throw new Error(`Provider ${activeProvider.name} does not support chat capability`);
55
+ }
56
+
57
+ const response = await activeProvider.chat(request);
58
+ this.logger.info('Chat request completed successfully');
59
+ return response;
60
+
61
+ } catch (error) {
62
+ this.logger.error('Chat request failed', error);
63
+ throw error;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * 生成命令
69
+ */
70
+ async generateCommand(request: CommandRequest): Promise<CommandResponse> {
71
+ const activeProvider = this.providerManager.getActiveProvider();
72
+ if (!activeProvider) {
73
+ throw new Error('No active AI provider available');
74
+ }
75
+
76
+ this.logger.info('Processing command generation request', { provider: activeProvider.name });
77
+
78
+ try {
79
+ // 检查提供商能力
80
+ if (!activeProvider.supportsCapability('command_generation' as any)) {
81
+ throw new Error(`Provider ${activeProvider.name} does not support command generation capability`);
82
+ }
83
+
84
+ const response = await activeProvider.generateCommand(request);
85
+ this.logger.info('Command generation completed successfully');
86
+ return response;
87
+
88
+ } catch (error) {
89
+ this.logger.error('Command generation failed', error);
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * 解释命令
96
+ */
97
+ async explainCommand(request: ExplainRequest): Promise<ExplainResponse> {
98
+ const activeProvider = this.providerManager.getActiveProvider();
99
+ if (!activeProvider) {
100
+ throw new Error('No active AI provider available');
101
+ }
102
+
103
+ this.logger.info('Processing command explanation request', { provider: activeProvider.name });
104
+
105
+ try {
106
+ // 检查提供商能力
107
+ if (!activeProvider.supportsCapability('command_explanation' as any)) {
108
+ throw new Error(`Provider ${activeProvider.name} does not support command explanation capability`);
109
+ }
110
+
111
+ const response = await activeProvider.explainCommand(request);
112
+ this.logger.info('Command explanation completed successfully');
113
+ return response;
114
+
115
+ } catch (error) {
116
+ this.logger.error('Command explanation failed', error);
117
+ throw error;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * 分析结果
123
+ */
124
+ async analyzeResult(request: any): Promise<any> {
125
+ const activeProvider = this.providerManager.getActiveProvider();
126
+ if (!activeProvider) {
127
+ throw new Error('No active AI provider available');
128
+ }
129
+
130
+ this.logger.info('Processing result analysis request', { provider: activeProvider.name });
131
+
132
+ try {
133
+ const response = await activeProvider.analyzeResult(request);
134
+ this.logger.info('Result analysis completed successfully');
135
+ return response;
136
+
137
+ } catch (error) {
138
+ this.logger.error('Result analysis failed', error);
139
+ throw error;
140
+ }
141
+ }
142
+
143
+ /**
144
+ * 从选择生成命令
145
+ */
146
+ async generateCommandFromSelection(): Promise<CommandResponse | null> {
147
+ try {
148
+ // TODO: 从当前终端获取选中文本
149
+ const selection = '';
150
+ const context = this.terminalContext.getCurrentContext();
151
+
152
+ const request: CommandRequest = {
153
+ naturalLanguage: selection || '帮我执行上一个命令',
154
+ context: {
155
+ currentDirectory: context?.session.cwd,
156
+ operatingSystem: context?.systemInfo.platform,
157
+ shell: context?.session.shell,
158
+ environment: context?.session.environment
159
+ }
160
+ };
161
+
162
+ return this.generateCommand(request);
163
+ } catch (error) {
164
+ this.logger.error('Failed to generate command from selection', error);
165
+ return null;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * 解释当前选择
171
+ */
172
+ async explainCommandFromSelection(): Promise<ExplainResponse | null> {
173
+ try {
174
+ // TODO: 从当前终端获取选中文本
175
+ const selection = '';
176
+ if (!selection) {
177
+ return null;
178
+ }
179
+
180
+ const context = this.terminalContext.getCurrentContext();
181
+ const request: ExplainRequest = {
182
+ command: selection,
183
+ context: {
184
+ currentDirectory: context?.session.cwd,
185
+ operatingSystem: context?.systemInfo.platform
186
+ }
187
+ };
188
+
189
+ return this.explainCommand(request);
190
+ } catch (error) {
191
+ this.logger.error('Failed to explain command from selection', error);
192
+ return null;
193
+ }
194
+ }
195
+
196
+ /**
197
+ * 打开聊天界面
198
+ */
199
+ openChatInterface(): void {
200
+ this.logger.info('Opening chat interface');
201
+ // TODO: 实现打开聊天界面的逻辑
202
+ // 可以使用Tabby的窗口API或者Angular路由
203
+ }
204
+
205
+ /**
206
+ * 获取提供商状态
207
+ */
208
+ getProviderStatus(): any {
209
+ const activeProvider = this.providerManager.getActiveProvider();
210
+ const allProviders = this.providerManager.getAllProviderInfo();
211
+
212
+ return {
213
+ active: activeProvider?.getInfo(),
214
+ all: allProviders,
215
+ count: allProviders.length
216
+ };
217
+ }
218
+
219
+ /**
220
+ * 切换提供商
221
+ */
222
+ switchProvider(providerName: string): boolean {
223
+ const success = this.providerManager.setActiveProvider(providerName);
224
+ if (success) {
225
+ this.config.setDefaultProvider(providerName);
226
+ this.logger.info('Provider switched successfully', { provider: providerName });
227
+ } else {
228
+ this.logger.error('Failed to switch provider', { provider: providerName });
229
+ }
230
+ return success;
231
+ }
232
+
233
+ /**
234
+ * 获取下一个提供商
235
+ */
236
+ switchToNextProvider(): boolean {
237
+ return this.providerManager.switchToNextProvider();
238
+ }
239
+
240
+ /**
241
+ * 获取上一个提供商
242
+ */
243
+ switchToPreviousProvider(): boolean {
244
+ return this.providerManager.switchToPreviousProvider();
245
+ }
246
+
247
+ /**
248
+ * 健康检查
249
+ */
250
+ async healthCheck(): Promise<{ provider: string; status: string; latency?: number }[]> {
251
+ this.logger.info('Performing health check on all providers');
252
+ return this.providerManager.checkAllProvidersHealth();
253
+ }
254
+
255
+ /**
256
+ * 验证配置
257
+ */
258
+ async validateConfig(): Promise<{ name: string; valid: boolean; errors: string[] }[]> {
259
+ this.logger.info('Validating all provider configurations');
260
+ return this.providerManager.validateAllProviders();
261
+ }
262
+
263
+ /**
264
+ * 获取当前上下文感知提示
265
+ */
266
+ getContextAwarePrompt(basePrompt: string): string {
267
+ const context = this.terminalContext.getCurrentContext();
268
+ const error = this.terminalContext.getLastError();
269
+
270
+ let enhancedPrompt = basePrompt;
271
+
272
+ if (context) {
273
+ enhancedPrompt += `\n\n当前环境:\n`;
274
+ enhancedPrompt += `- 目录:${context.session.cwd}\n`;
275
+ enhancedPrompt += `- Shell:${context.session.shell}\n`;
276
+ enhancedPrompt += `- 系统:${context.systemInfo.platform}\n`;
277
+
278
+ if (context.recentCommands.length > 0) {
279
+ enhancedPrompt += `- 最近命令:${context.recentCommands.slice(0, 3).join(' → ')}\n`;
280
+ }
281
+
282
+ if (error) {
283
+ enhancedPrompt += `\n当前错误:\n`;
284
+ enhancedPrompt += `- 错误:${error.message}\n`;
285
+ enhancedPrompt += `- 命令:${error.command}\n`;
286
+ }
287
+ }
288
+
289
+ return enhancedPrompt;
290
+ }
291
+
292
+ /**
293
+ * 获取建议命令
294
+ */
295
+ async getSuggestedCommands(_input: string): Promise<string[]> {
296
+ const activeProvider = this.providerManager.getActiveProvider();
297
+ if (!activeProvider) {
298
+ return [];
299
+ }
300
+
301
+ try {
302
+ // TODO: 实现智能建议逻辑
303
+ // 可以基于历史命令、当前上下文等生成建议
304
+ return [];
305
+ } catch (error) {
306
+ this.logger.error('Failed to get suggested commands', error);
307
+ return [];
308
+ }
309
+ }
310
+
311
+ /**
312
+ * 分析终端错误并提供修复建议
313
+ */
314
+ async getErrorFix(error: any): Promise<CommandResponse | null> {
315
+ try {
316
+ const context = this.terminalContext.getCurrentContext();
317
+
318
+ const request: CommandRequest = {
319
+ naturalLanguage: `修复这个错误:${error.message}`,
320
+ context: {
321
+ currentDirectory: context?.session.cwd,
322
+ operatingSystem: context?.systemInfo.platform,
323
+ shell: context?.session.shell,
324
+ environment: context?.session.environment
325
+ }
326
+ };
327
+
328
+ return this.generateCommand(request);
329
+ } catch (err) {
330
+ this.logger.error('Failed to get error fix', err);
331
+ return null;
332
+ }
333
+ }
334
+ }