codexmate 0.0.56 → 0.1.1

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 (42) hide show
  1. package/README.md +2 -2
  2. package/README.vi.md +1 -0
  3. package/README.zh.md +2 -2
  4. package/cli/openai-bridge-retry.js +62 -0
  5. package/cli/openai-bridge-runtime.js +1819 -0
  6. package/cli/openai-bridge.js +137 -2048
  7. package/cli.js +749 -133
  8. package/lib/task-orchestrator.js +90 -21
  9. package/lib/task-workspace-chat.js +292 -0
  10. package/package.json +2 -2
  11. package/web-ui/app.js +67 -131
  12. package/web-ui/modules/app.computed.main-tabs.mjs +304 -7
  13. package/web-ui/modules/app.methods.agents.mjs +192 -1
  14. package/web-ui/modules/app.methods.claude-config.mjs +65 -25
  15. package/web-ui/modules/app.methods.navigation.mjs +67 -83
  16. package/web-ui/modules/app.methods.openclaw-editing.mjs +3 -6
  17. package/web-ui/modules/app.methods.providers.mjs +40 -10
  18. package/web-ui/modules/app.methods.session-actions.mjs +1 -12
  19. package/web-ui/modules/app.methods.session-browser.mjs +23 -54
  20. package/web-ui/modules/app.methods.session-trash.mjs +0 -1
  21. package/web-ui/modules/app.methods.startup-claude.mjs +16 -31
  22. package/web-ui/modules/app.methods.task-orchestration.mjs +347 -8
  23. package/web-ui/modules/app.methods.tool-config-permissions.mjs +0 -3
  24. package/web-ui/modules/app.methods.web-ui-preferences.mjs +442 -68
  25. package/web-ui/modules/config-template-confirm-pref.mjs +2 -3
  26. package/web-ui/modules/i18n/locales/en.mjs +181 -30
  27. package/web-ui/modules/i18n/locales/ja.mjs +178 -27
  28. package/web-ui/modules/i18n/locales/vi.mjs +180 -29
  29. package/web-ui/modules/i18n/locales/zh-tw.mjs +181 -30
  30. package/web-ui/modules/i18n/locales/zh.mjs +183 -32
  31. package/web-ui/modules/i18n.mjs +5 -12
  32. package/web-ui/modules/sessions-filters-url.mjs +1 -2
  33. package/web-ui/partials/index/layout-header.html +44 -38
  34. package/web-ui/partials/index/modals-basic.html +26 -0
  35. package/web-ui/partials/index/panel-orchestration.html +489 -282
  36. package/web-ui/partials/index/panel-prompts.html +66 -3
  37. package/web-ui/res/web-ui-render.precompiled.js +1181 -604
  38. package/web-ui/styles/layout-shell.css +157 -1
  39. package/web-ui/styles/modals-core.css +173 -0
  40. package/web-ui/styles/navigation-panels.css +11 -0
  41. package/web-ui/styles/responsive.css +32 -0
  42. 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', () => {
@@ -75,6 +74,12 @@ document.addEventListener('DOMContentLoaded', () => {
75
74
  showAgentsModal: false,
76
75
  promptsSubTab: 'codex',
77
76
  projectClaudeMdPath: '',
77
+ promptPresets: [],
78
+ selectedPromptPresetId: '',
79
+ promptPresetNameDraft: '',
80
+ promptPresetRenameDraft: {},
81
+ promptPresetSaving: false,
82
+ __skipNextPromptsSubTabLoad: false,
78
83
  projectPathOptions: [],
79
84
  projectPathOptionsLoading: false,
80
85
  showSkillsModal: false,
@@ -174,7 +179,7 @@ document.addEventListener('DOMContentLoaded', () => {
174
179
  ticket: 0
175
180
  },
176
181
  sessionsViewMode: 'browser',
177
- sessionsUsageTimeRange: (function () { try { const saved = localStorage.getItem('sessionsUsageTimeRange'); if (saved === '7d' || saved === '30d' || saved === 'all') return saved; } catch (_) {} return '7d'; })(),
182
+ sessionsUsageTimeRange: '7d',
178
183
  sessionsUsageList: [],
179
184
  sessionsUsageCompareEnabled: false,
180
185
  sessionsUsageSelectedDayKey: '',
@@ -285,9 +290,9 @@ document.addEventListener('DOMContentLoaded', () => {
285
290
  appVersionStatusChecked: false,
286
291
  appVersionStatusCheckedAt: '',
287
292
  appVersionStatusSource: '',
288
- newProvider: { name: '', url: '', key: '', model: '', useTransform: false },
293
+ newProvider: { name: '', url: '', key: '', model: '', useTransform: false, openaiBridgeMaxRetries: 2 },
289
294
  resetConfigLoading: false,
290
- editingProvider: { name: '', url: '', key: '', readOnly: false, nonEditable: false },
295
+ editingProvider: { name: '', url: '', key: '', readOnly: false, nonEditable: false, useTransform: false, openaiBridgeMaxRetries: 2 },
291
296
  newModelName: '',
292
297
  currentClaudeConfig: '',
293
298
  currentClaudeModel: '',
@@ -391,22 +396,7 @@ document.addEventListener('DOMContentLoaded', () => {
391
396
  providerCacheError: '',
392
397
  providerCacheRequestSeq: 0,
393
398
  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
- })(),
399
+ toolConfigPermissions: { codex: false, claude: false, opencode: false },
410
400
  toolConfigPermissionSaving: { codex: false, claude: false, opencode: false },
411
401
  sessionTrashEnabled: true,
412
402
  sessionTrashItems: [],
@@ -451,6 +441,9 @@ document.addEventListener('DOMContentLoaded', () => {
451
441
  opencodeMaxTokens: '',
452
442
  opencodeReasoningEffort: '',
453
443
  forceCompactLayout: false,
444
+ sidebarCollapsed: false,
445
+ sessionLoadNativeDialog: false,
446
+ starPrompted: false,
454
447
  taskOrchestrationTabEnabled: true,
455
448
  taskOrchestration: {
456
449
  loading: false,
@@ -460,11 +453,14 @@ document.addEventListener('DOMContentLoaded', () => {
460
453
  queueStarting: false,
461
454
  retrying: false,
462
455
  target: '',
456
+ chatDraft: '',
463
457
  title: '',
464
458
  notes: '',
459
+ workspacePath: '',
460
+ threadId: '',
465
461
  followUpsText: '',
466
462
  workflowIdsText: '',
467
- selectedEngine: 'codex',
463
+ selectedEngine: 'openai-chat',
468
464
  runMode: 'write',
469
465
  concurrency: 2,
470
466
  autoFixRounds: 1,
@@ -482,6 +478,7 @@ document.addEventListener('DOMContentLoaded', () => {
482
478
  selectedRunLoading: false,
483
479
  selectedRunError: '',
484
480
  detailRequestToken: 0,
481
+ settingsOpen: false,
485
482
  lastLoadedAt: '',
486
483
  lastError: ''
487
484
  },
@@ -501,9 +498,8 @@ document.addEventListener('DOMContentLoaded', () => {
501
498
  if (pathname === '/web-ui' || pathname === '/web-ui/' || pathname === '/web-ui/index.html') {
502
499
  const url = new URL(window.location.href);
503
500
  url.pathname = '/';
504
- // 移除查询参数和 hash,保持 URL 纯净
505
- url.search = '';
506
- url.hash = '';
501
+ // Preserve startup query/hash flags while normalizing the legacy web-ui path.
502
+ // Feature gates such as ?taskOrchestration=1 are consumed below after redirect.
507
503
  window.location.replace(url.toString());
508
504
  return;
509
505
  }
@@ -536,25 +532,15 @@ document.addEventListener('DOMContentLoaded', () => {
536
532
  this.agentsModalTitle = this.t('modal.agents.title');
537
533
  this.agentsModalHint = this.t('modal.agents.hint');
538
534
  }
535
+ try {
536
+ const url = new URL(window.location.href);
537
+ const requestedTaskOrchestration = String(url.searchParams.get('taskOrchestration') || '').trim().toLowerCase();
538
+ if (requestedTaskOrchestration === '1' || requestedTaskOrchestration === 'true') {
539
+ this.taskOrchestrationTabEnabled = true;
540
+ }
541
+ } catch (_) {}
539
542
  {
540
- const NAV_STATE_STORAGE_KEY = 'codexmateNavState.v1';
541
543
  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
544
  let urlMainTab = '';
559
545
  try {
560
546
  const url = new URL(window.location.href);
@@ -564,25 +550,13 @@ document.addEventListener('DOMContentLoaded', () => {
564
550
  } catch (_) {
565
551
  urlMainTab = '';
566
552
  }
567
- const resolvedMainTab = urlMainTab && mainTabSet.has(urlMainTab)
568
- ? urlMainTab
569
- : nextMainTab;
570
- if (nextSettingsTab && (nextSettingsTab === 'general' || nextSettingsTab === 'data')) {
571
- this.settingsTab = nextSettingsTab;
553
+ let resolvedMainTab = urlMainTab && mainTabSet.has(urlMainTab) ? urlMainTab : '';
554
+ if (typeof this.isMainTabDisabled === 'function' && this.isMainTabDisabled(resolvedMainTab)) {
555
+ resolvedMainTab = typeof this.getFirstSelectableMainTab === 'function'
556
+ ? this.getFirstSelectableMainTab()
557
+ : 'dashboard';
572
558
  }
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) {
559
+ if (resolvedMainTab && mainTabSet.has(resolvedMainTab) && resolvedMainTab !== this.mainTab) {
586
560
  this.__navStateRestoring = true;
587
561
  try {
588
562
  this.switchMainTab(resolvedMainTab);
@@ -593,61 +567,26 @@ document.addEventListener('DOMContentLoaded', () => {
593
567
  }
594
568
  this.initSessionStandalone();
595
569
  this.updateCompactLayoutMode();
596
- if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
597
- this.mainTab = 'config';
570
+ if (typeof this.isMainTabDisabled === 'function' && this.isMainTabDisabled(this.mainTab)) {
571
+ const fallbackTab = typeof this.getFirstSelectableMainTab === 'function'
572
+ ? this.getFirstSelectableMainTab()
573
+ : 'dashboard';
574
+ this.switchMainTab(fallbackTab);
575
+ } else if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
576
+ this.switchMainTab('dashboard');
598
577
  }
599
578
  this.restoreSessionFilterCache();
600
579
  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
580
  window.addEventListener('resize', this.onWindowResize);
622
581
  window.addEventListener('keydown', this.handleGlobalKeydown);
623
582
  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;
583
+ if (typeof this.normalizeStoredClaudeConfigs === 'function') {
584
+ const claudeConfigsChanged = this.normalizeStoredClaudeConfigs();
585
+ if (claudeConfigsChanged && typeof this.persistWebUiPreferences === 'function') {
586
+ this.persistWebUiPreferences({
587
+ claudeConfigs: this.claudeConfigs,
588
+ currentClaudeConfig: this.currentClaudeConfig || ''
589
+ });
651
590
  }
652
591
  }
653
592
  if (!this.currentClaudeConfig) {
@@ -681,17 +620,7 @@ document.addEventListener('DOMContentLoaded', () => {
681
620
  }
682
621
  return normalized;
683
622
  };
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
- }
623
+ this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
695
624
  const configNames = Object.keys(this.openclawConfigs);
696
625
  if (configNames.length > 0) {
697
626
  this.currentOpenclawConfig = this.openclawConfigs['默认配置'] ? '默认配置' : configNames[0];
@@ -774,8 +703,12 @@ document.addEventListener('DOMContentLoaded', () => {
774
703
  this._initialLoadTimer = 0;
775
704
  }
776
705
  if (this.__webUiPreferencesPersistTimer) {
777
- clearTimeout(this.__webUiPreferencesPersistTimer);
778
- this.__webUiPreferencesPersistTimer = 0;
706
+ if (typeof this.flushWebUiPreferences === 'function') {
707
+ this.flushWebUiPreferences();
708
+ } else {
709
+ clearTimeout(this.__webUiPreferencesPersistTimer);
710
+ this.__webUiPreferencesPersistTimer = 0;
711
+ }
779
712
  }
780
713
  window.removeEventListener('resize', this.onWindowResize);
781
714
  window.removeEventListener('keydown', this.handleGlobalKeydown);
@@ -790,6 +723,15 @@ document.addEventListener('DOMContentLoaded', () => {
790
723
 
791
724
  watch: {
792
725
  mainTab(newTab) {
726
+ if (typeof this.isMainTabDisabled === 'function' && this.isMainTabDisabled(newTab)) {
727
+ const fallbackTab = typeof this.getFirstSelectableMainTab === 'function'
728
+ ? this.getFirstSelectableMainTab()
729
+ : 'dashboard';
730
+ if (fallbackTab && fallbackTab !== newTab && typeof this.switchMainTab === 'function') {
731
+ this.switchMainTab(fallbackTab);
732
+ }
733
+ return;
734
+ }
793
735
  if (newTab === 'prompts' && typeof this.loadPromptsContent === 'function') {
794
736
  if (this.promptsSubTab === 'claude-project' && !this.projectPathOptions.length && !this.projectPathOptionsLoading && typeof this.loadProjectPathOptions === 'function') {
795
737
  this.loadProjectPathOptions();
@@ -798,24 +740,18 @@ document.addEventListener('DOMContentLoaded', () => {
798
740
  }
799
741
  },
800
742
  promptsSubTab(newVal) {
801
- try {
802
- localStorage.setItem('codexmate_prompts_sub_tab', newVal);
803
- } catch (_) {}
804
743
  if (typeof this.persistWebUiPreferences === 'function') {
805
744
  this.persistWebUiPreferences({ promptsSubTab: newVal });
806
745
  }
746
+ if (this.__skipNextPromptsSubTabLoad) {
747
+ this.__skipNextPromptsSubTabLoad = false;
748
+ return;
749
+ }
807
750
  if (this.mainTab === 'prompts' && typeof this.loadPromptsContent === 'function') {
808
751
  this.loadPromptsContent();
809
752
  }
810
753
  },
811
754
  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
755
  if (typeof this.persistWebUiPreferences === 'function') {
820
756
  this.persistWebUiPreferences({ projectClaudeMdPath: newPath || '' });
821
757
  }