codexmate 0.1.8 → 0.1.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/cli.js +63 -2696
- package/package.json +1 -1
- package/web-ui/app.js +27 -56
- package/web-ui/index.html +0 -1
- package/web-ui/modules/app.computed.dashboard.mjs +0 -3
- package/web-ui/modules/app.computed.main-tabs.mjs +0 -474
- package/web-ui/modules/app.methods.index.mjs +1 -3
- package/web-ui/modules/app.methods.navigation.mjs +1 -2
- package/web-ui/modules/app.methods.session-actions.mjs +146 -21
- package/web-ui/modules/app.methods.session-browser.mjs +5 -0
- package/web-ui/modules/app.methods.web-ui-preferences.mjs +20 -9
- package/web-ui/modules/i18n/locales/en.mjs +14 -265
- package/web-ui/modules/i18n/locales/ja.mjs +14 -265
- package/web-ui/modules/i18n/locales/vi.mjs +14 -266
- package/web-ui/modules/i18n/locales/zh-tw.mjs +14 -265
- package/web-ui/modules/i18n/locales/zh.mjs +14 -265
- package/web-ui/partials/index/layout-header.html +0 -48
- package/web-ui/partials/index/panel-dashboard.html +0 -21
- package/web-ui/partials/index/panel-sessions.html +30 -2
- package/web-ui/res/web-ui-render.precompiled.js +105 -1193
- package/web-ui/session-helpers.mjs +3 -16
- package/web-ui/styles/sessions-list.css +96 -0
- package/web-ui/styles.css +0 -1
- package/lib/automation.js +0 -404
- package/lib/task-orchestrator.js +0 -938
- package/lib/task-workspace-chat.js +0 -292
- package/web-ui/modules/app.methods.task-orchestration.mjs +0 -895
- package/web-ui/partials/index/panel-orchestration.html +0 -598
- package/web-ui/styles/task-orchestration.css +0 -2979
|
@@ -639,27 +639,16 @@ export function createSessionActionMethods(options = {}) {
|
|
|
639
639
|
}
|
|
640
640
|
},
|
|
641
641
|
|
|
642
|
-
async deleteSession(session) {
|
|
642
|
+
async deleteSession(session, batchOpts = {}) {
|
|
643
|
+
const batch = !!(batchOpts && batchOpts.batch);
|
|
643
644
|
if (!this.isDeleteAvailable(session)) {
|
|
644
|
-
this.showMessage('不支持此操作', 'error');
|
|
645
|
-
return;
|
|
645
|
+
if (!batch) this.showMessage('不支持此操作', 'error');
|
|
646
|
+
return false;
|
|
646
647
|
}
|
|
647
648
|
const useTrash = this.sessionTrashEnabled !== false;
|
|
648
|
-
if (!useTrash && typeof this.requestConfirmDialog === 'function') {
|
|
649
|
-
const confirmed = await this.requestConfirmDialog({
|
|
650
|
-
title: '直接删除会话',
|
|
651
|
-
message: '关闭回收站后,删除会话将直接永久删除,且无法恢复。',
|
|
652
|
-
confirmText: '直接删除',
|
|
653
|
-
cancelText: '取消',
|
|
654
|
-
danger: true
|
|
655
|
-
});
|
|
656
|
-
if (!confirmed) {
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
649
|
const key = this.getSessionExportKey(session);
|
|
661
650
|
if (this.sessionDeleting[key]) {
|
|
662
|
-
return;
|
|
651
|
+
return false;
|
|
663
652
|
}
|
|
664
653
|
this.sessionDeleting[key] = true;
|
|
665
654
|
try {
|
|
@@ -670,13 +659,14 @@ export function createSessionActionMethods(options = {}) {
|
|
|
670
659
|
filePath: session.filePath
|
|
671
660
|
});
|
|
672
661
|
if (!res || res.error) {
|
|
673
|
-
|
|
674
|
-
|
|
662
|
+
const msg = (res && res.error) || (typeof this.t === 'function' ? this.t('toast.delete.fail') : '删除失败');
|
|
663
|
+
if (!batch) this.showMessage(msg, 'error');
|
|
664
|
+
return false;
|
|
675
665
|
}
|
|
676
666
|
this.removeSessionPin(session);
|
|
677
667
|
if (useTrash) {
|
|
678
668
|
this.invalidateSessionTrashRequests();
|
|
679
|
-
this.showMessage('已移入回收站', 'success');
|
|
669
|
+
if (!batch) this.showMessage('已移入回收站', 'success');
|
|
680
670
|
if (this.sessionTrashLoadedOnce) {
|
|
681
671
|
this.prependSessionTrashItem(this.buildSessionTrashItemFromSession(session, res), {
|
|
682
672
|
totalCount: res && res.totalCount !== undefined ? res.totalCount : undefined
|
|
@@ -689,7 +679,7 @@ export function createSessionActionMethods(options = {}) {
|
|
|
689
679
|
this.sessionTrashItems
|
|
690
680
|
);
|
|
691
681
|
}
|
|
692
|
-
} else {
|
|
682
|
+
} else if (!batch) {
|
|
693
683
|
this.showMessage('已删除', 'success');
|
|
694
684
|
}
|
|
695
685
|
if (typeof this.invalidateSessionsUsageData === 'function') {
|
|
@@ -700,11 +690,146 @@ export function createSessionActionMethods(options = {}) {
|
|
|
700
690
|
} catch (_) {
|
|
701
691
|
// The delete already succeeded remotely; keep the success result.
|
|
702
692
|
}
|
|
693
|
+
return true;
|
|
703
694
|
} catch (_) {
|
|
704
|
-
|
|
695
|
+
if (!batch) {
|
|
696
|
+
this.showMessage(this.t && this.t('toast.delete.fail') ? this.t('toast.delete.fail') : '删除失败', 'error');
|
|
697
|
+
}
|
|
698
|
+
return false;
|
|
705
699
|
} finally {
|
|
706
700
|
this.sessionDeleting[key] = false;
|
|
707
701
|
}
|
|
702
|
+
},
|
|
703
|
+
|
|
704
|
+
isSessionBatchSelectable(session) {
|
|
705
|
+
return this.isDeleteAvailable(session);
|
|
706
|
+
},
|
|
707
|
+
|
|
708
|
+
isSessionSelectedForBatch(session) {
|
|
709
|
+
const key = this.getSessionExportKey(session);
|
|
710
|
+
if (!key) return false;
|
|
711
|
+
return !!this.sessionSelectedKeys[key];
|
|
712
|
+
},
|
|
713
|
+
|
|
714
|
+
toggleSessionSelectionForBatch(session) {
|
|
715
|
+
const key = this.getSessionExportKey(session);
|
|
716
|
+
if (!key) return;
|
|
717
|
+
if (this.sessionSelectedKeys[key]) {
|
|
718
|
+
const next = { ...this.sessionSelectedKeys };
|
|
719
|
+
delete next[key];
|
|
720
|
+
this.sessionSelectedKeys = next;
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
this.sessionSelectedKeys = { ...this.sessionSelectedKeys, [key]: true };
|
|
724
|
+
},
|
|
725
|
+
|
|
726
|
+
enterSessionBatchSelectMode() {
|
|
727
|
+
if (this.sessionBatchSelectMode) return;
|
|
728
|
+
this.sessionBatchSelectMode = true;
|
|
729
|
+
this.sessionSelectedKeys = {};
|
|
730
|
+
},
|
|
731
|
+
|
|
732
|
+
exitSessionBatchSelectMode() {
|
|
733
|
+
if (!this.sessionBatchSelectMode) return;
|
|
734
|
+
this.sessionBatchSelectMode = false;
|
|
735
|
+
this.sessionSelectedKeys = {};
|
|
736
|
+
},
|
|
737
|
+
|
|
738
|
+
getSelectedBatchCount() {
|
|
739
|
+
return this.sessionsList.filter(s => this.sessionBatchSelectMode && this.isSessionSelectedForBatch(s)).length;
|
|
740
|
+
},
|
|
741
|
+
|
|
742
|
+
getVisibleBatchSelectableCount() {
|
|
743
|
+
return (this.visibleSessionsList || []).filter(s => this.isDeleteAvailable(s)).length;
|
|
744
|
+
},
|
|
745
|
+
|
|
746
|
+
isAllVisibleBatchSelected() {
|
|
747
|
+
const visible = (this.visibleSessionsList || []).filter(s => this.isDeleteAvailable(s));
|
|
748
|
+
if (visible.length === 0) return false;
|
|
749
|
+
return visible.every(s => this.isSessionSelectedForBatch(s) || this.sessionDeleting[this.getSessionExportKey(s)]);
|
|
750
|
+
},
|
|
751
|
+
|
|
752
|
+
toggleSelectAllVisibleForBatch() {
|
|
753
|
+
const visible = (this.visibleSessionsList || []).filter(s => this.isDeleteAvailable(s) && !this.sessionDeleting[this.getSessionExportKey(s)]);
|
|
754
|
+
if (visible.length === 0) return;
|
|
755
|
+
const allSelected = visible.every(s => this.isSessionSelectedForBatch(s));
|
|
756
|
+
const next = { ...this.sessionSelectedKeys };
|
|
757
|
+
if (allSelected) {
|
|
758
|
+
for (const s of visible) {
|
|
759
|
+
delete next[this.getSessionExportKey(s)];
|
|
760
|
+
}
|
|
761
|
+
} else {
|
|
762
|
+
for (const s of visible) {
|
|
763
|
+
next[this.getSessionExportKey(s)] = true;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
this.sessionSelectedKeys = next;
|
|
767
|
+
},
|
|
768
|
+
|
|
769
|
+
clearSessionBatchSelection() {
|
|
770
|
+
this.sessionSelectedKeys = {};
|
|
771
|
+
},
|
|
772
|
+
|
|
773
|
+
async deleteSelectedSessions() {
|
|
774
|
+
if (this.sessionDeletingSelected) return;
|
|
775
|
+
const selected = (this.sessionsList || []).filter(s => this.isSessionSelectedForBatch(s));
|
|
776
|
+
if (selected.length === 0) {
|
|
777
|
+
if (typeof this.t === 'function') {
|
|
778
|
+
this.showMessage(this.t('sessions.batch.emptySelection'), 'warning');
|
|
779
|
+
}
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
const useTrash = this.sessionTrashEnabled !== false;
|
|
783
|
+
this.sessionDeletingSelected = true;
|
|
784
|
+
let failed = 0;
|
|
785
|
+
const succeededKeys = [];
|
|
786
|
+
try {
|
|
787
|
+
for (const session of selected) {
|
|
788
|
+
const ok = await this.deleteSession(session, { batch: true });
|
|
789
|
+
if (ok) {
|
|
790
|
+
succeededKeys.push(this.getSessionExportKey(session));
|
|
791
|
+
} else {
|
|
792
|
+
failed += 1;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
if (succeededKeys.length > 0) {
|
|
796
|
+
if (typeof this.invalidateSessionsUsageData === 'function') {
|
|
797
|
+
this.invalidateSessionsUsageData({ preserveList: true });
|
|
798
|
+
}
|
|
799
|
+
this.invalidateSessionTrashRequests();
|
|
800
|
+
// Remove succeeded sessions from the current list in order
|
|
801
|
+
for (const key of succeededKeys) {
|
|
802
|
+
const session = (this.sessionsList || []).find(s => this.getSessionExportKey(s) === key);
|
|
803
|
+
if (session) {
|
|
804
|
+
try {
|
|
805
|
+
await this.removeSessionFromCurrentList(session);
|
|
806
|
+
} catch (_) {
|
|
807
|
+
// Remote delete already succeeded; ignore local cleanup errors.
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
// Clear succeeded selections; keep failed ones selected
|
|
812
|
+
const next = {};
|
|
813
|
+
for (const session of selected) {
|
|
814
|
+
const k = this.getSessionExportKey(session);
|
|
815
|
+
if (failed > 0 && !succeededKeys.includes(k)) {
|
|
816
|
+
next[k] = true;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
this.sessionSelectedKeys = next;
|
|
820
|
+
}
|
|
821
|
+
if (failed === 0) {
|
|
822
|
+
const okMsg = useTrash ? '已移入回收站' : '已删除';
|
|
823
|
+
this.showMessage(okMsg + ' · ' + succeededKeys.length, 'success');
|
|
824
|
+
this.sessionBatchSelectMode = false;
|
|
825
|
+
} else if (failed === selected.length) {
|
|
826
|
+
this.showMessage(this.t('sessions.batch.allFail'), 'error');
|
|
827
|
+
} else {
|
|
828
|
+
this.showMessage(this.t('sessions.batch.partialFail', { failed }), 'warning');
|
|
829
|
+
}
|
|
830
|
+
} finally {
|
|
831
|
+
this.sessionDeletingSelected = false;
|
|
832
|
+
}
|
|
708
833
|
}
|
|
709
834
|
};
|
|
710
835
|
}
|
|
@@ -303,6 +303,7 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
303
303
|
},
|
|
304
304
|
|
|
305
305
|
onSessionSortChange() {
|
|
306
|
+
this.exitSessionBatchSelectMode();
|
|
306
307
|
const normalized = this.normalizeSessionSortMode(this.sessionSortMode);
|
|
307
308
|
this.sessionSortMode = normalized;
|
|
308
309
|
if (typeof this.persistWebUiPreferences === 'function') {
|
|
@@ -445,6 +446,7 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
445
446
|
|
|
446
447
|
setSessionSource(value) {
|
|
447
448
|
if (this.sessionsLoading) return;
|
|
449
|
+
this.exitSessionBatchSelectMode();
|
|
448
450
|
this.sessionFilterSource = value;
|
|
449
451
|
this.refreshSessionPathOptions(value);
|
|
450
452
|
this.persistSessionFilterCache();
|
|
@@ -478,12 +480,14 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
478
480
|
},
|
|
479
481
|
|
|
480
482
|
async onSessionPathFilterChange() {
|
|
483
|
+
this.exitSessionBatchSelectMode();
|
|
481
484
|
this.persistSessionFilterCache();
|
|
482
485
|
syncSessionsFilterUrl(this);
|
|
483
486
|
await this.loadSessions();
|
|
484
487
|
},
|
|
485
488
|
|
|
486
489
|
async onSessionFilterChange() {
|
|
490
|
+
this.exitSessionBatchSelectMode();
|
|
487
491
|
this.persistSessionFilterCache();
|
|
488
492
|
syncSessionsFilterUrl(this);
|
|
489
493
|
await this.loadSessions();
|
|
@@ -552,6 +556,7 @@ export function createSessionBrowserMethods(options = {}) {
|
|
|
552
556
|
},
|
|
553
557
|
|
|
554
558
|
async clearSessionFilters() {
|
|
559
|
+
this.exitSessionBatchSelectMode();
|
|
555
560
|
this.sessionFilterSource = 'all';
|
|
556
561
|
this.sessionPathFilter = '';
|
|
557
562
|
this.sessionQuery = '';
|
|
@@ -8,7 +8,6 @@ const LEGACY_WEB_UI_PREFERENCE_KEYS = Object.freeze([
|
|
|
8
8
|
'codexmate_prompts_sub_tab',
|
|
9
9
|
'codexmate_project_claude_md_path',
|
|
10
10
|
'codexmateNavState.v1',
|
|
11
|
-
'codexmateTaskOrchestrationTabEnabled',
|
|
12
11
|
'codexmateSessionLoadNativeDialog',
|
|
13
12
|
'codexmateSessionFilterSource',
|
|
14
13
|
'codexmateSessionPathFilter',
|
|
@@ -63,9 +62,21 @@ function normalizeUsageTimeRange(value) {
|
|
|
63
62
|
function normalizePromptsSubTab(value) {
|
|
64
63
|
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
65
64
|
if (normalized === 'claude-project') return normalized;
|
|
65
|
+
if (normalized === 'system') return normalized;
|
|
66
66
|
return 'codex';
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
function normalizeSysPromptScope(value) {
|
|
70
|
+
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
71
|
+
if (normalized === 'project') return normalized;
|
|
72
|
+
return 'global';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function normalizeSysPromptMode(value) {
|
|
76
|
+
const normalized = typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
77
|
+
return normalized === 'append' ? 'append' : 'system';
|
|
78
|
+
}
|
|
79
|
+
|
|
69
80
|
function normalizePromptPresets(value) {
|
|
70
81
|
if (!Array.isArray(value)) return [];
|
|
71
82
|
const seen = new Set();
|
|
@@ -187,10 +198,6 @@ function collectLegacyLocalStoragePreferences(storage) {
|
|
|
187
198
|
preferences.configTemplateDiffConfirmEnabled = normalizeBoolean(read('codexmateConfigTemplateDiffConfirmEnabled'), true);
|
|
188
199
|
found = true;
|
|
189
200
|
}
|
|
190
|
-
if (has('codexmateTaskOrchestrationTabEnabled')) {
|
|
191
|
-
preferences.taskOrchestrationTabEnabled = normalizeBoolean(read('codexmateTaskOrchestrationTabEnabled'), true);
|
|
192
|
-
found = true;
|
|
193
|
-
}
|
|
194
201
|
if (has('codexmateSessionLoadNativeDialog')) {
|
|
195
202
|
preferences.sessionLoadNativeDialog = normalizeBoolean(read('codexmateSessionLoadNativeDialog'), false);
|
|
196
203
|
found = true;
|
|
@@ -333,13 +340,14 @@ export function createWebUiPreferencesMethods(options = {}) {
|
|
|
333
340
|
: this.configTemplateDiffConfirmEnabled !== false,
|
|
334
341
|
sessionsUsageTimeRange: normalizeUsageTimeRange(hasOwn(source, 'sessionsUsageTimeRange') ? source.sessionsUsageTimeRange : this.sessionsUsageTimeRange),
|
|
335
342
|
promptsSubTab: normalizePromptsSubTab(hasOwn(source, 'promptsSubTab') ? source.promptsSubTab : this.promptsSubTab),
|
|
343
|
+
sysPromptScope: normalizeSysPromptScope(hasOwn(source, 'sysPromptScope') ? source.sysPromptScope : this.sysPromptScope),
|
|
344
|
+
sysPromptMode: normalizeSysPromptMode(hasOwn(source, 'sysPromptMode') ? source.sysPromptMode : this.sysPromptMode),
|
|
336
345
|
promptPresets: normalizePromptPresets(hasOwn(source, 'promptPresets') ? source.promptPresets : this.promptPresets),
|
|
337
346
|
projectClaudeMdPath: typeof source.projectClaudeMdPath === 'string'
|
|
338
347
|
? source.projectClaudeMdPath
|
|
339
348
|
: (typeof this.projectClaudeMdPath === 'string' ? this.projectClaudeMdPath : ''),
|
|
340
349
|
sidebarCollapsed: normalizeBoolean(hasOwn(source, 'sidebarCollapsed') ? source.sidebarCollapsed : this.sidebarCollapsed, false),
|
|
341
350
|
starPrompted: normalizeBoolean(hasOwn(source, 'starPrompted') ? source.starPrompted : this.starPrompted, false),
|
|
342
|
-
taskOrchestrationTabEnabled: normalizeBoolean(hasOwn(source, 'taskOrchestrationTabEnabled') ? source.taskOrchestrationTabEnabled : this.taskOrchestrationTabEnabled, true),
|
|
343
351
|
sessionLoadNativeDialog: normalizeBoolean(hasOwn(source, 'sessionLoadNativeDialog') ? source.sessionLoadNativeDialog : this.sessionLoadNativeDialog, false),
|
|
344
352
|
language: typeof source.language === 'string'
|
|
345
353
|
? source.language
|
|
@@ -386,6 +394,12 @@ export function createWebUiPreferencesMethods(options = {}) {
|
|
|
386
394
|
if (typeof source.promptsSubTab === 'string') {
|
|
387
395
|
this.promptsSubTab = normalizePromptsSubTab(source.promptsSubTab);
|
|
388
396
|
}
|
|
397
|
+
if (typeof source.sysPromptScope === 'string') {
|
|
398
|
+
this.sysPromptScope = normalizeSysPromptScope(source.sysPromptScope);
|
|
399
|
+
}
|
|
400
|
+
if (typeof source.sysPromptMode === 'string') {
|
|
401
|
+
this.sysPromptMode = normalizeSysPromptMode(source.sysPromptMode);
|
|
402
|
+
}
|
|
389
403
|
if (Array.isArray(source.promptPresets)) {
|
|
390
404
|
this.promptPresets = normalizePromptPresets(source.promptPresets);
|
|
391
405
|
if (this.selectedPromptPresetId && !this.promptPresets.some(preset => preset.id === this.selectedPromptPresetId)) {
|
|
@@ -401,9 +415,6 @@ export function createWebUiPreferencesMethods(options = {}) {
|
|
|
401
415
|
if (hasOwn(source, 'starPrompted')) {
|
|
402
416
|
this.starPrompted = normalizeBoolean(source.starPrompted, false);
|
|
403
417
|
}
|
|
404
|
-
if (hasOwn(source, 'taskOrchestrationTabEnabled')) {
|
|
405
|
-
this.taskOrchestrationTabEnabled = normalizeBoolean(source.taskOrchestrationTabEnabled, true);
|
|
406
|
-
}
|
|
407
418
|
if (hasOwn(source, 'sessionLoadNativeDialog')) {
|
|
408
419
|
this.sessionLoadNativeDialog = normalizeBoolean(source.sessionLoadNativeDialog, false);
|
|
409
420
|
}
|