tabby-ai-assistant 1.0.8 → 1.0.10
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.
- package/dist/components/chat/ai-sidebar.component.d.ts +16 -3
- package/dist/components/chat/chat-input.component.d.ts +4 -0
- package/dist/components/chat/chat-interface.component.d.ts +22 -1
- package/dist/components/chat/chat-settings.component.d.ts +21 -11
- package/dist/components/settings/ai-settings-tab.component.d.ts +14 -4
- package/dist/components/settings/general-settings.component.d.ts +43 -12
- package/dist/components/settings/provider-config.component.d.ts +110 -5
- package/dist/components/settings/security-settings.component.d.ts +14 -4
- package/dist/i18n/index.d.ts +48 -0
- package/dist/i18n/translations/en-US.d.ts +5 -0
- package/dist/i18n/translations/ja-JP.d.ts +5 -0
- package/dist/i18n/translations/zh-CN.d.ts +5 -0
- package/dist/i18n/types.d.ts +198 -0
- package/dist/index.js +1 -1
- package/dist/services/chat/ai-sidebar.service.d.ts +23 -1
- package/dist/services/core/theme.service.d.ts +53 -0
- package/dist/services/core/toast.service.d.ts +15 -0
- package/package.json +1 -1
- package/src/components/chat/ai-sidebar.component.scss +468 -0
- package/src/components/chat/ai-sidebar.component.ts +47 -344
- package/src/components/chat/chat-input.component.scss +2 -2
- package/src/components/chat/chat-input.component.ts +16 -5
- package/src/components/chat/chat-interface.component.html +11 -11
- package/src/components/chat/chat-interface.component.scss +410 -4
- package/src/components/chat/chat-interface.component.ts +105 -14
- package/src/components/chat/chat-message.component.scss +3 -3
- package/src/components/chat/chat-message.component.ts +3 -2
- package/src/components/chat/chat-settings.component.html +95 -61
- package/src/components/chat/chat-settings.component.scss +224 -50
- package/src/components/chat/chat-settings.component.ts +56 -30
- package/src/components/security/risk-confirm-dialog.component.scss +7 -7
- package/src/components/settings/ai-settings-tab.component.html +27 -27
- package/src/components/settings/ai-settings-tab.component.scss +34 -20
- package/src/components/settings/ai-settings-tab.component.ts +59 -20
- package/src/components/settings/general-settings.component.html +69 -40
- package/src/components/settings/general-settings.component.scss +151 -58
- package/src/components/settings/general-settings.component.ts +168 -55
- package/src/components/settings/provider-config.component.html +183 -60
- package/src/components/settings/provider-config.component.scss +332 -153
- package/src/components/settings/provider-config.component.ts +268 -19
- package/src/components/settings/security-settings.component.html +70 -39
- package/src/components/settings/security-settings.component.scss +104 -8
- package/src/components/settings/security-settings.component.ts +48 -10
- package/src/i18n/index.ts +129 -0
- package/src/i18n/translations/en-US.ts +193 -0
- package/src/i18n/translations/ja-JP.ts +193 -0
- package/src/i18n/translations/zh-CN.ts +193 -0
- package/src/i18n/types.ts +224 -0
- package/src/index.ts +6 -0
- package/src/services/chat/ai-sidebar.service.ts +157 -5
- package/src/services/core/theme.service.ts +480 -0
- package/src/services/core/toast.service.ts +36 -0
- package/src/styles/ai-assistant.scss +8 -88
- package/src/styles/themes.scss +161 -0
|
@@ -2,17 +2,36 @@
|
|
|
2
2
|
.security-settings {
|
|
3
3
|
h3 {
|
|
4
4
|
margin-bottom: 1.5rem;
|
|
5
|
-
color:
|
|
5
|
+
color: var(--ai-text-primary);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
h4 {
|
|
9
|
+
font-size: 1.1rem;
|
|
10
|
+
margin-bottom: 1rem;
|
|
11
|
+
color: var(--ai-text-primary);
|
|
12
|
+
border-bottom: 1px solid var(--ai-border);
|
|
13
|
+
padding-bottom: 0.5rem;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.settings-section {
|
|
17
|
+
margin-bottom: 2rem;
|
|
18
|
+
padding-bottom: 1.5rem;
|
|
19
|
+
border-bottom: 1px solid var(--ai-border);
|
|
20
|
+
|
|
21
|
+
&:last-of-type {
|
|
22
|
+
border-bottom: none;
|
|
23
|
+
}
|
|
6
24
|
}
|
|
7
25
|
|
|
8
26
|
.form-group {
|
|
9
|
-
margin-bottom: 1.
|
|
27
|
+
margin-bottom: 1.25rem;
|
|
10
28
|
}
|
|
11
29
|
|
|
12
30
|
.form-label {
|
|
13
31
|
font-weight: 600;
|
|
14
32
|
margin-bottom: 0.5rem;
|
|
15
33
|
display: block;
|
|
34
|
+
color: var(--ai-text-primary);
|
|
16
35
|
|
|
17
36
|
input[type="checkbox"] {
|
|
18
37
|
margin-right: 0.5rem;
|
|
@@ -22,14 +41,16 @@
|
|
|
22
41
|
.form-control {
|
|
23
42
|
width: 100%;
|
|
24
43
|
padding: 0.5rem;
|
|
25
|
-
border: 1px solid
|
|
44
|
+
border: 1px solid var(--ai-border);
|
|
26
45
|
border-radius: 4px;
|
|
27
46
|
font-size: 14px;
|
|
47
|
+
background-color: var(--ai-bg-primary);
|
|
48
|
+
color: var(--ai-text-primary);
|
|
28
49
|
|
|
29
50
|
&:focus {
|
|
30
51
|
outline: none;
|
|
31
|
-
border-color:
|
|
32
|
-
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
|
52
|
+
border-color: var(--ai-primary);
|
|
53
|
+
box-shadow: 0 0 0 0.2rem rgba(var(--ai-primary-rgb, 0, 123, 255), 0.25);
|
|
33
54
|
}
|
|
34
55
|
}
|
|
35
56
|
|
|
@@ -37,7 +58,61 @@
|
|
|
37
58
|
display: block;
|
|
38
59
|
margin-top: 0.25rem;
|
|
39
60
|
font-size: 12px;
|
|
40
|
-
color:
|
|
61
|
+
color: var(--ai-text-secondary);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* 危险命令模式列表 */
|
|
65
|
+
.pattern-list {
|
|
66
|
+
margin-bottom: 1rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.pattern-item {
|
|
70
|
+
display: flex;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: space-between;
|
|
73
|
+
padding: 0.5rem 0.75rem;
|
|
74
|
+
background-color: var(--ai-bg-secondary);
|
|
75
|
+
border-radius: 4px;
|
|
76
|
+
margin-bottom: 0.5rem;
|
|
77
|
+
|
|
78
|
+
code {
|
|
79
|
+
font-family: 'Consolas', 'Monaco', monospace;
|
|
80
|
+
color: var(--ai-danger);
|
|
81
|
+
font-size: 13px;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.btn-icon {
|
|
86
|
+
background: none;
|
|
87
|
+
border: none;
|
|
88
|
+
color: var(--ai-text-secondary);
|
|
89
|
+
cursor: pointer;
|
|
90
|
+
padding: 0.25rem 0.5rem;
|
|
91
|
+
border-radius: 3px;
|
|
92
|
+
transition: color 0.2s, background-color 0.2s;
|
|
93
|
+
|
|
94
|
+
&:hover {
|
|
95
|
+
color: var(--ai-danger);
|
|
96
|
+
background-color: rgba(var(--ai-danger-rgb, 220, 53, 69), 0.1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.add-pattern {
|
|
101
|
+
display: flex;
|
|
102
|
+
gap: 0.5rem;
|
|
103
|
+
|
|
104
|
+
.form-control {
|
|
105
|
+
flex: 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* 操作按钮 */
|
|
110
|
+
.settings-actions {
|
|
111
|
+
display: flex;
|
|
112
|
+
gap: 1rem;
|
|
113
|
+
margin-top: 2rem;
|
|
114
|
+
padding-top: 1.5rem;
|
|
115
|
+
border-top: 1px solid var(--ai-border);
|
|
41
116
|
}
|
|
42
117
|
|
|
43
118
|
.btn {
|
|
@@ -50,11 +125,11 @@
|
|
|
50
125
|
transition: all 0.2s;
|
|
51
126
|
|
|
52
127
|
&.btn-primary {
|
|
53
|
-
background-color:
|
|
128
|
+
background-color: var(--ai-primary);
|
|
54
129
|
color: white;
|
|
55
130
|
|
|
56
131
|
&:hover {
|
|
57
|
-
background-color:
|
|
132
|
+
background-color: var(--ai-primary-hover);
|
|
58
133
|
transform: translateY(-1px);
|
|
59
134
|
}
|
|
60
135
|
|
|
@@ -62,5 +137,26 @@
|
|
|
62
137
|
transform: translateY(0);
|
|
63
138
|
}
|
|
64
139
|
}
|
|
140
|
+
|
|
141
|
+
&.btn-secondary {
|
|
142
|
+
background-color: var(--ai-secondary);
|
|
143
|
+
color: white;
|
|
144
|
+
|
|
145
|
+
&:hover {
|
|
146
|
+
background-color: var(--ai-secondary);
|
|
147
|
+
filter: brightness(0.9);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
&.btn-outline {
|
|
152
|
+
background-color: transparent;
|
|
153
|
+
border: 1px solid var(--ai-border);
|
|
154
|
+
color: var(--ai-text-secondary);
|
|
155
|
+
|
|
156
|
+
&:hover {
|
|
157
|
+
background-color: var(--ai-bg-secondary);
|
|
158
|
+
color: var(--ai-text-primary);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
65
161
|
}
|
|
66
162
|
}
|
|
@@ -1,22 +1,32 @@
|
|
|
1
|
-
import { Component, OnInit } from '@angular/core';
|
|
1
|
+
import { Component, OnInit, OnDestroy, ViewEncapsulation } from '@angular/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { takeUntil } from 'rxjs/operators';
|
|
2
4
|
import { ConfigProviderService } from '../../services/core/config-provider.service';
|
|
3
5
|
import { LoggerService } from '../../services/core/logger.service';
|
|
6
|
+
import { TranslateService } from '../../i18n';
|
|
4
7
|
|
|
5
8
|
@Component({
|
|
6
9
|
selector: 'app-security-settings',
|
|
7
10
|
templateUrl: './security-settings.component.html',
|
|
8
|
-
styleUrls: ['./security-settings.component.scss']
|
|
11
|
+
styleUrls: ['./security-settings.component.scss'],
|
|
12
|
+
encapsulation: ViewEncapsulation.None
|
|
9
13
|
})
|
|
10
|
-
export class SecuritySettingsComponent implements OnInit {
|
|
14
|
+
export class SecuritySettingsComponent implements OnInit, OnDestroy {
|
|
11
15
|
settings = {
|
|
12
16
|
enablePasswordProtection: false,
|
|
17
|
+
enableRiskAssessment: true,
|
|
18
|
+
defaultRiskLevel: 'medium',
|
|
19
|
+
enableConsentPersistence: true,
|
|
13
20
|
consentExpiryDays: 30,
|
|
14
21
|
autoApproveLowRisk: true,
|
|
15
22
|
promptForMediumRisk: true,
|
|
16
|
-
requirePasswordForHighRisk: true
|
|
17
|
-
enableRiskAssessment: true
|
|
23
|
+
requirePasswordForHighRisk: true
|
|
18
24
|
};
|
|
19
25
|
|
|
26
|
+
// 缺失的变量
|
|
27
|
+
password: string = '';
|
|
28
|
+
newPattern: string = '';
|
|
29
|
+
|
|
20
30
|
dangerousPatterns = [
|
|
21
31
|
'rm -rf /',
|
|
22
32
|
'sudo rm',
|
|
@@ -25,15 +35,35 @@ export class SecuritySettingsComponent implements OnInit {
|
|
|
25
35
|
'fork('
|
|
26
36
|
];
|
|
27
37
|
|
|
38
|
+
// 翻译对象
|
|
39
|
+
t: any;
|
|
40
|
+
|
|
41
|
+
private destroy$ = new Subject<void>();
|
|
42
|
+
|
|
28
43
|
constructor(
|
|
29
44
|
private config: ConfigProviderService,
|
|
30
|
-
private logger: LoggerService
|
|
31
|
-
|
|
45
|
+
private logger: LoggerService,
|
|
46
|
+
private translate: TranslateService
|
|
47
|
+
) {
|
|
48
|
+
this.t = this.translate.t;
|
|
49
|
+
}
|
|
32
50
|
|
|
33
51
|
ngOnInit(): void {
|
|
52
|
+
// 监听语言变化
|
|
53
|
+
this.translate.translation$.pipe(
|
|
54
|
+
takeUntil(this.destroy$)
|
|
55
|
+
).subscribe(translation => {
|
|
56
|
+
this.t = translation;
|
|
57
|
+
});
|
|
58
|
+
|
|
34
59
|
this.loadSettings();
|
|
35
60
|
}
|
|
36
61
|
|
|
62
|
+
ngOnDestroy(): void {
|
|
63
|
+
this.destroy$.next();
|
|
64
|
+
this.destroy$.complete();
|
|
65
|
+
}
|
|
66
|
+
|
|
37
67
|
private loadSettings(): void {
|
|
38
68
|
const securityConfig = this.config.getSecurityConfig();
|
|
39
69
|
this.settings = { ...this.settings, ...securityConfig };
|
|
@@ -48,6 +78,7 @@ export class SecuritySettingsComponent implements OnInit {
|
|
|
48
78
|
addDangerousPattern(pattern: string): void {
|
|
49
79
|
if (pattern && !this.dangerousPatterns.includes(pattern)) {
|
|
50
80
|
this.dangerousPatterns.push(pattern);
|
|
81
|
+
this.newPattern = '';
|
|
51
82
|
}
|
|
52
83
|
}
|
|
53
84
|
|
|
@@ -55,15 +86,22 @@ export class SecuritySettingsComponent implements OnInit {
|
|
|
55
86
|
this.dangerousPatterns.splice(index, 1);
|
|
56
87
|
}
|
|
57
88
|
|
|
89
|
+
saveSettings(): void {
|
|
90
|
+
this.config.updateSecurityConfig(this.settings);
|
|
91
|
+
this.logger.info('Security settings saved', this.settings);
|
|
92
|
+
}
|
|
93
|
+
|
|
58
94
|
resetToDefaults(): void {
|
|
59
|
-
if (confirm(
|
|
95
|
+
if (confirm(this.t.security.resetConfirm)) {
|
|
60
96
|
this.settings = {
|
|
61
97
|
enablePasswordProtection: false,
|
|
98
|
+
enableRiskAssessment: true,
|
|
99
|
+
defaultRiskLevel: 'medium',
|
|
100
|
+
enableConsentPersistence: true,
|
|
62
101
|
consentExpiryDays: 30,
|
|
63
102
|
autoApproveLowRisk: true,
|
|
64
103
|
promptForMediumRisk: true,
|
|
65
|
-
requirePasswordForHighRisk: true
|
|
66
|
-
enableRiskAssessment: true
|
|
104
|
+
requirePasswordForHighRisk: true
|
|
67
105
|
};
|
|
68
106
|
this.config.updateSecurityConfig(this.settings);
|
|
69
107
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 翻译服务
|
|
3
|
+
*/
|
|
4
|
+
import { Injectable } from '@angular/core';
|
|
5
|
+
import { BehaviorSubject, Observable } from 'rxjs';
|
|
6
|
+
import { TranslationKeys, SupportedLanguage, LanguageConfig } from './types';
|
|
7
|
+
import { zhCN } from './translations/zh-CN';
|
|
8
|
+
import { enUS } from './translations/en-US';
|
|
9
|
+
import { jaJP } from './translations/ja-JP';
|
|
10
|
+
import { ConfigProviderService } from '../services/core/config-provider.service';
|
|
11
|
+
|
|
12
|
+
const translations: Record<SupportedLanguage, TranslationKeys> = {
|
|
13
|
+
'zh-CN': zhCN,
|
|
14
|
+
'en-US': enUS,
|
|
15
|
+
'ja-JP': jaJP
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// 语言配置
|
|
19
|
+
export const languageConfigs: LanguageConfig[] = [
|
|
20
|
+
{ code: 'zh-CN', label: '简体中文', flag: '🇨🇳' },
|
|
21
|
+
{ code: 'en-US', label: 'English', flag: '🇺🇸' }
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
// 导出类型
|
|
25
|
+
export { TranslationKeys, SupportedLanguage, LanguageConfig } from './types';
|
|
26
|
+
|
|
27
|
+
@Injectable({
|
|
28
|
+
providedIn: 'root'
|
|
29
|
+
})
|
|
30
|
+
export class TranslateService {
|
|
31
|
+
private currentLang$ = new BehaviorSubject<SupportedLanguage>('zh-CN');
|
|
32
|
+
private currentTranslation$ = new BehaviorSubject<TranslationKeys>(zhCN);
|
|
33
|
+
|
|
34
|
+
constructor(private config: ConfigProviderService) {
|
|
35
|
+
// 加载保存的语言设置
|
|
36
|
+
const savedLang = this.config.get<string>('language', 'zh-CN') as SupportedLanguage;
|
|
37
|
+
this.setLanguage(savedLang || 'zh-CN');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 获取当前语言
|
|
42
|
+
*/
|
|
43
|
+
get currentLanguage(): SupportedLanguage {
|
|
44
|
+
return this.currentLang$.value;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 监听语言变化
|
|
49
|
+
*/
|
|
50
|
+
get language$(): Observable<SupportedLanguage> {
|
|
51
|
+
return this.currentLang$.asObservable();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 获取翻译对象
|
|
56
|
+
*/
|
|
57
|
+
get t(): TranslationKeys {
|
|
58
|
+
return this.currentTranslation$.value;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 监听翻译变化
|
|
63
|
+
*/
|
|
64
|
+
get translation$(): Observable<TranslationKeys> {
|
|
65
|
+
return this.currentTranslation$.asObservable();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 获取所有语言配置
|
|
70
|
+
*/
|
|
71
|
+
get languages(): LanguageConfig[] {
|
|
72
|
+
return languageConfigs;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 设置语言
|
|
77
|
+
*/
|
|
78
|
+
setLanguage(lang: SupportedLanguage): void {
|
|
79
|
+
if (translations[lang]) {
|
|
80
|
+
this.currentLang$.next(lang);
|
|
81
|
+
this.currentTranslation$.next(translations[lang]);
|
|
82
|
+
this.config.set('language', lang);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 获取翻译 - 支持插值
|
|
88
|
+
* 例如: translate('general.providerCount', { count: 3 })
|
|
89
|
+
*/
|
|
90
|
+
translate(key: string, params?: Record<string, any>): string {
|
|
91
|
+
const keys = key.split('.');
|
|
92
|
+
let value: any = this.currentTranslation$.value;
|
|
93
|
+
|
|
94
|
+
for (const k of keys) {
|
|
95
|
+
if (value && typeof value === 'object' && k in value) {
|
|
96
|
+
value = value[k];
|
|
97
|
+
} else {
|
|
98
|
+
return key; // 找不到翻译,返回 key
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (typeof value !== 'string') {
|
|
103
|
+
return key;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 处理插值 {count} -> 实际值
|
|
107
|
+
if (params) {
|
|
108
|
+
return value.replace(/\{(\w+)\}/g, (match, paramKey) => {
|
|
109
|
+
return params[paramKey]?.toString() || match;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return value;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 简写方法
|
|
118
|
+
*/
|
|
119
|
+
_(key: string, params?: Record<string, any>): string {
|
|
120
|
+
return this.translate(key, params);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 获取指定语言的翻译
|
|
125
|
+
*/
|
|
126
|
+
getTranslationForLang(lang: SupportedLanguage): TranslationKeys {
|
|
127
|
+
return translations[lang] || translations['zh-CN'];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* English translations
|
|
3
|
+
*/
|
|
4
|
+
import { TranslationKeys } from '../types';
|
|
5
|
+
|
|
6
|
+
export const enUS: TranslationKeys = {
|
|
7
|
+
common: {
|
|
8
|
+
save: 'Save',
|
|
9
|
+
cancel: 'Cancel',
|
|
10
|
+
delete: 'Delete',
|
|
11
|
+
confirm: 'Confirm',
|
|
12
|
+
enabled: 'Enabled',
|
|
13
|
+
disabled: 'Disabled',
|
|
14
|
+
online: 'Online',
|
|
15
|
+
offline: 'Offline',
|
|
16
|
+
testing: 'Testing...',
|
|
17
|
+
error: 'Error',
|
|
18
|
+
success: 'Success',
|
|
19
|
+
notConfigured: 'Not configured',
|
|
20
|
+
add: 'Add',
|
|
21
|
+
remove: 'Remove',
|
|
22
|
+
close: 'Close',
|
|
23
|
+
yes: 'Yes',
|
|
24
|
+
no: 'No',
|
|
25
|
+
reset: 'Reset',
|
|
26
|
+
default: 'Default',
|
|
27
|
+
today: 'Today'
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
settings: {
|
|
31
|
+
title: 'Settings',
|
|
32
|
+
generalTab: 'General',
|
|
33
|
+
providersTab: 'AI Providers',
|
|
34
|
+
securityTab: 'Security',
|
|
35
|
+
chatTab: 'Chat',
|
|
36
|
+
advancedTab: 'Advanced'
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
general: {
|
|
40
|
+
title: 'General Settings',
|
|
41
|
+
enableAssistant: 'Enable AI Assistant',
|
|
42
|
+
enableAssistantDesc: 'Enable or disable the entire AI assistant feature',
|
|
43
|
+
defaultProvider: 'Default AI Provider',
|
|
44
|
+
providerCount: '{count} provider(s) configured, currently using',
|
|
45
|
+
language: 'Language',
|
|
46
|
+
theme: 'Theme',
|
|
47
|
+
themeAuto: 'Follow System',
|
|
48
|
+
themeLight: 'Light Theme',
|
|
49
|
+
themeDark: 'Dark Theme',
|
|
50
|
+
themePixel: 'Pixel Retro',
|
|
51
|
+
themeTech: 'Cyber Tech',
|
|
52
|
+
shortcuts: 'Shortcuts',
|
|
53
|
+
shortcutOpenChat: 'Open AI Assistant',
|
|
54
|
+
shortcutOpenChatDesc: 'Open the chat interface',
|
|
55
|
+
shortcutGenerate: 'Generate Command',
|
|
56
|
+
shortcutGenerateDesc: 'Generate command from selection',
|
|
57
|
+
shortcutExplain: 'Explain Command',
|
|
58
|
+
shortcutExplainDesc: 'Explain current selection',
|
|
59
|
+
shortcutTip: 'Shortcuts can be customized in Tabby settings'
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
chatSettings: {
|
|
63
|
+
title: 'Chat Settings',
|
|
64
|
+
appearance: 'Appearance',
|
|
65
|
+
theme: 'Theme',
|
|
66
|
+
fontSize: 'Font Size',
|
|
67
|
+
compactMode: 'Compact Mode',
|
|
68
|
+
compactModeDesc: 'Reduce message spacing to show more content',
|
|
69
|
+
behavior: 'Chat Behavior',
|
|
70
|
+
enterToSend: 'Enter to Send',
|
|
71
|
+
enterToSendDesc: 'Shift+Enter for new line',
|
|
72
|
+
showTimestamps: 'Show Timestamps',
|
|
73
|
+
showTimestampsDesc: 'Display send time below each message',
|
|
74
|
+
showAvatars: 'Show Avatars',
|
|
75
|
+
showAvatarsDesc: 'Display user and AI avatar icons',
|
|
76
|
+
soundEnabled: 'Enable Sound',
|
|
77
|
+
soundEnabledDesc: 'Play notification sound when AI responds',
|
|
78
|
+
history: 'Chat History',
|
|
79
|
+
enableHistory: 'Enable Chat History',
|
|
80
|
+
enableHistoryDesc: 'Save chat records for next session',
|
|
81
|
+
maxHistory: 'Max History Records',
|
|
82
|
+
maxHistoryUnit: 'entries',
|
|
83
|
+
autoSave: 'Auto-save Chat',
|
|
84
|
+
autoSaveDesc: 'Automatically save after each message',
|
|
85
|
+
exportSettings: 'Export Settings',
|
|
86
|
+
clearHistory: 'Clear Chat History',
|
|
87
|
+
resetDefaults: 'Reset to Defaults',
|
|
88
|
+
clearHistoryConfirm: 'Are you sure you want to clear all chat records? This cannot be undone.',
|
|
89
|
+
resetConfirm: 'Are you sure you want to reset all settings to defaults?'
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
security: {
|
|
93
|
+
title: 'Security Settings',
|
|
94
|
+
accessControl: 'Access Control',
|
|
95
|
+
passwordProtection: 'Enable Password Protection',
|
|
96
|
+
passwordProtectionDesc: 'High-risk commands require password confirmation',
|
|
97
|
+
setPassword: 'Set Password',
|
|
98
|
+
passwordPlaceholder: 'Enter password',
|
|
99
|
+
riskAssessment: 'Risk Assessment',
|
|
100
|
+
riskAssessmentDesc: 'Automatically assess command risk level',
|
|
101
|
+
defaultRiskLevel: 'Default Risk Level',
|
|
102
|
+
riskLow: 'Low Risk',
|
|
103
|
+
riskMedium: 'Medium Risk',
|
|
104
|
+
riskHigh: 'High Risk',
|
|
105
|
+
userConsent: 'User Consent',
|
|
106
|
+
rememberConsent: 'Remember User Consent',
|
|
107
|
+
rememberConsentDesc: 'Consent valid for',
|
|
108
|
+
consentExpiryDays: 'days',
|
|
109
|
+
dangerousPatterns: 'Dangerous Command Patterns',
|
|
110
|
+
addPattern: 'Add Dangerous Pattern',
|
|
111
|
+
patternPlaceholder: 'Enter dangerous command pattern',
|
|
112
|
+
saveSettings: 'Save Settings',
|
|
113
|
+
resetDefaults: 'Restore Defaults',
|
|
114
|
+
resetConfirm: 'Are you sure you want to reset security settings to defaults?'
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
providers: {
|
|
118
|
+
title: 'AI Provider Configuration',
|
|
119
|
+
cloudProviders: 'Cloud Providers',
|
|
120
|
+
cloudProvidersDesc: 'Online services requiring API Key',
|
|
121
|
+
localProviders: 'Local Providers',
|
|
122
|
+
localProvidersDesc: 'Running locally, no API Key required',
|
|
123
|
+
configured: 'Enabled',
|
|
124
|
+
displayName: 'Display Name',
|
|
125
|
+
status: 'Status',
|
|
126
|
+
apiKey: 'API Key',
|
|
127
|
+
baseURL: 'Base URL',
|
|
128
|
+
model: 'Model',
|
|
129
|
+
saveConfig: 'Save Config',
|
|
130
|
+
testConnection: 'Test Connection',
|
|
131
|
+
detectService: 'Detect Service',
|
|
132
|
+
delete: 'Delete',
|
|
133
|
+
deleteConfirm: 'Are you sure you want to delete this provider configuration?',
|
|
134
|
+
testSuccess: 'Connection test successful!',
|
|
135
|
+
testFail: 'Connection test failed',
|
|
136
|
+
testError: 'Cannot connect to service, please ensure it is running',
|
|
137
|
+
configSaved: 'Configuration saved',
|
|
138
|
+
configDeleted: 'Configuration deleted'
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
providerNames: {
|
|
142
|
+
openai: 'OpenAI',
|
|
143
|
+
anthropic: 'Anthropic Claude',
|
|
144
|
+
minimax: 'Minimax',
|
|
145
|
+
glm: 'GLM (ChatGLM)',
|
|
146
|
+
openaiCompatible: 'OpenAI Compatible',
|
|
147
|
+
ollama: 'Ollama (Local)',
|
|
148
|
+
vllm: 'vLLM (Local)'
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
chatInterface: {
|
|
152
|
+
title: 'AI Assistant',
|
|
153
|
+
welcomeMessage: 'Hello! I am your AI Assistant',
|
|
154
|
+
inputPlaceholder: 'Enter your question or describe the command you want to execute...',
|
|
155
|
+
thinking: 'AI is thinking...',
|
|
156
|
+
executingTool: 'Executing tool...',
|
|
157
|
+
toolComplete: 'Tool execution complete',
|
|
158
|
+
errorPrefix: 'Error',
|
|
159
|
+
tipCommand: 'Tip: You can describe the command you want, e.g., "List all files in current directory"',
|
|
160
|
+
tipShortcut: 'Shortcuts: Ctrl+Shift+G to generate, Ctrl+Shift+E to explain',
|
|
161
|
+
clearChat: 'Clear Chat',
|
|
162
|
+
clearChatConfirm: 'Are you sure you want to clear the chat?',
|
|
163
|
+
exportChat: 'Export Chat',
|
|
164
|
+
switchProvider: 'Switch AI Provider',
|
|
165
|
+
providerBadge: 'Provider'
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
riskLevel: {
|
|
169
|
+
low: 'Low Risk',
|
|
170
|
+
medium: 'Medium Risk',
|
|
171
|
+
high: 'High Risk',
|
|
172
|
+
unknown: 'Unknown'
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
advancedSettings: {
|
|
176
|
+
title: 'Advanced Settings',
|
|
177
|
+
configManagement: 'Configuration Management',
|
|
178
|
+
validateConfig: 'Validate Config',
|
|
179
|
+
resetDefaults: 'Reset to Defaults',
|
|
180
|
+
logSettings: 'Log Settings',
|
|
181
|
+
logLevel: 'Log Level',
|
|
182
|
+
logLevels: {
|
|
183
|
+
debug: 'Debug',
|
|
184
|
+
info: 'Info',
|
|
185
|
+
warn: 'Warning',
|
|
186
|
+
error: 'Error'
|
|
187
|
+
},
|
|
188
|
+
systemInfo: 'System Information',
|
|
189
|
+
pluginVersion: 'Plugin Version',
|
|
190
|
+
supportedProviders: 'Supported Providers',
|
|
191
|
+
currentProvider: 'Current Provider'
|
|
192
|
+
}
|
|
193
|
+
};
|