codexmate 0.1.10 → 0.1.12
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/README.md +0 -4
- package/README.vi.md +0 -4
- package/README.zh.md +0 -4
- package/cli/agents-files.js +27 -3
- package/cli/prompt-history.js +171 -0
- package/cli/system-prompt-files.js +20 -2
- package/cli.js +23 -1
- package/package.json +1 -1
- package/web-ui/app.js +15 -0
- package/web-ui/modules/app.methods.agents.mjs +90 -0
- package/web-ui/modules/app.methods.navigation.mjs +7 -1
- package/web-ui/modules/app.methods.session-actions.mjs +57 -0
- package/web-ui/modules/app.methods.system-prompt.mjs +81 -0
- package/web-ui/modules/app.methods.web-ui-preferences.mjs +6 -0
- package/web-ui/modules/i18n/locales/en.mjs +9 -0
- package/web-ui/modules/i18n/locales/ja.mjs +9 -0
- package/web-ui/modules/i18n/locales/vi.mjs +9 -0
- package/web-ui/modules/i18n/locales/zh-tw.mjs +9 -0
- package/web-ui/modules/i18n/locales/zh.mjs +9 -0
- package/web-ui/partials/index/layout-header.html +5 -0
- package/web-ui/partials/index/panel-config-claude.html +3 -3
- package/web-ui/partials/index/panel-config-codex.html +3 -3
- package/web-ui/partials/index/panel-config-kilocode.html +5 -5
- package/web-ui/partials/index/panel-config-openclaw.html +3 -3
- package/web-ui/partials/index/panel-config-opencode.html +5 -5
- package/web-ui/partials/index/panel-prompts.html +52 -0
- package/web-ui/partials/index/panel-sessions.html +12 -0
- package/web-ui/partials/index/panel-settings.html +35 -0
- package/web-ui/res/web-ui-render.precompiled.js +517 -186
- package/web-ui/styles/modals-core.css +86 -0
- package/web-ui/styles/sessions-preview.css +38 -0
- package/web-ui/styles/titles-cards.css +2 -2
|
@@ -223,6 +223,9 @@ export function createSystemPromptMethods(options = {}) {
|
|
|
223
223
|
this.showMessage(res.error, 'error');
|
|
224
224
|
return;
|
|
225
225
|
}
|
|
226
|
+
if (typeof res.historyBucket === 'string' && res.historyBucket) {
|
|
227
|
+
this.sysHistoryBucket = res.historyBucket;
|
|
228
|
+
}
|
|
226
229
|
this.showMessage(this.t('sysPrompt.toast.saved'), 'success');
|
|
227
230
|
await this.loadSystemPrompt();
|
|
228
231
|
} catch (e) {
|
|
@@ -289,6 +292,84 @@ export function createSystemPromptMethods(options = {}) {
|
|
|
289
292
|
return { text: this.t('sysPrompt.hint.twoStepSave'), warn: false };
|
|
290
293
|
}
|
|
291
294
|
return null;
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
resolveSysHistoryBucket() {
|
|
298
|
+
if (typeof this.sysHistoryBucket === 'string' && this.sysHistoryBucket) {
|
|
299
|
+
return this.sysHistoryBucket;
|
|
300
|
+
}
|
|
301
|
+
const scope = this.sysPromptScope || 'global';
|
|
302
|
+
return 'system_' + scope + '_global';
|
|
303
|
+
},
|
|
304
|
+
|
|
305
|
+
async openSysHistory() {
|
|
306
|
+
if (this.sysHistoryLoading) return;
|
|
307
|
+
const bucket = this.resolveSysHistoryBucket();
|
|
308
|
+
this.sysHistoryVisible = true;
|
|
309
|
+
this.sysHistoryError = '';
|
|
310
|
+
await this.loadSysHistory(bucket);
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
async loadSysHistory(bucketArg) {
|
|
314
|
+
if (this.sysHistoryLoading) return;
|
|
315
|
+
const bucket = typeof bucketArg === 'string' && bucketArg.trim()
|
|
316
|
+
? bucketArg.trim()
|
|
317
|
+
: this.resolveSysHistoryBucket();
|
|
318
|
+
this.sysHistoryBucket = bucket;
|
|
319
|
+
this.sysHistoryLoading = true;
|
|
320
|
+
this.sysHistoryError = '';
|
|
321
|
+
this.sysHistoryItems = [];
|
|
322
|
+
this.sysHistoryPreviewId = '';
|
|
323
|
+
this.sysHistoryPreviewContent = '';
|
|
324
|
+
try {
|
|
325
|
+
const res = await api('list-prompt-history', { bucket });
|
|
326
|
+
if (res && res.error) {
|
|
327
|
+
this.sysHistoryError = res.error;
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
this.sysHistoryItems = Array.isArray(res) ? res : [];
|
|
331
|
+
} catch (e) {
|
|
332
|
+
this.sysHistoryError = this.t('toast.load.fail');
|
|
333
|
+
} finally {
|
|
334
|
+
this.sysHistoryLoading = false;
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
closeSysHistory() {
|
|
339
|
+
this.sysHistoryVisible = false;
|
|
340
|
+
this.sysHistoryPreviewId = '';
|
|
341
|
+
this.sysHistoryPreviewContent = '';
|
|
342
|
+
this.sysHistoryError = '';
|
|
343
|
+
},
|
|
344
|
+
|
|
345
|
+
async viewSysHistoryItem(item) {
|
|
346
|
+
if (!item || !item.id) return;
|
|
347
|
+
if (this.sysHistoryLoading) return;
|
|
348
|
+
if (this.sysHistoryPreviewId === item.id && this.sysHistoryPreviewContent) return;
|
|
349
|
+
this.sysHistoryPreviewId = item.id;
|
|
350
|
+
this.sysHistoryPreviewContent = '';
|
|
351
|
+
try {
|
|
352
|
+
const res = await api('get-prompt-history', { bucket: this.sysHistoryBucket, id: item.id });
|
|
353
|
+
if (res && res.error) {
|
|
354
|
+
this.sysHistoryError = res.error;
|
|
355
|
+
this.sysHistoryPreviewId = '';
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
this.sysHistoryPreviewContent = typeof res.content === 'string' ? res.content : '';
|
|
359
|
+
} catch (e) {
|
|
360
|
+
this.sysHistoryError = this.t('toast.load.fail');
|
|
361
|
+
this.sysHistoryPreviewId = '';
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
applySysHistoryToEditor() {
|
|
366
|
+
if (!this.sysHistoryPreviewContent) return;
|
|
367
|
+
if (this.sysPromptSaving || this.sysPromptDiffVisible) return;
|
|
368
|
+
this.sysPromptContent = this.sysHistoryPreviewContent;
|
|
369
|
+
this.sysHistoryVisible = false;
|
|
370
|
+
this.sysHistoryPreviewId = '';
|
|
371
|
+
this.sysHistoryPreviewContent = '';
|
|
372
|
+
this.showMessage(this.t('toast.history.restored'), 'success');
|
|
292
373
|
}
|
|
293
374
|
};
|
|
294
375
|
}
|
|
@@ -347,6 +347,9 @@ export function createWebUiPreferencesMethods(options = {}) {
|
|
|
347
347
|
? source.projectClaudeMdPath
|
|
348
348
|
: (typeof this.projectClaudeMdPath === 'string' ? this.projectClaudeMdPath : ''),
|
|
349
349
|
sidebarCollapsed: normalizeBoolean(hasOwn(source, 'sidebarCollapsed') ? source.sidebarCollapsed : this.sidebarCollapsed, false),
|
|
350
|
+
configModeVisibility: typeof this.normalizeConfigModeVisibility === 'function'
|
|
351
|
+
? this.normalizeConfigModeVisibility(hasOwn(source, 'configModeVisibility') ? source.configModeVisibility : this.configModeVisibility)
|
|
352
|
+
: { codex: true, claude: true, openclaw: true, opencode: true, kilocode: true },
|
|
350
353
|
starPrompted: normalizeBoolean(hasOwn(source, 'starPrompted') ? source.starPrompted : this.starPrompted, false),
|
|
351
354
|
sessionLoadNativeDialog: normalizeBoolean(hasOwn(source, 'sessionLoadNativeDialog') ? source.sessionLoadNativeDialog : this.sessionLoadNativeDialog, false),
|
|
352
355
|
language: typeof source.language === 'string'
|
|
@@ -412,6 +415,9 @@ export function createWebUiPreferencesMethods(options = {}) {
|
|
|
412
415
|
if (hasOwn(source, 'sidebarCollapsed')) {
|
|
413
416
|
this.sidebarCollapsed = normalizeBoolean(source.sidebarCollapsed, false);
|
|
414
417
|
}
|
|
418
|
+
if (hasOwn(source, 'configModeVisibility') && typeof this.normalizeConfigModeVisibility === 'function') {
|
|
419
|
+
this.configModeVisibility = this.normalizeConfigModeVisibility(source.configModeVisibility);
|
|
420
|
+
}
|
|
415
421
|
if (hasOwn(source, 'starPrompted')) {
|
|
416
422
|
this.starPrompted = normalizeBoolean(source.starPrompted, false);
|
|
417
423
|
}
|
|
@@ -34,6 +34,8 @@ const en = Object.freeze({
|
|
|
34
34
|
'common.save': 'Save',
|
|
35
35
|
'common.saveApply': 'Save & apply',
|
|
36
36
|
'common.close': 'Close',
|
|
37
|
+
'common.history': 'History',
|
|
38
|
+
'common.restoreToEditor': 'Restore to editor',
|
|
37
39
|
'common.delete': 'Delete',
|
|
38
40
|
'common.clear': 'Clear',
|
|
39
41
|
'common.show': 'Show',
|
|
@@ -463,6 +465,8 @@ const en = Object.freeze({
|
|
|
463
465
|
'toast.health.noFailedProviderSelection': 'Select at least one failed provider first',
|
|
464
466
|
'toast.health.deleteFailedProvidersDone': 'Deleted {count} failed provider(s)',
|
|
465
467
|
'toast.noChanges': 'No changes detected',
|
|
468
|
+
'toast.history.restored': 'Restored to editor, save to confirm',
|
|
469
|
+
'toast.history.empty': 'No history yet',
|
|
466
470
|
'toast.template.loadFail': 'Failed to load template',
|
|
467
471
|
'toast.template.empty': 'Template cannot be empty',
|
|
468
472
|
'toast.template.applied': 'Template applied',
|
|
@@ -692,6 +696,7 @@ const en = Object.freeze({
|
|
|
692
696
|
'sessions.preview.importNative.failedWithReason': 'Import to native failed: {reason}',
|
|
693
697
|
'sessions.preview.copyLink': 'Copy link',
|
|
694
698
|
'sessions.preview.copyPath': 'Copy path',
|
|
699
|
+
'sessions.preview.copyMessage': 'Copy message',
|
|
695
700
|
'sessions.preview.openLink': 'Open link',
|
|
696
701
|
'sessions.preview.loadingBody': 'Loading session content...',
|
|
697
702
|
'sessions.preview.emptyMsgs': 'No messages to display',
|
|
@@ -1175,6 +1180,10 @@ const en = Object.freeze({
|
|
|
1175
1180
|
'settings.timeline.style.dots': 'Dots',
|
|
1176
1181
|
'settings.timeline.style.bar': 'Bar',
|
|
1177
1182
|
'settings.timeline.style.hint': 'Dots for quick navigation, Bar for visual progress',
|
|
1183
|
+
'settings.configTabs.title': 'Config panel visibility',
|
|
1184
|
+
'settings.configTabs.meta': 'Control which configuration sub-tabs appear in the sidebar',
|
|
1185
|
+
'settings.configTabs.hint': 'Hidden sub-tabs will no longer be visible; at least one must remain',
|
|
1186
|
+
'settings.configTabs.minRequired': 'At least one configuration tab must remain visible',
|
|
1178
1187
|
|
|
1179
1188
|
'settings.reset.title': 'Config reset',
|
|
1180
1189
|
'settings.reset.meta': 'Proceed with caution',
|
|
@@ -35,6 +35,8 @@ const ja = Object.freeze({
|
|
|
35
35
|
'common.save': '保存',
|
|
36
36
|
'common.saveApply': '保存して適用',
|
|
37
37
|
'common.close': '閉じる',
|
|
38
|
+
'common.history': '履歴',
|
|
39
|
+
'common.restoreToEditor': 'エディタに復元',
|
|
38
40
|
'common.delete': '削除',
|
|
39
41
|
'common.clear': 'クリア',
|
|
40
42
|
'common.show': '表示',
|
|
@@ -469,6 +471,8 @@ const ja = Object.freeze({
|
|
|
469
471
|
'toast.health.noFailedProviderSelection': '先に失敗プロバイダーを選択してください',
|
|
470
472
|
'toast.health.deleteFailedProvidersDone': '失敗プロバイダー {count} 件を削除しました',
|
|
471
473
|
'toast.noChanges': '変更が検出されませんでした',
|
|
474
|
+
'toast.history.restored': 'エディタに復元しました。保存すると反映されます',
|
|
475
|
+
'toast.history.empty': '履歴はまだありません',
|
|
472
476
|
'toast.template.loadFail': 'テンプレートの読み込みに失敗しました',
|
|
473
477
|
'toast.template.empty': 'テンプレートは空にできません',
|
|
474
478
|
'toast.template.applied': 'テンプレートが適用されました',
|
|
@@ -695,6 +699,7 @@ const ja = Object.freeze({
|
|
|
695
699
|
'sessions.preview.openStandalone': 'スタンドアロンで開く',
|
|
696
700
|
'sessions.preview.copyLink': 'リンクをコピー',
|
|
697
701
|
'sessions.preview.copyPath': 'パスをコピー',
|
|
702
|
+
'sessions.preview.copyMessage': 'メッセージをコピー',
|
|
698
703
|
'sessions.preview.openLink': 'リンクを開く',
|
|
699
704
|
'sessions.preview.loadingBody': 'メッセージ読み込み中...',
|
|
700
705
|
'sessions.preview.emptyMsgs': 'メッセージがありません',
|
|
@@ -1177,6 +1182,10 @@ const ja = Object.freeze({
|
|
|
1177
1182
|
'settings.timeline.style.dots': 'ドット',
|
|
1178
1183
|
'settings.timeline.style.bar': 'バー',
|
|
1179
1184
|
'settings.timeline.style.hint': 'ドットは素早いナビゲーション、バーは進捗を直感的に表示',
|
|
1185
|
+
'settings.configTabs.title': '設定パネルの表示',
|
|
1186
|
+
'settings.configTabs.meta': 'サイドバーに表示する設定サブページを制御します',
|
|
1187
|
+
'settings.configTabs.hint': 'オフにすると対応するサブページが非表示になります。最低1つは必要です',
|
|
1188
|
+
'settings.configTabs.minRequired': '少なくとも1つの設定ページを表示する必要があります',
|
|
1180
1189
|
|
|
1181
1190
|
'settings.reset.title': '設定リセット',
|
|
1182
1191
|
'settings.reset.meta': '注意して操作してください',
|
|
@@ -43,6 +43,8 @@ const vi = Object.freeze({
|
|
|
43
43
|
'common.save': 'Lưu',
|
|
44
44
|
'common.saveApply': 'Lưu & áp dụng',
|
|
45
45
|
'common.close': 'Đóng',
|
|
46
|
+
'common.history': 'Lịch sử',
|
|
47
|
+
'common.restoreToEditor': 'Khôi phục vào trình soạn',
|
|
46
48
|
'common.delete': 'Xóa',
|
|
47
49
|
'common.clear': 'Xóa',
|
|
48
50
|
'common.show': 'Hiện',
|
|
@@ -410,6 +412,8 @@ const vi = Object.freeze({
|
|
|
410
412
|
'toast.health.noFailedProviderSelection': 'Hãy chọn ít nhất một provider lỗi trước',
|
|
411
413
|
'toast.health.deleteFailedProvidersDone': 'Đã xóa {count} provider lỗi',
|
|
412
414
|
'toast.noChanges': 'Không phát hiện thay đổi',
|
|
415
|
+
'toast.history.restored': 'Đã khôi phục vào trình soạn, lưu để xác nhận',
|
|
416
|
+
'toast.history.empty': 'Chưa có lịch sử',
|
|
413
417
|
'toast.template.loadFail': 'Tải mẫu thất bại',
|
|
414
418
|
'toast.template.empty': 'Mẫu không được để trống',
|
|
415
419
|
'toast.template.applied': 'Đã áp dụng mẫu',
|
|
@@ -465,6 +469,10 @@ const vi = Object.freeze({
|
|
|
465
469
|
'settings.timeline.style.dots': 'Chấm',
|
|
466
470
|
'settings.timeline.style.bar': 'Thanh',
|
|
467
471
|
'settings.timeline.style.hint': 'Chấm để điều hướng nhanh, Thanh để hiển thị tiến trình trực quan',
|
|
472
|
+
'settings.configTabs.title': 'Hiển thị bảng cấu hình',
|
|
473
|
+
'settings.configTabs.meta': 'Kiểm soát các sub-tab cấu hình hiển thị trên thanh bên',
|
|
474
|
+
'settings.configTabs.hint': 'Tab bị ẩn sẽ không hiển thị; cần giữ lại ít nhất một tab',
|
|
475
|
+
'settings.configTabs.minRequired': 'Phải giữ lại ít nhất một tab cấu hình',
|
|
468
476
|
|
|
469
477
|
// Diff / Agents hints
|
|
470
478
|
'diff.hint.busy': 'Đang tạo diff hoặc áp dụng. Thao tác tạm thời bị vô hiệu hóa.',
|
|
@@ -863,6 +871,7 @@ const vi = Object.freeze({
|
|
|
863
871
|
'sessions.preview.importNative.failedWithReason': 'Nhập vào native thất bại: {reason}',
|
|
864
872
|
'sessions.preview.copyLink': 'Sao chép link',
|
|
865
873
|
'sessions.preview.copyPath': 'Sao chép đường dẫn',
|
|
874
|
+
'sessions.preview.copyMessage': 'Sao chép tin nhắn',
|
|
866
875
|
'sessions.preview.loadingBody': 'Đang tải nội dung phiên...',
|
|
867
876
|
'sessions.preview.emptyMsgs': 'Không có tin nhắn để hiển thị',
|
|
868
877
|
'sessions.preview.rendering': 'Đang render nội dung phiên...',
|
|
@@ -34,6 +34,8 @@ const zhTw = Object.freeze({
|
|
|
34
34
|
'common.save': '保存',
|
|
35
35
|
'common.saveApply': '保存並應用',
|
|
36
36
|
'common.close': '關閉',
|
|
37
|
+
'common.history': '歷史',
|
|
38
|
+
'common.restoreToEditor': '還原到編輯器',
|
|
37
39
|
'common.delete': '刪除',
|
|
38
40
|
'common.clear': '清空',
|
|
39
41
|
'common.show': '顯示',
|
|
@@ -467,6 +469,8 @@ const zhTw = Object.freeze({
|
|
|
467
469
|
'toast.health.noFailedProviderSelection': '請先選擇至少一個失敗提供商',
|
|
468
470
|
'toast.health.deleteFailedProvidersDone': '已刪除 {count} 個失敗提供商',
|
|
469
471
|
'toast.noChanges': '未檢測到改動',
|
|
472
|
+
'toast.history.restored': '已還原到編輯器,儲存後生效',
|
|
473
|
+
'toast.history.empty': '尚無歷史',
|
|
470
474
|
'toast.template.loadFail': '載入模板失敗',
|
|
471
475
|
'toast.template.empty': '模板不能為空',
|
|
472
476
|
'toast.template.applied': '模板已應用',
|
|
@@ -691,6 +695,7 @@ const zhTw = Object.freeze({
|
|
|
691
695
|
'sessions.preview.importNative.failedWithReason': '匯入原生目錄失敗:{reason}',
|
|
692
696
|
'sessions.preview.copyLink': '複製鏈接',
|
|
693
697
|
'sessions.preview.copyPath': '複製路徑',
|
|
698
|
+
'sessions.preview.copyMessage': '複製記錄',
|
|
694
699
|
'sessions.preview.openLink': '打開鏈接',
|
|
695
700
|
'sessions.preview.loadingBody': '正在載入會話內容...',
|
|
696
701
|
'sessions.preview.emptyMsgs': '目前會話暫無可展示消息',
|
|
@@ -1173,6 +1178,10 @@ const zhTw = Object.freeze({
|
|
|
1173
1178
|
'settings.timeline.style.dots': '點狀',
|
|
1174
1179
|
'settings.timeline.style.bar': '條狀',
|
|
1175
1180
|
'settings.timeline.style.hint': '點狀適合快速定位,條狀更直觀顯示進度',
|
|
1181
|
+
'settings.configTabs.title': '配置面板可見性',
|
|
1182
|
+
'settings.configTabs.meta': '控制側邊欄顯示哪些配置子頁面',
|
|
1183
|
+
'settings.configTabs.hint': '關閉後對應的配置子頁面將不再顯示,至少需保留一個',
|
|
1184
|
+
'settings.configTabs.minRequired': '至少需要保留一個可見的配置頁面',
|
|
1176
1185
|
|
|
1177
1186
|
'settings.reset.title': '設定重置',
|
|
1178
1187
|
'settings.reset.meta': '謹慎操作',
|
|
@@ -34,6 +34,8 @@ const zh = Object.freeze({
|
|
|
34
34
|
'common.save': '保存',
|
|
35
35
|
'common.saveApply': '保存并应用',
|
|
36
36
|
'common.close': '关闭',
|
|
37
|
+
'common.history': '历史',
|
|
38
|
+
'common.restoreToEditor': '恢复到编辑器',
|
|
37
39
|
'common.delete': '删除',
|
|
38
40
|
'common.clear': '清空',
|
|
39
41
|
'common.show': '显示',
|
|
@@ -467,6 +469,8 @@ const zh = Object.freeze({
|
|
|
467
469
|
'toast.health.noFailedProviderSelection': '请先选择至少一个失败提供商',
|
|
468
470
|
'toast.health.deleteFailedProvidersDone': '已删除 {count} 个失败提供商',
|
|
469
471
|
'toast.noChanges': '未检测到改动',
|
|
472
|
+
'toast.history.restored': '已恢复到编辑器,保存后生效',
|
|
473
|
+
'toast.history.empty': '暂无历史',
|
|
470
474
|
'toast.template.loadFail': '加载模板失败',
|
|
471
475
|
'toast.template.empty': '模板不能为空',
|
|
472
476
|
'toast.template.applied': '模板已应用',
|
|
@@ -691,6 +695,7 @@ const zh = Object.freeze({
|
|
|
691
695
|
'sessions.preview.importNative.failedWithReason': '导入原生目录失败:{reason}',
|
|
692
696
|
'sessions.preview.copyLink': '复制链接',
|
|
693
697
|
'sessions.preview.copyPath': '复制路径',
|
|
698
|
+
'sessions.preview.copyMessage': '复制记录',
|
|
694
699
|
'sessions.preview.openLink': '打开链接',
|
|
695
700
|
'sessions.preview.loadingBody': '正在加载会话内容...',
|
|
696
701
|
'sessions.preview.emptyMsgs': '当前会话暂无可展示消息',
|
|
@@ -1173,6 +1178,10 @@ const zh = Object.freeze({
|
|
|
1173
1178
|
'settings.timeline.style.dots': '点状',
|
|
1174
1179
|
'settings.timeline.style.bar': '条状',
|
|
1175
1180
|
'settings.timeline.style.hint': '点状适合快速定位,条状更直观显示进度',
|
|
1181
|
+
'settings.configTabs.title': '配置面板可见性',
|
|
1182
|
+
'settings.configTabs.meta': '控制侧栏中哪些配置子页面可见',
|
|
1183
|
+
'settings.configTabs.hint': '关闭后对应的配置子页面将不再显示,至少需保留一个',
|
|
1184
|
+
'settings.configTabs.minRequired': '至少需要保留一个可见的配置页面',
|
|
1176
1185
|
|
|
1177
1186
|
'settings.reset.title': '配置重置',
|
|
1178
1187
|
'settings.reset.meta': '谨慎操作',
|
|
@@ -183,6 +183,7 @@
|
|
|
183
183
|
<div class="side-section" role="navigation" :aria-label="t('side.config')">
|
|
184
184
|
<div class="side-section-title">{{ t('side.config') }}</div>
|
|
185
185
|
<button
|
|
186
|
+
v-if="isConfigModeVisible('codex')"
|
|
186
187
|
id="side-tab-config-codex"
|
|
187
188
|
data-main-tab="config"
|
|
188
189
|
data-config-mode="codex"
|
|
@@ -197,6 +198,7 @@
|
|
|
197
198
|
</div>
|
|
198
199
|
</button>
|
|
199
200
|
<button
|
|
201
|
+
v-if="isConfigModeVisible('claude')"
|
|
200
202
|
id="side-tab-config-claude"
|
|
201
203
|
data-main-tab="config"
|
|
202
204
|
data-config-mode="claude"
|
|
@@ -211,6 +213,7 @@
|
|
|
211
213
|
</div>
|
|
212
214
|
</button>
|
|
213
215
|
<button
|
|
216
|
+
v-if="isConfigModeVisible('openclaw')"
|
|
214
217
|
id="side-tab-config-openclaw"
|
|
215
218
|
data-main-tab="config"
|
|
216
219
|
data-config-mode="openclaw"
|
|
@@ -225,6 +228,7 @@
|
|
|
225
228
|
</div>
|
|
226
229
|
</button>
|
|
227
230
|
<button
|
|
231
|
+
v-if="isConfigModeVisible('opencode')"
|
|
228
232
|
id="side-tab-config-opencode"
|
|
229
233
|
data-main-tab="config"
|
|
230
234
|
data-config-mode="opencode"
|
|
@@ -240,6 +244,7 @@
|
|
|
240
244
|
</button>
|
|
241
245
|
|
|
242
246
|
<button
|
|
247
|
+
v-if="isConfigModeVisible('kilocode')"
|
|
243
248
|
id="side-tab-config-kilocode"
|
|
244
249
|
data-main-tab="config"
|
|
245
250
|
data-config-mode="kilocode"
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
role="tabpanel"
|
|
7
7
|
:aria-labelledby="forceCompactLayout ? 'tab-config' : 'side-tab-config-claude'">
|
|
8
8
|
<div v-if="forceCompactLayout && !sessionStandalone" class="segmented-control">
|
|
9
|
-
<button type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
-
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
-
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
9
|
+
<button v-if="isConfigModeVisible('codex')" type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
+
<button v-if="isConfigModeVisible('claude')" type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
+
<button v-if="isConfigModeVisible('openclaw')" type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
12
|
</div>
|
|
13
13
|
<template v-if="shouldShowCliInstallPlaceholder('claude')">
|
|
14
14
|
<div class="selector-section">
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
role="tabpanel"
|
|
7
7
|
:aria-labelledby="forceCompactLayout ? 'tab-config' : ('side-tab-config-' + configMode)">
|
|
8
8
|
<div v-if="forceCompactLayout && !sessionStandalone" class="segmented-control">
|
|
9
|
-
<button type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
-
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
-
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
9
|
+
<button v-if="isConfigModeVisible('codex')" type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
+
<button v-if="isConfigModeVisible('claude')" type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
+
<button v-if="isConfigModeVisible('openclaw')" type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
12
|
</div>
|
|
13
13
|
<template v-if="isCodexConfigMode && shouldShowCliInstallPlaceholder('codex')">
|
|
14
14
|
<div class="selector-section">
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
role="tabpanel"
|
|
7
7
|
:aria-labelledby="forceCompactLayout ? 'tab-config' : 'side-tab-config-kilocode'">
|
|
8
8
|
<div v-if="forceCompactLayout && !sessionStandalone" class="segmented-control">
|
|
9
|
-
<button type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
-
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
-
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
|
-
<button type="button" :class="['segment', { active: configMode === 'opencode' }]" @click="switchConfigMode('opencode')">{{ t('tab.config.opencode') }}</button>
|
|
13
|
-
<button type="button" :class="['segment', { active: configMode === 'kilocode' }]" @click="switchConfigMode('kilocode')">{{ t('tab.config.kilocode') }}</button>
|
|
9
|
+
<button v-if="isConfigModeVisible('codex')" type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
+
<button v-if="isConfigModeVisible('claude')" type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
+
<button v-if="isConfigModeVisible('openclaw')" type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
|
+
<button v-if="isConfigModeVisible('opencode')" type="button" :class="['segment', { active: configMode === 'opencode' }]" @click="switchConfigMode('opencode')">{{ t('tab.config.opencode') }}</button>
|
|
13
|
+
<button v-if="isConfigModeVisible('kilocode')" type="button" :class="['segment', { active: configMode === 'kilocode' }]" @click="switchConfigMode('kilocode')">{{ t('tab.config.kilocode') }}</button>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
<section class="tool-config-write-card" :aria-label="t('toolConfig.kilocode.title')">
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
role="tabpanel"
|
|
7
7
|
:aria-labelledby="forceCompactLayout ? 'tab-config' : 'side-tab-config-openclaw'">
|
|
8
8
|
<div v-if="forceCompactLayout && !sessionStandalone" class="segmented-control">
|
|
9
|
-
<button type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
-
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
-
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
9
|
+
<button v-if="isConfigModeVisible('codex')" type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
+
<button v-if="isConfigModeVisible('claude')" type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
+
<button v-if="isConfigModeVisible('openclaw')" type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
12
|
</div>
|
|
13
13
|
<div class="openclaw-layout">
|
|
14
14
|
<section class="tool-config-write-card" :aria-label="t('toolConfig.openclaw.title')">
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
role="tabpanel"
|
|
7
7
|
:aria-labelledby="forceCompactLayout ? 'tab-config' : 'side-tab-config-opencode'">
|
|
8
8
|
<div v-if="forceCompactLayout && !sessionStandalone" class="segmented-control">
|
|
9
|
-
<button type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
-
<button type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
-
<button type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
|
-
<button type="button" :class="['segment', { active: configMode === 'opencode' }]" @click="switchConfigMode('opencode')">{{ t('tab.config.opencode') }}</button>
|
|
13
|
-
<button type="button" :class="['segment', { active: configMode === 'kilocode' }]" @click="switchConfigMode('kilocode')">{{ t('tab.config.kilocode') }}</button>
|
|
9
|
+
<button v-if="isConfigModeVisible('codex')" type="button" :class="['segment', { active: configMode === 'codex' }]" @click="switchConfigMode('codex')">{{ t('tab.config.codex') }}</button>
|
|
10
|
+
<button v-if="isConfigModeVisible('claude')" type="button" :class="['segment', { active: configMode === 'claude' }]" @click="switchConfigMode('claude')">{{ t('tab.config.claude') }}</button>
|
|
11
|
+
<button v-if="isConfigModeVisible('openclaw')" type="button" :class="['segment', { active: configMode === 'openclaw' }]" @click="switchConfigMode('openclaw')">{{ t('tab.config.openclaw') }}</button>
|
|
12
|
+
<button v-if="isConfigModeVisible('opencode')" type="button" :class="['segment', { active: configMode === 'opencode' }]" @click="switchConfigMode('opencode')">{{ t('tab.config.opencode') }}</button>
|
|
13
|
+
<button v-if="isConfigModeVisible('kilocode')" type="button" :class="['segment', { active: configMode === 'kilocode' }]" @click="switchConfigMode('kilocode')">{{ t('tab.config.kilocode') }}</button>
|
|
14
14
|
</div>
|
|
15
15
|
|
|
16
16
|
<section class="tool-config-write-card" :aria-label="t('opencode.writeAria')">
|
|
@@ -65,6 +65,13 @@
|
|
|
65
65
|
:title="t('common.paste')">
|
|
66
66
|
<svg class="btn-icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="8" y="2" width="8" height="4" rx="1"/><path d="M16 4h2a2 2 0 012 2v14a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2h2"/></svg>
|
|
67
67
|
</button>
|
|
68
|
+
<button
|
|
69
|
+
class="btn-mini"
|
|
70
|
+
@click="openPromptHistory"
|
|
71
|
+
:disabled="agentsSaving || agentsDiffVisible"
|
|
72
|
+
:title="t('common.history')">
|
|
73
|
+
<svg class="btn-icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 8v4l3 2"/><path d="M3 12a9 9 0 1 0 9-9 9 9 0 0 0-7.5 4M3 4v4h4"/></svg>
|
|
74
|
+
</button>
|
|
68
75
|
</div>
|
|
69
76
|
<div class="prompts-editor-group prompts-editor-group--workflow">
|
|
70
77
|
<button class="btn-mini" @click="loadPromptsContent" :disabled="agentsSaving || agentsDiffLoading" :title="t('common.cancel')">
|
|
@@ -85,6 +92,27 @@
|
|
|
85
92
|
</div>
|
|
86
93
|
</div>
|
|
87
94
|
</div>
|
|
95
|
+
<details v-if="promptHistoryVisible" class="prompt-history-panel" open>
|
|
96
|
+
<summary class="prompt-history-summary">
|
|
97
|
+
<span>{{ t('common.history') }}</span>
|
|
98
|
+
<button type="button" class="btn-mini prompt-history-close" @click="closePromptHistory" :title="t('common.close')">✕</button>
|
|
99
|
+
</summary>
|
|
100
|
+
<div class="prompt-history-body">
|
|
101
|
+
<ul v-if="!promptHistoryLoading && !promptHistoryError && promptHistoryItems.length" class="prompt-history-list">
|
|
102
|
+
<li v-for="item in promptHistoryItems" :key="item.id" :class="['prompt-history-item', { active: promptHistoryPreviewId === item.id }]" @click="viewPromptHistoryItem(item)">
|
|
103
|
+
<span class="prompt-history-time">{{ item.id }}</span>
|
|
104
|
+
<span class="prompt-history-size">{{ Math.round(item.size / 1024 * 10) / 10 }} KB</span>
|
|
105
|
+
</li>
|
|
106
|
+
</ul>
|
|
107
|
+
<div v-if="promptHistoryLoading" class="state-message">{{ t('diff.generating') }}</div>
|
|
108
|
+
<div v-else-if="promptHistoryError" class="state-message error">{{ promptHistoryError }}</div>
|
|
109
|
+
<div v-else-if="!promptHistoryItems.length" class="state-message">{{ t('toast.history.empty') }}</div>
|
|
110
|
+
<div v-if="promptHistoryPreviewContent" class="prompt-history-preview-wrap">
|
|
111
|
+
<pre class="prompt-history-preview">{{ promptHistoryPreviewContent }}</pre>
|
|
112
|
+
<button type="button" class="btn-mini btn-confirm-mini" @click="applyPromptHistoryToEditor" :disabled="agentsSaving || agentsDiffVisible">{{ t('common.restoreToEditor') }}</button>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</details>
|
|
88
116
|
<div class="prompt-presets-inline-row">
|
|
89
117
|
<div class="prompt-presets-inline-group">
|
|
90
118
|
<label class="prompt-presets-inline-label">{{ t('prompts.presets.title') }}</label>
|
|
@@ -228,6 +256,9 @@
|
|
|
228
256
|
<button class="btn-mini" @click="pasteSysPromptContent" :disabled="sysPromptLoading || sysPromptSaving || sysPromptDiffVisible" :title="t('common.paste')">
|
|
229
257
|
<svg class="btn-icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="8" y="2" width="8" height="4" rx="1"/><path d="M16 4h2a2 2 0 012 2v14a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2h2"/></svg>
|
|
230
258
|
</button>
|
|
259
|
+
<button class="btn-mini" @click="openSysHistory" :disabled="sysPromptSaving || sysPromptDiffVisible" :title="t('common.history')">
|
|
260
|
+
<svg class="btn-icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 8v4l3 2"/><path d="M3 12a9 9 0 1 0 9-9 9 9 0 0 0-7.5 4M3 4v4h4"/></svg>
|
|
261
|
+
</button>
|
|
231
262
|
</div>
|
|
232
263
|
<div class="prompts-editor-group prompts-editor-group--workflow">
|
|
233
264
|
<button class="btn-mini" @click="cancelSysPromptEdit" :disabled="sysPromptSaving || sysPromptDiffLoading" :title="t('common.cancel')">
|
|
@@ -243,6 +274,27 @@
|
|
|
243
274
|
</div>
|
|
244
275
|
</div>
|
|
245
276
|
</div>
|
|
277
|
+
<details v-if="sysHistoryVisible" class="prompt-history-panel" open>
|
|
278
|
+
<summary class="prompt-history-summary">
|
|
279
|
+
<span>{{ t('common.history') }}</span>
|
|
280
|
+
<button type="button" class="btn-mini prompt-history-close" @click="closeSysHistory" :title="t('common.close')">✕</button>
|
|
281
|
+
</summary>
|
|
282
|
+
<div class="prompt-history-body">
|
|
283
|
+
<ul v-if="!sysHistoryLoading && !sysHistoryError && sysHistoryItems.length" class="prompt-history-list">
|
|
284
|
+
<li v-for="item in sysHistoryItems" :key="item.id" :class="['prompt-history-item', { active: sysHistoryPreviewId === item.id }]" @click="viewSysHistoryItem(item)">
|
|
285
|
+
<span class="prompt-history-time">{{ item.id }}</span>
|
|
286
|
+
<span class="prompt-history-size">{{ Math.round(item.size / 1024 * 10) / 10 }} KB</span>
|
|
287
|
+
</li>
|
|
288
|
+
</ul>
|
|
289
|
+
<div v-if="sysHistoryLoading" class="state-message">{{ t('diff.generating') }}</div>
|
|
290
|
+
<div v-else-if="sysHistoryError" class="state-message error">{{ sysHistoryError }}</div>
|
|
291
|
+
<div v-else-if="!sysHistoryItems.length" class="state-message">{{ t('toast.history.empty') }}</div>
|
|
292
|
+
<div v-if="sysHistoryPreviewContent" class="prompt-history-preview-wrap">
|
|
293
|
+
<pre class="prompt-history-preview">{{ sysHistoryPreviewContent }}</pre>
|
|
294
|
+
<button type="button" class="btn-mini btn-confirm-mini" @click="applySysHistoryToEditor" :disabled="sysPromptSaving || sysPromptDiffVisible">{{ t('common.restoreToEditor') }}</button>
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
</details>
|
|
246
298
|
<div class="form-group">
|
|
247
299
|
<div v-if="sysPromptDiffVisible">
|
|
248
300
|
<div
|
|
@@ -410,6 +410,18 @@
|
|
|
410
410
|
</div>
|
|
411
411
|
</div>
|
|
412
412
|
<div class="session-msg-content" v-html="highlightQueryText(msg.text) || ''"></div>
|
|
413
|
+
<button
|
|
414
|
+
v-if="msg.normalizedRole === 'user'"
|
|
415
|
+
type="button"
|
|
416
|
+
class="session-msg-copy"
|
|
417
|
+
@click="copySessionMessage(msg)"
|
|
418
|
+
:aria-label="t('sessions.preview.copyMessage')"
|
|
419
|
+
:title="t('sessions.preview.copyMessage')">
|
|
420
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
421
|
+
<rect x="8" y="8" width="12" height="12" rx="2"></rect>
|
|
422
|
+
<path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"></path>
|
|
423
|
+
</svg>
|
|
424
|
+
</button>
|
|
413
425
|
</div>
|
|
414
426
|
<div v-if="canLoadMoreSessionMessages" class="session-preview-load-more">
|
|
415
427
|
<span>{{ t('sessions.preview.shownCount', { shown: activeSessionVisibleMessages.length, total: activeSessionMessages.length }) }}</span>
|
|
@@ -138,6 +138,41 @@
|
|
|
138
138
|
</div>
|
|
139
139
|
</div>
|
|
140
140
|
</section>
|
|
141
|
+
|
|
142
|
+
<section class="settings-card" :aria-label="t('settings.configTabs.title')">
|
|
143
|
+
<div class="settings-card-main">
|
|
144
|
+
<div class="settings-card-content">
|
|
145
|
+
<div class="settings-card-title">{{ t('settings.configTabs.title') }}</div>
|
|
146
|
+
<p class="settings-card-desc">{{ t('settings.configTabs.meta') }}</p>
|
|
147
|
+
<label class="settings-toggle-row">
|
|
148
|
+
<input type="checkbox" :checked="configModeVisibility.codex" @change="setConfigModeVisibility('codex', $event.target.checked)">
|
|
149
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
150
|
+
<span>{{ t('tab.config.codex') }}</span>
|
|
151
|
+
</label>
|
|
152
|
+
<label class="settings-toggle-row">
|
|
153
|
+
<input type="checkbox" :checked="configModeVisibility.claude" @change="setConfigModeVisibility('claude', $event.target.checked)">
|
|
154
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
155
|
+
<span>{{ t('tab.config.claude') }}</span>
|
|
156
|
+
</label>
|
|
157
|
+
<label class="settings-toggle-row">
|
|
158
|
+
<input type="checkbox" :checked="configModeVisibility.openclaw" @change="setConfigModeVisibility('openclaw', $event.target.checked)">
|
|
159
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
160
|
+
<span>{{ t('tab.config.openclaw') }}</span>
|
|
161
|
+
</label>
|
|
162
|
+
<label class="settings-toggle-row">
|
|
163
|
+
<input type="checkbox" :checked="configModeVisibility.opencode" @change="setConfigModeVisibility('opencode', $event.target.checked)">
|
|
164
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
165
|
+
<span>{{ t('tab.config.opencode') }}</span>
|
|
166
|
+
</label>
|
|
167
|
+
<label class="settings-toggle-row">
|
|
168
|
+
<input type="checkbox" :checked="configModeVisibility.kilocode" @change="setConfigModeVisibility('kilocode', $event.target.checked)">
|
|
169
|
+
<span class="toggle-track"><span class="toggle-thumb"></span></span>
|
|
170
|
+
<span>{{ t('tab.config.kilocode') }}</span>
|
|
171
|
+
</label>
|
|
172
|
+
<p class="settings-card-hint">{{ t('settings.configTabs.hint') }}</p>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</section>
|
|
141
176
|
</div>
|
|
142
177
|
</div>
|
|
143
178
|
|