codexmate 0.1.9 → 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.
Files changed (45) hide show
  1. package/README.md +0 -4
  2. package/README.vi.md +0 -4
  3. package/README.zh.md +0 -4
  4. package/cli/agents-files.js +27 -3
  5. package/cli/prompt-history.js +171 -0
  6. package/cli/system-prompt-files.js +20 -2
  7. package/cli.js +83 -2694
  8. package/package.json +1 -1
  9. package/web-ui/app.js +39 -56
  10. package/web-ui/index.html +0 -1
  11. package/web-ui/modules/app.computed.dashboard.mjs +0 -3
  12. package/web-ui/modules/app.computed.main-tabs.mjs +0 -474
  13. package/web-ui/modules/app.methods.agents.mjs +90 -0
  14. package/web-ui/modules/app.methods.index.mjs +1 -3
  15. package/web-ui/modules/app.methods.navigation.mjs +8 -3
  16. package/web-ui/modules/app.methods.session-actions.mjs +57 -25
  17. package/web-ui/modules/app.methods.system-prompt.mjs +81 -0
  18. package/web-ui/modules/app.methods.web-ui-preferences.mjs +26 -9
  19. package/web-ui/modules/i18n/locales/en.mjs +10 -265
  20. package/web-ui/modules/i18n/locales/ja.mjs +10 -265
  21. package/web-ui/modules/i18n/locales/vi.mjs +10 -266
  22. package/web-ui/modules/i18n/locales/zh-tw.mjs +10 -265
  23. package/web-ui/modules/i18n/locales/zh.mjs +10 -265
  24. package/web-ui/partials/index/layout-header.html +5 -48
  25. package/web-ui/partials/index/panel-config-claude.html +3 -3
  26. package/web-ui/partials/index/panel-config-codex.html +3 -3
  27. package/web-ui/partials/index/panel-config-kilocode.html +5 -5
  28. package/web-ui/partials/index/panel-config-openclaw.html +3 -3
  29. package/web-ui/partials/index/panel-config-opencode.html +5 -5
  30. package/web-ui/partials/index/panel-dashboard.html +0 -21
  31. package/web-ui/partials/index/panel-prompts.html +52 -0
  32. package/web-ui/partials/index/panel-sessions.html +12 -0
  33. package/web-ui/partials/index/panel-settings.html +35 -0
  34. package/web-ui/res/web-ui-render.precompiled.js +543 -1376
  35. package/web-ui/session-helpers.mjs +0 -16
  36. package/web-ui/styles/modals-core.css +86 -0
  37. package/web-ui/styles/sessions-preview.css +38 -0
  38. package/web-ui/styles/titles-cards.css +2 -2
  39. package/web-ui/styles.css +0 -1
  40. package/lib/automation.js +0 -404
  41. package/lib/task-orchestrator.js +0 -938
  42. package/lib/task-workspace-chat.js +0 -292
  43. package/web-ui/modules/app.methods.task-orchestration.mjs +0 -895
  44. package/web-ui/partials/index/panel-orchestration.html +0 -598
  45. package/web-ui/styles/task-orchestration.css +0 -2979
@@ -357,6 +357,42 @@ export function createSessionActionMethods(options = {}) {
357
357
  }
358
358
  },
359
359
 
360
+ normalizeConfigModeVisibility(value) {
361
+ const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
362
+ const result = {};
363
+ for (const mode of ['codex', 'claude', 'openclaw', 'opencode', 'kilocode']) {
364
+ result[mode] = typeof source[mode] === 'boolean' ? source[mode] : true;
365
+ }
366
+ return result;
367
+ },
368
+
369
+ isConfigModeVisible(mode) {
370
+ const normalizedMode = typeof mode === 'string' ? mode.trim().toLowerCase() : '';
371
+ if (!this.configModeVisibility) return true;
372
+ return this.configModeVisibility[normalizedMode] !== false;
373
+ },
374
+
375
+ setConfigModeVisibility(mode, visible) {
376
+ const normalizedMode = typeof mode === 'string' ? mode.trim().toLowerCase() : '';
377
+ if (!normalizedMode || !['codex', 'claude', 'openclaw', 'opencode', 'kilocode'].includes(normalizedMode)) return;
378
+ const visibility = this.configModeVisibility || { codex: true, claude: true, openclaw: true, opencode: true, kilocode: true };
379
+ const next = { ...visibility, [normalizedMode]: !!visible };
380
+ const visibleCount = Object.values(next).filter(Boolean).length;
381
+ if (visibleCount === 0) {
382
+ this.showMessage(typeof this.t === 'function' ? this.t('settings.configTabs.minRequired') : 'At least one tab must remain visible', 'info');
383
+ return;
384
+ }
385
+ this.configModeVisibility = next;
386
+ if (typeof this.persistWebUiPreferences === 'function') {
387
+ this.persistWebUiPreferences({ configModeVisibility: next });
388
+ }
389
+ if (this.mainTab === 'config' && this.configMode === normalizedMode && !next[normalizedMode]) {
390
+ const fallback = ['codex', 'claude', 'openclaw', 'opencode', 'kilocode'].find(m => next[m] !== false);
391
+ if (fallback) this.switchConfigMode(fallback);
392
+ }
393
+ },
394
+
395
+
360
396
  getShareCommandPrefixInvocation() {
361
397
  const prefix = this.normalizeShareCommandPrefix(this.shareCommandPrefix);
362
398
  return prefix === 'codexmate' ? 'codexmate' : 'npm start --';
@@ -393,6 +429,27 @@ export function createSessionActionMethods(options = {}) {
393
429
  }
394
430
  },
395
431
 
432
+ async copySessionMessage(msg) {
433
+ const text = msg && typeof msg.text === 'string' ? msg.text : '';
434
+ if (!text) {
435
+ this.showMessage(typeof this.t === 'function' ? this.t('toast.copy.empty') : 'Nothing to copy', 'info');
436
+ return;
437
+ }
438
+ const ok = this.fallbackCopyText(text);
439
+ if (ok) {
440
+ this.showMessage(typeof this.t === 'function' ? this.t('toast.copy.ok') : 'Copied', 'success');
441
+ return;
442
+ }
443
+ try {
444
+ if (navigator.clipboard && window.isSecureContext) {
445
+ await navigator.clipboard.writeText(text);
446
+ this.showMessage(typeof this.t === 'function' ? this.t('toast.copy.ok') : 'Copied', 'success');
447
+ return;
448
+ }
449
+ } catch (_) {}
450
+ this.showMessage(typeof this.t === 'function' ? this.t('toast.copy.fail') : 'Copy failed', 'error');
451
+ },
452
+
396
453
  copyAgentsContent() {
397
454
  const text = typeof this.agentsContent === 'string' ? this.agentsContent : '';
398
455
  if (!text) {
@@ -646,18 +703,6 @@ export function createSessionActionMethods(options = {}) {
646
703
  return false;
647
704
  }
648
705
  const useTrash = this.sessionTrashEnabled !== false;
649
- if (!batch && !useTrash && typeof this.requestConfirmDialog === 'function') {
650
- const confirmed = await this.requestConfirmDialog({
651
- title: '直接删除会话',
652
- message: '关闭回收站后,删除会话将直接永久删除,且无法恢复。',
653
- confirmText: '直接删除',
654
- cancelText: '取消',
655
- danger: true
656
- });
657
- if (!confirmed) {
658
- return false;
659
- }
660
- }
661
706
  const key = this.getSessionExportKey(session);
662
707
  if (this.sessionDeleting[key]) {
663
708
  return false;
@@ -792,19 +837,6 @@ export function createSessionActionMethods(options = {}) {
792
837
  return;
793
838
  }
794
839
  const useTrash = this.sessionTrashEnabled !== false;
795
- if (typeof this.requestConfirmDialog === 'function') {
796
- const confirmKey = useTrash ? 'sessions.batch.deleteConfirm' : 'sessions.batch.deleteConfirmHard';
797
- const confirmed = await this.requestConfirmDialog({
798
- title: this.t('sessions.batch.select'),
799
- message: this.t(confirmKey, { count: selected.length }),
800
- confirmText: this.t('sessions.batch.deleteSelected'),
801
- cancelText: this.t('common.cancel'),
802
- danger: !useTrash
803
- });
804
- if (!confirmed) {
805
- return;
806
- }
807
- }
808
840
  this.sessionDeletingSelected = true;
809
841
  let failed = 0;
810
842
  const succeededKeys = [];
@@ -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
  }
@@ -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,17 @@ 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),
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 },
341
353
  starPrompted: normalizeBoolean(hasOwn(source, 'starPrompted') ? source.starPrompted : this.starPrompted, false),
342
- taskOrchestrationTabEnabled: normalizeBoolean(hasOwn(source, 'taskOrchestrationTabEnabled') ? source.taskOrchestrationTabEnabled : this.taskOrchestrationTabEnabled, true),
343
354
  sessionLoadNativeDialog: normalizeBoolean(hasOwn(source, 'sessionLoadNativeDialog') ? source.sessionLoadNativeDialog : this.sessionLoadNativeDialog, false),
344
355
  language: typeof source.language === 'string'
345
356
  ? source.language
@@ -386,6 +397,12 @@ export function createWebUiPreferencesMethods(options = {}) {
386
397
  if (typeof source.promptsSubTab === 'string') {
387
398
  this.promptsSubTab = normalizePromptsSubTab(source.promptsSubTab);
388
399
  }
400
+ if (typeof source.sysPromptScope === 'string') {
401
+ this.sysPromptScope = normalizeSysPromptScope(source.sysPromptScope);
402
+ }
403
+ if (typeof source.sysPromptMode === 'string') {
404
+ this.sysPromptMode = normalizeSysPromptMode(source.sysPromptMode);
405
+ }
389
406
  if (Array.isArray(source.promptPresets)) {
390
407
  this.promptPresets = normalizePromptPresets(source.promptPresets);
391
408
  if (this.selectedPromptPresetId && !this.promptPresets.some(preset => preset.id === this.selectedPromptPresetId)) {
@@ -398,12 +415,12 @@ export function createWebUiPreferencesMethods(options = {}) {
398
415
  if (hasOwn(source, 'sidebarCollapsed')) {
399
416
  this.sidebarCollapsed = normalizeBoolean(source.sidebarCollapsed, false);
400
417
  }
418
+ if (hasOwn(source, 'configModeVisibility') && typeof this.normalizeConfigModeVisibility === 'function') {
419
+ this.configModeVisibility = this.normalizeConfigModeVisibility(source.configModeVisibility);
420
+ }
401
421
  if (hasOwn(source, 'starPrompted')) {
402
422
  this.starPrompted = normalizeBoolean(source.starPrompted, false);
403
423
  }
404
- if (hasOwn(source, 'taskOrchestrationTabEnabled')) {
405
- this.taskOrchestrationTabEnabled = normalizeBoolean(source.taskOrchestrationTabEnabled, true);
406
- }
407
424
  if (hasOwn(source, 'sessionLoadNativeDialog')) {
408
425
  this.sessionLoadNativeDialog = normalizeBoolean(source.sessionLoadNativeDialog, false);
409
426
  }