codexmate 0.0.56 → 0.0.57

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 (31) hide show
  1. package/cli.js +680 -129
  2. package/lib/task-orchestrator.js +90 -21
  3. package/lib/task-workspace-chat.js +292 -0
  4. package/package.json +2 -2
  5. package/web-ui/app.js +55 -129
  6. package/web-ui/modules/app.computed.main-tabs.mjs +304 -7
  7. package/web-ui/modules/app.methods.agents.mjs +3 -0
  8. package/web-ui/modules/app.methods.claude-config.mjs +65 -25
  9. package/web-ui/modules/app.methods.navigation.mjs +67 -83
  10. package/web-ui/modules/app.methods.openclaw-editing.mjs +3 -6
  11. package/web-ui/modules/app.methods.session-actions.mjs +1 -12
  12. package/web-ui/modules/app.methods.session-browser.mjs +23 -54
  13. package/web-ui/modules/app.methods.session-trash.mjs +0 -1
  14. package/web-ui/modules/app.methods.startup-claude.mjs +16 -31
  15. package/web-ui/modules/app.methods.task-orchestration.mjs +347 -8
  16. package/web-ui/modules/app.methods.tool-config-permissions.mjs +0 -3
  17. package/web-ui/modules/app.methods.web-ui-preferences.mjs +415 -68
  18. package/web-ui/modules/config-template-confirm-pref.mjs +2 -3
  19. package/web-ui/modules/i18n/locales/en.mjs +146 -26
  20. package/web-ui/modules/i18n/locales/ja.mjs +143 -23
  21. package/web-ui/modules/i18n/locales/vi.mjs +145 -25
  22. package/web-ui/modules/i18n/locales/zh-tw.mjs +146 -26
  23. package/web-ui/modules/i18n/locales/zh.mjs +148 -28
  24. package/web-ui/modules/i18n.mjs +5 -12
  25. package/web-ui/modules/sessions-filters-url.mjs +1 -2
  26. package/web-ui/partials/index/layout-header.html +37 -14
  27. package/web-ui/partials/index/panel-orchestration.html +489 -282
  28. package/web-ui/res/web-ui-render.precompiled.js +1049 -610
  29. package/web-ui/styles/layout-shell.css +157 -1
  30. package/web-ui/styles/navigation-panels.css +11 -0
  31. package/web-ui/styles/task-orchestration.css +2161 -4
package/web-ui/app.js CHANGED
@@ -6,7 +6,6 @@ import {
6
6
  } from './modules/app.constants.mjs';
7
7
  import { createAppComputed } from './modules/app.computed.index.mjs';
8
8
  import { createAppMethods } from './modules/app.methods.index.mjs';
9
- import { loadConfigTemplateDiffConfirmEnabledFromStorage } from './modules/config-template-confirm-pref.mjs';
10
9
  import { installWebUiUrlCanonicalization } from './modules/sessions-filters-url.mjs';
11
10
 
12
11
  document.addEventListener('DOMContentLoaded', () => {
@@ -174,7 +173,7 @@ document.addEventListener('DOMContentLoaded', () => {
174
173
  ticket: 0
175
174
  },
176
175
  sessionsViewMode: 'browser',
177
- sessionsUsageTimeRange: (function () { try { const saved = localStorage.getItem('sessionsUsageTimeRange'); if (saved === '7d' || saved === '30d' || saved === 'all') return saved; } catch (_) {} return '7d'; })(),
176
+ sessionsUsageTimeRange: '7d',
178
177
  sessionsUsageList: [],
179
178
  sessionsUsageCompareEnabled: false,
180
179
  sessionsUsageSelectedDayKey: '',
@@ -391,22 +390,7 @@ document.addEventListener('DOMContentLoaded', () => {
391
390
  providerCacheError: '',
392
391
  providerCacheRequestSeq: 0,
393
392
  settingsTab: 'general',
394
- toolConfigPermissions: (function() {
395
- try {
396
- const cached = localStorage.getItem('toolConfigPermissions');
397
- if (cached) {
398
- const parsed = JSON.parse(cached);
399
- if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
400
- return {
401
- codex: parsed.codex === true,
402
- claude: parsed.claude === true,
403
- opencode: parsed.opencode === true
404
- };
405
- }
406
- }
407
- } catch (_) {}
408
- return { codex: false, claude: false, opencode: false };
409
- })(),
393
+ toolConfigPermissions: { codex: false, claude: false, opencode: false },
410
394
  toolConfigPermissionSaving: { codex: false, claude: false, opencode: false },
411
395
  sessionTrashEnabled: true,
412
396
  sessionTrashItems: [],
@@ -451,6 +435,9 @@ document.addEventListener('DOMContentLoaded', () => {
451
435
  opencodeMaxTokens: '',
452
436
  opencodeReasoningEffort: '',
453
437
  forceCompactLayout: false,
438
+ sidebarCollapsed: false,
439
+ sessionLoadNativeDialog: false,
440
+ starPrompted: false,
454
441
  taskOrchestrationTabEnabled: true,
455
442
  taskOrchestration: {
456
443
  loading: false,
@@ -460,11 +447,14 @@ document.addEventListener('DOMContentLoaded', () => {
460
447
  queueStarting: false,
461
448
  retrying: false,
462
449
  target: '',
450
+ chatDraft: '',
463
451
  title: '',
464
452
  notes: '',
453
+ workspacePath: '',
454
+ threadId: '',
465
455
  followUpsText: '',
466
456
  workflowIdsText: '',
467
- selectedEngine: 'codex',
457
+ selectedEngine: 'openai-chat',
468
458
  runMode: 'write',
469
459
  concurrency: 2,
470
460
  autoFixRounds: 1,
@@ -482,6 +472,7 @@ document.addEventListener('DOMContentLoaded', () => {
482
472
  selectedRunLoading: false,
483
473
  selectedRunError: '',
484
474
  detailRequestToken: 0,
475
+ settingsOpen: false,
485
476
  lastLoadedAt: '',
486
477
  lastError: ''
487
478
  },
@@ -501,9 +492,8 @@ document.addEventListener('DOMContentLoaded', () => {
501
492
  if (pathname === '/web-ui' || pathname === '/web-ui/' || pathname === '/web-ui/index.html') {
502
493
  const url = new URL(window.location.href);
503
494
  url.pathname = '/';
504
- // 移除查询参数和 hash,保持 URL 纯净
505
- url.search = '';
506
- url.hash = '';
495
+ // Preserve startup query/hash flags while normalizing the legacy web-ui path.
496
+ // Feature gates such as ?taskOrchestration=1 are consumed below after redirect.
507
497
  window.location.replace(url.toString());
508
498
  return;
509
499
  }
@@ -536,25 +526,15 @@ document.addEventListener('DOMContentLoaded', () => {
536
526
  this.agentsModalTitle = this.t('modal.agents.title');
537
527
  this.agentsModalHint = this.t('modal.agents.hint');
538
528
  }
529
+ try {
530
+ const url = new URL(window.location.href);
531
+ const requestedTaskOrchestration = String(url.searchParams.get('taskOrchestration') || '').trim().toLowerCase();
532
+ if (requestedTaskOrchestration === '1' || requestedTaskOrchestration === 'true') {
533
+ this.taskOrchestrationTabEnabled = true;
534
+ }
535
+ } catch (_) {}
539
536
  {
540
- const NAV_STATE_STORAGE_KEY = 'codexmateNavState.v1';
541
537
  const mainTabSet = new Set(['dashboard', 'config', 'sessions', 'usage', 'orchestration', 'market', 'plugins', 'docs', 'settings', 'trash', 'prompts']);
542
- let restored = null;
543
- try {
544
- const raw = localStorage.getItem(NAV_STATE_STORAGE_KEY) || '';
545
- restored = raw ? JSON.parse(raw) : null;
546
- } catch (_) {
547
- restored = null;
548
- }
549
- const nextMainTab = restored && typeof restored.mainTab === 'string'
550
- ? restored.mainTab.trim().toLowerCase()
551
- : '';
552
- const nextConfigMode = restored && typeof restored.configMode === 'string'
553
- ? restored.configMode.trim().toLowerCase()
554
- : '';
555
- const nextSettingsTab = restored && typeof restored.settingsTab === 'string'
556
- ? restored.settingsTab.trim().toLowerCase()
557
- : '';
558
538
  let urlMainTab = '';
559
539
  try {
560
540
  const url = new URL(window.location.href);
@@ -564,25 +544,13 @@ document.addEventListener('DOMContentLoaded', () => {
564
544
  } catch (_) {
565
545
  urlMainTab = '';
566
546
  }
567
- const resolvedMainTab = urlMainTab && mainTabSet.has(urlMainTab)
568
- ? urlMainTab
569
- : nextMainTab;
570
- if (nextSettingsTab && (nextSettingsTab === 'general' || nextSettingsTab === 'data')) {
571
- this.settingsTab = nextSettingsTab;
547
+ let resolvedMainTab = urlMainTab && mainTabSet.has(urlMainTab) ? urlMainTab : '';
548
+ if (typeof this.isMainTabDisabled === 'function' && this.isMainTabDisabled(resolvedMainTab)) {
549
+ resolvedMainTab = typeof this.getFirstSelectableMainTab === 'function'
550
+ ? this.getFirstSelectableMainTab()
551
+ : 'dashboard';
572
552
  }
573
- if (nextConfigMode && typeof this.switchConfigMode === 'function') {
574
- this.__navStateRestoring = true;
575
- try {
576
- if (nextConfigMode === 'codex' || nextConfigMode === 'claude' || nextConfigMode === 'openclaw' || nextConfigMode === 'opencode') {
577
- this.configMode = nextConfigMode;
578
- }
579
- if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
580
- this.switchMainTab(resolvedMainTab);
581
- }
582
- } finally {
583
- this.__navStateRestoring = false;
584
- }
585
- } else if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
553
+ if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
586
554
  this.__navStateRestoring = true;
587
555
  try {
588
556
  this.switchMainTab(resolvedMainTab);
@@ -593,61 +561,26 @@ document.addEventListener('DOMContentLoaded', () => {
593
561
  }
594
562
  this.initSessionStandalone();
595
563
  this.updateCompactLayoutMode();
596
- if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
597
- this.mainTab = 'config';
564
+ if (typeof this.isMainTabDisabled === 'function' && this.isMainTabDisabled(this.mainTab)) {
565
+ const fallbackTab = typeof this.getFirstSelectableMainTab === 'function'
566
+ ? this.getFirstSelectableMainTab()
567
+ : 'dashboard';
568
+ this.switchMainTab(fallbackTab);
569
+ } else if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
570
+ this.switchMainTab('dashboard');
598
571
  }
599
572
  this.restoreSessionFilterCache();
600
573
  this.restoreSessionPinnedMap();
601
- this.shareCommandPrefix = this.normalizeShareCommandPrefix(localStorage.getItem('codexmateShareCommandPrefix'));
602
- this.sessionTrashEnabled = this.normalizeSessionTrashEnabled(localStorage.getItem('codexmateSessionTrashEnabled'));
603
- this.sessionTrashRetentionDays = this.normalizeSessionTrashRetentionDays(localStorage.getItem('codexmateSessionTrashRetentionDays'));
604
- try {
605
- var savedTimelineStyle = localStorage.getItem('codexmateSessionTimelineStyle');
606
- this.sessionTimelineStyle = savedTimelineStyle === 'bar' ? 'bar' : 'dots';
607
- } catch (_) {}
608
- this.configTemplateDiffConfirmEnabled = loadConfigTemplateDiffConfirmEnabledFromStorage(localStorage);
609
- try {
610
- var savedProjectPath = localStorage.getItem('codexmate_project_claude_md_path');
611
- if (savedProjectPath) {
612
- this.projectClaudeMdPath = savedProjectPath;
613
- }
614
- } catch (_) {}
615
- try {
616
- var savedSubTab = localStorage.getItem('codexmate_prompts_sub_tab');
617
- if (savedSubTab === 'codex' || savedSubTab === 'claude-project') {
618
- this.promptsSubTab = savedSubTab;
619
- }
620
- } catch (_) {}
621
574
  window.addEventListener('resize', this.onWindowResize);
622
575
  window.addEventListener('keydown', this.handleGlobalKeydown);
623
576
  window.addEventListener('beforeunload', this.handleBeforeUnload);
624
- const savedConfigs = localStorage.getItem('claudeConfigs');
625
- if (savedConfigs) {
626
- try {
627
- this.claudeConfigs = JSON.parse(savedConfigs);
628
- for (const [name, config] of Object.entries(this.claudeConfigs)) {
629
- if (config.apiKey && config.apiKey.includes('****')) {
630
- config.apiKey = '';
631
- config.hasKey = false;
632
- }
633
- const targetApiRaw = typeof config.targetApi === 'string' ? config.targetApi.trim().toLowerCase() : '';
634
- if (targetApiRaw === 'chat_completions' || targetApiRaw === 'chat-completions' || targetApiRaw === 'chat/completions') {
635
- config.targetApi = 'chat_completions';
636
- } else if (targetApiRaw === 'ollama') {
637
- config.targetApi = 'ollama';
638
- } else {
639
- config.targetApi = 'responses';
640
- }
641
- }
642
- localStorage.setItem('claudeConfigs', JSON.stringify(this.claudeConfigs));
643
- } catch (e) {
644
- console.error('加载 Claude 配置失败:', e);
645
- }
646
- }
647
- {
648
- const savedCurrentClaudeConfig = localStorage.getItem('currentClaudeConfig');
649
- if (savedCurrentClaudeConfig && this.claudeConfigs[savedCurrentClaudeConfig]) {
650
- this.currentClaudeConfig = savedCurrentClaudeConfig;
577
+ if (typeof this.normalizeStoredClaudeConfigs === 'function') {
578
+ const claudeConfigsChanged = this.normalizeStoredClaudeConfigs();
579
+ if (claudeConfigsChanged && typeof this.persistWebUiPreferences === 'function') {
580
+ this.persistWebUiPreferences({
581
+ claudeConfigs: this.claudeConfigs,
582
+ currentClaudeConfig: this.currentClaudeConfig || ''
583
+ });
651
584
  }
652
585
  }
653
586
  if (!this.currentClaudeConfig) {
@@ -681,17 +614,7 @@ document.addEventListener('DOMContentLoaded', () => {
681
614
  }
682
615
  return normalized;
683
616
  };
684
- const savedOpenclawConfigs = localStorage.getItem('openclawConfigs');
685
- if (savedOpenclawConfigs) {
686
- try {
687
- this.openclawConfigs = normalizeOpenclawConfigs(JSON.parse(savedOpenclawConfigs));
688
- } catch (e) {
689
- console.error('加载 OpenClaw 配置失败:', e);
690
- this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
691
- }
692
- } else {
693
- this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
694
- }
617
+ this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
695
618
  const configNames = Object.keys(this.openclawConfigs);
696
619
  if (configNames.length > 0) {
697
620
  this.currentOpenclawConfig = this.openclawConfigs['默认配置'] ? '默认配置' : configNames[0];
@@ -774,8 +697,12 @@ document.addEventListener('DOMContentLoaded', () => {
774
697
  this._initialLoadTimer = 0;
775
698
  }
776
699
  if (this.__webUiPreferencesPersistTimer) {
777
- clearTimeout(this.__webUiPreferencesPersistTimer);
778
- this.__webUiPreferencesPersistTimer = 0;
700
+ if (typeof this.flushWebUiPreferences === 'function') {
701
+ this.flushWebUiPreferences();
702
+ } else {
703
+ clearTimeout(this.__webUiPreferencesPersistTimer);
704
+ this.__webUiPreferencesPersistTimer = 0;
705
+ }
779
706
  }
780
707
  window.removeEventListener('resize', this.onWindowResize);
781
708
  window.removeEventListener('keydown', this.handleGlobalKeydown);
@@ -790,6 +717,15 @@ document.addEventListener('DOMContentLoaded', () => {
790
717
 
791
718
  watch: {
792
719
  mainTab(newTab) {
720
+ if (typeof this.isMainTabDisabled === 'function' && this.isMainTabDisabled(newTab)) {
721
+ const fallbackTab = typeof this.getFirstSelectableMainTab === 'function'
722
+ ? this.getFirstSelectableMainTab()
723
+ : 'dashboard';
724
+ if (fallbackTab && fallbackTab !== newTab && typeof this.switchMainTab === 'function') {
725
+ this.switchMainTab(fallbackTab);
726
+ }
727
+ return;
728
+ }
793
729
  if (newTab === 'prompts' && typeof this.loadPromptsContent === 'function') {
794
730
  if (this.promptsSubTab === 'claude-project' && !this.projectPathOptions.length && !this.projectPathOptionsLoading && typeof this.loadProjectPathOptions === 'function') {
795
731
  this.loadProjectPathOptions();
@@ -798,9 +734,6 @@ document.addEventListener('DOMContentLoaded', () => {
798
734
  }
799
735
  },
800
736
  promptsSubTab(newVal) {
801
- try {
802
- localStorage.setItem('codexmate_prompts_sub_tab', newVal);
803
- } catch (_) {}
804
737
  if (typeof this.persistWebUiPreferences === 'function') {
805
738
  this.persistWebUiPreferences({ promptsSubTab: newVal });
806
739
  }
@@ -809,13 +742,6 @@ document.addEventListener('DOMContentLoaded', () => {
809
742
  }
810
743
  },
811
744
  projectClaudeMdPath(newPath) {
812
- try {
813
- if (newPath) {
814
- localStorage.setItem('codexmate_project_claude_md_path', newPath);
815
- } else {
816
- localStorage.removeItem('codexmate_project_claude_md_path');
817
- }
818
- } catch (_) {}
819
745
  if (typeof this.persistWebUiPreferences === 'function') {
820
746
  this.persistWebUiPreferences({ projectClaudeMdPath: newPath || '' });
821
747
  }