tabby-ai-assistant 1.0.5 → 1.0.6

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 (116) hide show
  1. package/dist/components/chat/ai-sidebar.component.d.ts +147 -0
  2. package/dist/components/chat/chat-interface.component.d.ts +38 -6
  3. package/dist/components/settings/general-settings.component.d.ts +6 -3
  4. package/dist/components/settings/provider-config.component.d.ts +25 -12
  5. package/dist/components/terminal/command-preview.component.d.ts +38 -0
  6. package/dist/index-full.d.ts +8 -0
  7. package/dist/index-minimal.d.ts +3 -0
  8. package/dist/index.d.ts +7 -3
  9. package/dist/index.js +1 -2
  10. package/dist/providers/tabby/ai-config.provider.d.ts +57 -5
  11. package/dist/providers/tabby/ai-hotkey.provider.d.ts +8 -14
  12. package/dist/providers/tabby/ai-toolbar-button.provider.d.ts +8 -9
  13. package/dist/services/chat/ai-sidebar.service.d.ts +89 -0
  14. package/dist/services/chat/chat-history.service.d.ts +78 -0
  15. package/dist/services/chat/chat-session.service.d.ts +57 -2
  16. package/dist/services/context/compaction.d.ts +90 -0
  17. package/dist/services/context/manager.d.ts +69 -0
  18. package/dist/services/context/memory.d.ts +116 -0
  19. package/dist/services/context/token-budget.d.ts +105 -0
  20. package/dist/services/core/ai-assistant.service.d.ts +40 -1
  21. package/dist/services/core/checkpoint.service.d.ts +130 -0
  22. package/dist/services/platform/escape-sequence.service.d.ts +132 -0
  23. package/dist/services/platform/platform-detection.service.d.ts +146 -0
  24. package/dist/services/providers/anthropic-provider.service.d.ts +5 -0
  25. package/dist/services/providers/base-provider.service.d.ts +6 -1
  26. package/dist/services/providers/glm-provider.service.d.ts +5 -0
  27. package/dist/services/providers/minimax-provider.service.d.ts +10 -1
  28. package/dist/services/providers/ollama-provider.service.d.ts +76 -0
  29. package/dist/services/providers/openai-compatible.service.d.ts +5 -0
  30. package/dist/services/providers/openai-provider.service.d.ts +5 -0
  31. package/dist/services/providers/vllm-provider.service.d.ts +82 -0
  32. package/dist/services/terminal/buffer-analyzer.service.d.ts +128 -0
  33. package/dist/services/terminal/terminal-manager.service.d.ts +185 -0
  34. package/dist/services/terminal/terminal-tools.service.d.ts +79 -0
  35. package/dist/types/ai.types.d.ts +92 -0
  36. package/dist/types/provider.types.d.ts +1 -1
  37. package/package.json +7 -10
  38. package/src/components/chat/ai-sidebar.component.ts +945 -0
  39. package/src/components/chat/chat-input.component.html +9 -24
  40. package/src/components/chat/chat-input.component.scss +3 -2
  41. package/src/components/chat/chat-interface.component.html +77 -69
  42. package/src/components/chat/chat-interface.component.scss +54 -4
  43. package/src/components/chat/chat-interface.component.ts +250 -34
  44. package/src/components/chat/chat-settings.component.scss +4 -4
  45. package/src/components/chat/chat-settings.component.ts +22 -11
  46. package/src/components/common/error-message.component.html +15 -0
  47. package/src/components/common/error-message.component.scss +77 -0
  48. package/src/components/common/error-message.component.ts +2 -96
  49. package/src/components/common/loading-spinner.component.html +4 -0
  50. package/src/components/common/loading-spinner.component.scss +57 -0
  51. package/src/components/common/loading-spinner.component.ts +2 -63
  52. package/src/components/security/consent-dialog.component.html +22 -0
  53. package/src/components/security/consent-dialog.component.scss +34 -0
  54. package/src/components/security/consent-dialog.component.ts +2 -55
  55. package/src/components/security/password-prompt.component.html +19 -0
  56. package/src/components/security/password-prompt.component.scss +30 -0
  57. package/src/components/security/password-prompt.component.ts +2 -54
  58. package/src/components/security/risk-confirm-dialog.component.html +8 -12
  59. package/src/components/security/risk-confirm-dialog.component.scss +8 -5
  60. package/src/components/security/risk-confirm-dialog.component.ts +6 -6
  61. package/src/components/settings/ai-settings-tab.component.html +16 -20
  62. package/src/components/settings/ai-settings-tab.component.scss +8 -5
  63. package/src/components/settings/ai-settings-tab.component.ts +12 -12
  64. package/src/components/settings/general-settings.component.html +8 -17
  65. package/src/components/settings/general-settings.component.scss +6 -3
  66. package/src/components/settings/general-settings.component.ts +62 -22
  67. package/src/components/settings/provider-config.component.html +19 -39
  68. package/src/components/settings/provider-config.component.scss +182 -39
  69. package/src/components/settings/provider-config.component.ts +119 -7
  70. package/src/components/settings/security-settings.component.scss +1 -1
  71. package/src/components/terminal/ai-toolbar-button.component.html +8 -0
  72. package/src/components/terminal/ai-toolbar-button.component.scss +20 -0
  73. package/src/components/terminal/ai-toolbar-button.component.ts +2 -30
  74. package/src/components/terminal/command-preview.component.html +61 -0
  75. package/src/components/terminal/command-preview.component.scss +72 -0
  76. package/src/components/terminal/command-preview.component.ts +127 -140
  77. package/src/components/terminal/command-suggestion.component.html +23 -0
  78. package/src/components/terminal/command-suggestion.component.scss +55 -0
  79. package/src/components/terminal/command-suggestion.component.ts +2 -77
  80. package/src/index-minimal.ts +32 -0
  81. package/src/index.ts +94 -11
  82. package/src/index.ts.backup +165 -0
  83. package/src/providers/tabby/ai-config.provider.ts +60 -51
  84. package/src/providers/tabby/ai-hotkey.provider.ts +23 -39
  85. package/src/providers/tabby/ai-settings-tab.provider.ts +2 -2
  86. package/src/providers/tabby/ai-toolbar-button.provider.ts +29 -24
  87. package/src/services/chat/ai-sidebar.service.ts +258 -0
  88. package/src/services/chat/chat-history.service.ts +308 -0
  89. package/src/services/chat/chat-history.service.ts.backup +239 -0
  90. package/src/services/chat/chat-session.service.ts +276 -3
  91. package/src/services/context/compaction.ts +483 -0
  92. package/src/services/context/manager.ts +442 -0
  93. package/src/services/context/memory.ts +519 -0
  94. package/src/services/context/token-budget.ts +422 -0
  95. package/src/services/core/ai-assistant.service.ts +280 -5
  96. package/src/services/core/ai-provider-manager.service.ts +2 -2
  97. package/src/services/core/checkpoint.service.ts +619 -0
  98. package/src/services/platform/escape-sequence.service.ts +499 -0
  99. package/src/services/platform/platform-detection.service.ts +494 -0
  100. package/src/services/providers/anthropic-provider.service.ts +28 -1
  101. package/src/services/providers/base-provider.service.ts +7 -1
  102. package/src/services/providers/glm-provider.service.ts +28 -1
  103. package/src/services/providers/minimax-provider.service.ts +209 -11
  104. package/src/services/providers/ollama-provider.service.ts +445 -0
  105. package/src/services/providers/openai-compatible.service.ts +9 -0
  106. package/src/services/providers/openai-provider.service.ts +9 -0
  107. package/src/services/providers/vllm-provider.service.ts +463 -0
  108. package/src/services/security/risk-assessment.service.ts +6 -2
  109. package/src/services/terminal/buffer-analyzer.service.ts +594 -0
  110. package/src/services/terminal/terminal-manager.service.ts +748 -0
  111. package/src/services/terminal/terminal-tools.service.ts +441 -0
  112. package/src/styles/ai-assistant.scss +78 -6
  113. package/src/types/ai.types.ts +144 -0
  114. package/src/types/provider.types.ts +1 -1
  115. package/tsconfig.json +9 -9
  116. package/webpack.config.js +28 -6
@@ -0,0 +1,57 @@
1
+ .spinner-container {
2
+ display: flex;
3
+ flex-direction: column;
4
+ align-items: center;
5
+ justify-content: center;
6
+ padding: 2rem;
7
+
8
+ &.small {
9
+ padding: 1rem;
10
+
11
+ .spinner {
12
+ width: 24px;
13
+ height: 24px;
14
+ border-width: 2px;
15
+ }
16
+
17
+ .spinner-message {
18
+ font-size: 0.75rem;
19
+ margin-top: 0.5rem;
20
+ }
21
+ }
22
+
23
+ &.medium {
24
+ .spinner {
25
+ width: 36px;
26
+ height: 36px;
27
+ border-width: 3px;
28
+ }
29
+ }
30
+
31
+ &.large {
32
+ .spinner {
33
+ width: 48px;
34
+ height: 48px;
35
+ border-width: 4px;
36
+ }
37
+ }
38
+ }
39
+
40
+ .spinner {
41
+ border: 3px solid var(--ai-border);
42
+ border-top-color: var(--ai-primary);
43
+ border-radius: 50%;
44
+ animation: spin 0.8s linear infinite;
45
+ }
46
+
47
+ .spinner-message {
48
+ margin-top: 1rem;
49
+ color: var(--ai-secondary);
50
+ font-size: 0.875rem;
51
+ }
52
+
53
+ @keyframes spin {
54
+ to {
55
+ transform: rotate(360deg);
56
+ }
57
+ }
@@ -2,69 +2,8 @@ import { Component, Input } from '@angular/core';
2
2
 
3
3
  @Component({
4
4
  selector: 'app-loading-spinner',
5
- template: `
6
- <div class="spinner-container" [ngClass]="size">
7
- <div class="spinner"></div>
8
- <p *ngIf="message" class="spinner-message">{{ message }}</p>
9
- </div>
10
- `,
11
- styles: [`
12
- .spinner-container {
13
- display: flex;
14
- flex-direction: column;
15
- align-items: center;
16
- justify-content: center;
17
- padding: 2rem;
18
-
19
- &.small {
20
- padding: 1rem;
21
-
22
- .spinner {
23
- width: 24px;
24
- height: 24px;
25
- border-width: 2px;
26
- }
27
-
28
- .spinner-message {
29
- font-size: 0.75rem;
30
- margin-top: 0.5rem;
31
- }
32
- }
33
-
34
- &.medium {
35
- .spinner {
36
- width: 36px;
37
- height: 36px;
38
- border-width: 3px;
39
- }
40
- }
41
-
42
- &.large {
43
- .spinner {
44
- width: 48px;
45
- height: 48px;
46
- border-width: 4px;
47
- }
48
- }
49
- }
50
-
51
- .spinner {
52
- border: 3px solid var(--ai-border);
53
- border-top-color: var(--ai-primary);
54
- border-radius: 50%;
55
- animation: spin 0.8s linear infinite;
56
- }
57
-
58
- .spinner-message {
59
- margin-top: 1rem;
60
- color: var(--ai-secondary);
61
- font-size: 0.875rem;
62
- }
63
-
64
- @keyframes spin {
65
- to { transform: rotate(360deg); }
66
- }
67
- `]
5
+ templateUrl: './loading-spinner.component.html',
6
+ styleUrls: ['./loading-spinner.component.scss']
68
7
  })
69
8
  export class LoadingSpinnerComponent {
70
9
  @Input() size: 'small' | 'medium' | 'large' = 'medium';
@@ -0,0 +1,22 @@
1
+ <div class="consent-dialog">
2
+ <div class="dialog-header">
3
+ <i class="fa fa-question-circle"></i>
4
+ <h3>确认执行</h3>
5
+ </div>
6
+ <div class="dialog-content">
7
+ <p>确定要执行此命令吗?</p>
8
+ <div class="command-preview">
9
+ <code>{{ command }}</code>
10
+ </div>
11
+ <div class="checkbox-group">
12
+ <label>
13
+ <input type="checkbox" [(ngModel)]="rememberChoice">
14
+ 记住我的选择(30天内不再提示)
15
+ </label>
16
+ </div>
17
+ </div>
18
+ <div class="dialog-footer">
19
+ <button class="btn btn-secondary" (click)="cancel()">取消</button>
20
+ <button class="btn btn-primary" (click)="confirm()">确认执行</button>
21
+ </div>
22
+ </div>
@@ -0,0 +1,34 @@
1
+ .consent-dialog {
2
+ background: var(--ai-bg-primary);
3
+ border-radius: 0.5rem;
4
+ max-width: 500px;
5
+ }
6
+
7
+ .dialog-header {
8
+ padding: 1.5rem;
9
+ text-align: center;
10
+ border-bottom: 1px solid var(--ai-border);
11
+ }
12
+
13
+ .dialog-content {
14
+ padding: 1.5rem;
15
+ }
16
+
17
+ .command-preview {
18
+ background: var(--ai-bg-secondary);
19
+ padding: 0.75rem;
20
+ border-radius: 0.375rem;
21
+ margin: 1rem 0;
22
+ }
23
+
24
+ .checkbox-group {
25
+ margin-top: 1rem;
26
+ }
27
+
28
+ .dialog-footer {
29
+ padding: 1rem 1.5rem;
30
+ display: flex;
31
+ justify-content: flex-end;
32
+ gap: 0.5rem;
33
+ border-top: 1px solid var(--ai-border);
34
+ }
@@ -4,61 +4,8 @@ import { RiskLevel } from '../../types/security.types';
4
4
 
5
5
  @Component({
6
6
  selector: 'app-consent-dialog',
7
- template: `
8
- <div class="consent-dialog">
9
- <div class="dialog-header">
10
- <i class="icon-help-circle"></i>
11
- <h3>确认执行</h3>
12
- </div>
13
- <div class="dialog-content">
14
- <p>确定要执行此命令吗?</p>
15
- <div class="command-preview">
16
- <code>{{ command }}</code>
17
- </div>
18
- <div class="checkbox-group">
19
- <label>
20
- <input type="checkbox" [(ngModel)]="rememberChoice">
21
- 记住我的选择(30天内不再提示)
22
- </label>
23
- </div>
24
- </div>
25
- <div class="dialog-footer">
26
- <button class="btn btn-secondary" (click)="cancel()">取消</button>
27
- <button class="btn btn-primary" (click)="confirm()">确认执行</button>
28
- </div>
29
- </div>
30
- `,
31
- styles: [`
32
- .consent-dialog {
33
- background: var(--ai-bg-primary);
34
- border-radius: 0.5rem;
35
- max-width: 500px;
36
- }
37
- .dialog-header {
38
- padding: 1.5rem;
39
- text-align: center;
40
- border-bottom: 1px solid var(--ai-border);
41
- }
42
- .dialog-content {
43
- padding: 1.5rem;
44
- }
45
- .command-preview {
46
- background: var(--ai-bg-secondary);
47
- padding: 0.75rem;
48
- border-radius: 0.375rem;
49
- margin: 1rem 0;
50
- }
51
- .checkbox-group {
52
- margin-top: 1rem;
53
- }
54
- .dialog-footer {
55
- padding: 1rem 1.5rem;
56
- display: flex;
57
- justify-content: flex-end;
58
- gap: 0.5rem;
59
- border-top: 1px solid var(--ai-border);
60
- }
61
- `]
7
+ templateUrl: './consent-dialog.component.html',
8
+ styleUrls: ['./consent-dialog.component.scss']
62
9
  })
63
10
  export class ConsentDialogComponent {
64
11
  @Input() command: string = '';
@@ -0,0 +1,19 @@
1
+ <div class="password-prompt">
2
+ <div class="prompt-header">
3
+ <i class="fa fa-lock"></i>
4
+ <h3>密码验证</h3>
5
+ </div>
6
+ <div class="prompt-content">
7
+ <p>请输入密码以执行此高风险操作:</p>
8
+ <input type="password" class="form-control" [(ngModel)]="password" (keydown.enter)="submit()" placeholder="输入密码"
9
+ #passwordInput>
10
+ <div *ngIf="errorMessage" class="error-message">
11
+ <i class="fa fa-exclamation-circle"></i>
12
+ {{ errorMessage }}
13
+ </div>
14
+ </div>
15
+ <div class="prompt-footer">
16
+ <button class="btn btn-secondary" (click)="cancel()">取消</button>
17
+ <button class="btn btn-primary" (click)="submit()" [disabled]="!password">确认</button>
18
+ </div>
19
+ </div>
@@ -0,0 +1,30 @@
1
+ .password-prompt {
2
+ background: var(--ai-bg-primary);
3
+ border-radius: 0.5rem;
4
+ max-width: 400px;
5
+ margin: 0 auto;
6
+ }
7
+
8
+ .prompt-header {
9
+ padding: 1.5rem;
10
+ text-align: center;
11
+ border-bottom: 1px solid var(--ai-border);
12
+ }
13
+
14
+ .prompt-content {
15
+ padding: 1.5rem;
16
+ }
17
+
18
+ .error-message {
19
+ margin-top: 0.75rem;
20
+ color: var(--ai-danger);
21
+ font-size: 0.875rem;
22
+ }
23
+
24
+ .prompt-footer {
25
+ padding: 1rem 1.5rem;
26
+ display: flex;
27
+ justify-content: flex-end;
28
+ gap: 0.5rem;
29
+ border-top: 1px solid var(--ai-border);
30
+ }
@@ -3,60 +3,8 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
3
3
 
4
4
  @Component({
5
5
  selector: 'app-password-prompt',
6
- template: `
7
- <div class="password-prompt">
8
- <div class="prompt-header">
9
- <i class="icon-lock"></i>
10
- <h3>密码验证</h3>
11
- </div>
12
- <div class="prompt-content">
13
- <p>请输入密码以执行此高风险操作:</p>
14
- <input
15
- type="password"
16
- class="form-control"
17
- [(ngModel)]="password"
18
- (keydown.enter)="submit()"
19
- placeholder="输入密码"
20
- #passwordInput>
21
- <div *ngIf="errorMessage" class="error-message">
22
- <i class="icon-alert-circle"></i>
23
- {{ errorMessage }}
24
- </div>
25
- </div>
26
- <div class="prompt-footer">
27
- <button class="btn btn-secondary" (click)="cancel()">取消</button>
28
- <button class="btn btn-primary" (click)="submit()" [disabled]="!password">确认</button>
29
- </div>
30
- </div>
31
- `,
32
- styles: [`
33
- .password-prompt {
34
- background: var(--ai-bg-primary);
35
- border-radius: 0.5rem;
36
- max-width: 400px;
37
- margin: 0 auto;
38
- }
39
- .prompt-header {
40
- padding: 1.5rem;
41
- text-align: center;
42
- border-bottom: 1px solid var(--ai-border);
43
- }
44
- .prompt-content {
45
- padding: 1.5rem;
46
- }
47
- .error-message {
48
- margin-top: 0.75rem;
49
- color: var(--ai-danger);
50
- font-size: 0.875rem;
51
- }
52
- .prompt-footer {
53
- padding: 1rem 1.5rem;
54
- display: flex;
55
- justify-content: flex-end;
56
- gap: 0.5rem;
57
- border-top: 1px solid var(--ai-border);
58
- }
59
- `]
6
+ templateUrl: './password-prompt.component.html',
7
+ styleUrls: ['./password-prompt.component.scss']
60
8
  })
61
9
  export class PasswordPromptComponent {
62
10
  @Input() title: string = '密码验证';
@@ -6,7 +6,7 @@
6
6
  <span>{{ getRiskLevelText() }}</span>
7
7
  </div>
8
8
  <button type="button" class="close-button" (click)="cancel()">
9
- <i class="icon-x"></i>
9
+ <i class="fa fa-times"></i>
10
10
  </button>
11
11
  </div>
12
12
 
@@ -30,7 +30,7 @@
30
30
  <div class="command-display">
31
31
  <code>{{ command }}</code>
32
32
  <button class="btn-copy" (click)="navigator.clipboard.writeText(command)" title="复制">
33
- <i class="icon-copy"></i>
33
+ <i class="fa fa-copy"></i>
34
34
  </button>
35
35
  </div>
36
36
  </div>
@@ -45,7 +45,7 @@
45
45
  <label>安全建议:</label>
46
46
  <ul class="suggestions-list">
47
47
  <li *ngFor="let suggestion of suggestions">
48
- <i class="icon-lightbulb"></i>
48
+ <i class="fa fa-lightbulb-o"></i>
49
49
  <span>{{ suggestion }}</span>
50
50
  </li>
51
51
  </ul>
@@ -55,7 +55,7 @@
55
55
  <!-- 额外警告(高风险) -->
56
56
  <div *ngIf="isHighRisk()" class="high-risk-warning">
57
57
  <div class="warning-box">
58
- <i class="icon-alert-triangle"></i>
58
+ <i class="fa fa-exclamation-triangle"></i>
59
59
  <div class="warning-content">
60
60
  <strong>⚠️ 重要提示</strong>
61
61
  <p *ngIf="riskLevel === 'critical'">
@@ -72,16 +72,12 @@
72
72
  <!-- 底部按钮 -->
73
73
  <div class="dialog-footer">
74
74
  <button type="button" class="btn btn-secondary" (click)="cancel()">
75
- <i class="icon-x"></i>
75
+ <i class="fa fa-times"></i>
76
76
  取消
77
77
  </button>
78
- <button
79
- type="button"
80
- class="btn btn-danger"
81
- [ngClass]="{ 'btn-critical': isHighRisk() }"
82
- (click)="confirm()">
83
- <i [class]="isHighRisk() ? 'icon-alert-triangle' : 'icon-check'"></i>
78
+ <button type="button" class="btn btn-danger" [ngClass]="{ 'btn-critical': isHighRisk() }" (click)="confirm()">
79
+ <i [class]="isHighRisk() ? 'fa fa-exclamation-triangle' : 'fa fa-check'"></i>
84
80
  {{ isHighRisk() ? '仍要执行' : '确认执行' }}
85
81
  </button>
86
82
  </div>
87
- </div>
83
+ </div>
@@ -272,7 +272,7 @@
272
272
  color: white;
273
273
 
274
274
  &:hover {
275
- background-color: darken(#6c757d, 7.5%);
275
+ background-color: #5a6268;
276
276
  }
277
277
  }
278
278
 
@@ -281,7 +281,7 @@
281
281
  color: white;
282
282
 
283
283
  &:hover {
284
- background-color: darken(#dc3545, 7.5%);
284
+ background-color: #c82333;
285
285
  }
286
286
  }
287
287
 
@@ -292,7 +292,7 @@
292
292
 
293
293
  &:hover {
294
294
  animation: none;
295
- background-color: darken(#dc3545, 10%);
295
+ background-color: #bd2130;
296
296
  }
297
297
  }
298
298
  }
@@ -300,9 +300,12 @@
300
300
 
301
301
  /* 动画 */
302
302
  @keyframes pulse {
303
- 0%, 100% {
303
+
304
+ 0%,
305
+ 100% {
304
306
  box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7);
305
307
  }
308
+
306
309
  50% {
307
310
  box-shadow: 0 0 0 10px rgba(220, 53, 69, 0);
308
311
  }
@@ -357,4 +360,4 @@
357
360
  justify-content: center;
358
361
  }
359
362
  }
360
- }
363
+ }
@@ -15,7 +15,7 @@ export class RiskConfirmDialogComponent {
15
15
 
16
16
  @Output() confirmed = new EventEmitter<boolean>();
17
17
 
18
- constructor(public activeModal: NgbActiveModal) {}
18
+ constructor(public activeModal: NgbActiveModal) { }
19
19
 
20
20
  /**
21
21
  * 确认执行
@@ -75,15 +75,15 @@ export class RiskConfirmDialogComponent {
75
75
  getRiskLevelIcon(): string {
76
76
  switch (this.riskLevel) {
77
77
  case RiskLevel.LOW:
78
- return 'icon-check-circle';
78
+ return 'fa fa-check-circle';
79
79
  case RiskLevel.MEDIUM:
80
- return 'icon-warning';
80
+ return 'fa fa-exclamation-triangle';
81
81
  case RiskLevel.HIGH:
82
- return 'icon-alert-triangle';
82
+ return 'fa fa-exclamation-circle';
83
83
  case RiskLevel.CRITICAL:
84
- return 'icon-alert-octagon';
84
+ return 'fa fa-ban';
85
85
  default:
86
- return 'icon-help-circle';
86
+ return 'fa fa-question-circle';
87
87
  }
88
88
  }
89
89
 
@@ -3,42 +3,39 @@
3
3
  <div class="settings-header">
4
4
  <div class="header-content">
5
5
  <h2>
6
- <i class="icon-robot"></i>
6
+ <i class="fa fa-robot"></i>
7
7
  AI助手设置
8
8
  </h2>
9
9
  <div class="header-status">
10
10
  <div class="status-indicator" [class.enabled]="isEnabled">
11
- <i class="icon-power"></i>
11
+ <i class="fa fa-power-off"></i>
12
12
  <span>{{ isEnabled ? '已启用' : '已禁用' }}</span>
13
13
  </div>
14
14
  <div class="provider-info" *ngIf="isEnabled">
15
- <i class="icon-provider"></i>
15
+ <i class="fa fa-cloud"></i>
16
16
  <span>当前提供商: {{ currentProvider }}</span>
17
17
  </div>
18
18
  </div>
19
19
  </div>
20
20
  <div class="header-actions">
21
21
  <button class="btn-icon" (click)="toggleEnabled()" [title]="isEnabled ? '禁用AI助手' : '启用AI助手'">
22
- <i [class]="isEnabled ? 'icon-pause' : 'icon-play'"></i>
22
+ <i [class]="isEnabled ? 'fa fa-pause' : 'fa fa-play'"></i>
23
23
  </button>
24
24
  <button class="btn-icon" (click)="refreshProviderStatus()" title="刷新状态">
25
- <i class="icon-refresh"></i>
25
+ <i class="fa fa-refresh"></i>
26
26
  </button>
27
27
  <button class="btn-icon" (click)="exportConfig()" title="导出配置">
28
- <i class="icon-export"></i>
28
+ <i class="fa fa-download"></i>
29
29
  </button>
30
30
  <button class="btn-icon" (click)="importConfig()" title="导入配置">
31
- <i class="icon-import"></i>
31
+ <i class="fa fa-upload"></i>
32
32
  </button>
33
33
  </div>
34
34
  </div>
35
35
 
36
36
  <!-- 标签页导航 -->
37
37
  <div class="tabs-nav" *ngIf="isEnabled">
38
- <button
39
- *ngFor="let tab of tabs"
40
- class="tab-button"
41
- [class.active]="activeTab === tab.id"
38
+ <button *ngFor="let tab of tabs" class="tab-button" [class.active]="activeTab === tab.id"
42
39
  (click)="switchTab(tab.id)">
43
40
  <i [class]="tab.icon"></i>
44
41
  <span>{{ tab.label }}</span>
@@ -54,9 +51,7 @@
54
51
 
55
52
  <!-- AI提供商设置 -->
56
53
  <div *ngIf="activeTab === 'providers'" class="tab-content">
57
- <app-provider-config
58
- [providerStatus]="providerStatus"
59
- (refreshStatus)="refreshProviderStatus()"
54
+ <app-provider-config [providerStatus]="providerStatus" (refreshStatus)="refreshProviderStatus()"
60
55
  (switchProvider)="switchProvider($event)">
61
56
  </app-provider-config>
62
57
  </div>
@@ -80,11 +75,11 @@
80
75
  <div class="settings-section">
81
76
  <h4>配置管理</h4>
82
77
  <button class="btn btn-primary" (click)="validateConfig()">
83
- <i class="icon-check"></i>
78
+ <i class="fa fa-check"></i>
84
79
  验证配置
85
80
  </button>
86
81
  <button class="btn btn-warning" (click)="resetToDefaults()">
87
- <i class="icon-refresh"></i>
82
+ <i class="fa fa-refresh"></i>
88
83
  重置为默认
89
84
  </button>
90
85
  </div>
@@ -94,7 +89,8 @@
94
89
  <h4>日志设置</h4>
95
90
  <div class="log-level-selector">
96
91
  <label>日志级别</label>
97
- <select class="form-control" [(ngModel)]="config.logLevel" (change)="config.setLogLevel(config.logLevel)">
92
+ <select class="form-control" [(ngModel)]="config.logLevel"
93
+ (change)="config.setLogLevel(config.logLevel)">
98
94
  <option value="debug">Debug (详细)</option>
99
95
  <option value="info">Info (信息)</option>
100
96
  <option value="warn">Warn (警告)</option>
@@ -128,13 +124,13 @@
128
124
  <!-- 禁用提示 -->
129
125
  <div class="disabled-message" *ngIf="!isEnabled">
130
126
  <div class="message-content">
131
- <i class="icon-pause-circle"></i>
127
+ <i class="fa fa-pause-circle fa-3x"></i>
132
128
  <h3>AI助手已禁用</h3>
133
129
  <p>点击上方按钮启用AI助手功能</p>
134
130
  <button class="btn btn-primary" (click)="toggleEnabled()">
135
- <i class="icon-play"></i>
131
+ <i class="fa fa-play"></i>
136
132
  启用AI助手
137
133
  </button>
138
134
  </div>
139
135
  </div>
140
- </div>
136
+ </div>
@@ -194,7 +194,7 @@
194
194
  color: white;
195
195
 
196
196
  &:hover {
197
- background-color: darken(#007bff, 7.5%);
197
+ background-color: #0069d9;
198
198
  }
199
199
  }
200
200
 
@@ -203,7 +203,7 @@
203
203
  color: var(--ai-dark);
204
204
 
205
205
  &:hover {
206
- background-color: darken(#ffc107, 7.5%);
206
+ background-color: #e0a800;
207
207
  }
208
208
  }
209
209
  }
@@ -301,7 +301,7 @@
301
301
  font-size: 1rem;
302
302
 
303
303
  &:hover {
304
- background-color: darken(#007bff, 7.5%);
304
+ background-color: #0069d9;
305
305
  transform: translateY(-1px);
306
306
  }
307
307
  }
@@ -310,9 +310,12 @@
310
310
 
311
311
  /* 动画 */
312
312
  @keyframes pulse {
313
- 0%, 100% {
313
+
314
+ 0%,
315
+ 100% {
314
316
  opacity: 1;
315
317
  }
318
+
316
319
  50% {
317
320
  opacity: 0.5;
318
321
  }
@@ -368,4 +371,4 @@
368
371
  }
369
372
  }
370
373
  }
371
- }
374
+ }