codexmate 0.0.20 → 0.0.22

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 (96) hide show
  1. package/README.md +289 -152
  2. package/README.zh.md +321 -0
  3. package/cli/agents-files.js +224 -0
  4. package/cli/archive-helpers.js +446 -0
  5. package/cli/auth-profiles.js +359 -0
  6. package/cli/builtin-proxy.js +1044 -0
  7. package/cli/claude-proxy.js +998 -0
  8. package/cli/config-bootstrap.js +384 -0
  9. package/cli/openai-bridge.js +950 -0
  10. package/cli/openclaw-config.js +629 -0
  11. package/cli/session-usage.concurrent.js +28 -0
  12. package/cli/session-usage.js +112 -0
  13. package/cli/session-usage.models.js +176 -0
  14. package/cli/skills.js +1141 -0
  15. package/cli/zip-commands.js +510 -0
  16. package/cli.js +9408 -9719
  17. package/lib/cli-models-utils.js +109 -1
  18. package/lib/cli-path-utils.js +69 -0
  19. package/lib/cli-sessions.js +386 -0
  20. package/lib/download-artifacts.js +77 -0
  21. package/lib/task-orchestrator.js +869 -0
  22. package/package.json +14 -10
  23. package/res/logo.png +0 -0
  24. package/res/vue.global.prod.js +13 -0
  25. package/web-ui/app.js +193 -15
  26. package/web-ui/index.html +5 -1
  27. package/web-ui/logic.agents-diff.mjs +1 -1
  28. package/web-ui/logic.claude.mjs +60 -0
  29. package/web-ui/logic.runtime.mjs +11 -7
  30. package/web-ui/logic.sessions.mjs +372 -21
  31. package/web-ui/modules/api.mjs +22 -1
  32. package/web-ui/modules/app.computed.dashboard.mjs +23 -10
  33. package/web-ui/modules/app.computed.index.mjs +4 -0
  34. package/web-ui/modules/app.computed.main-tabs.mjs +198 -0
  35. package/web-ui/modules/app.computed.session.mjs +521 -9
  36. package/web-ui/modules/app.methods.agents.mjs +62 -11
  37. package/web-ui/modules/app.methods.codex-config.mjs +189 -34
  38. package/web-ui/modules/app.methods.index.mjs +7 -1
  39. package/web-ui/modules/app.methods.install.mjs +24 -20
  40. package/web-ui/modules/app.methods.navigation.mjs +142 -1
  41. package/web-ui/modules/app.methods.openclaw-core.mjs +339 -39
  42. package/web-ui/modules/app.methods.openclaw-editing.mjs +39 -4
  43. package/web-ui/modules/app.methods.openclaw-persist.mjs +122 -4
  44. package/web-ui/modules/app.methods.providers.mjs +192 -53
  45. package/web-ui/modules/app.methods.session-actions.mjs +99 -19
  46. package/web-ui/modules/app.methods.session-browser.mjs +196 -5
  47. package/web-ui/modules/app.methods.session-timeline.mjs +22 -15
  48. package/web-ui/modules/app.methods.session-trash.mjs +3 -0
  49. package/web-ui/modules/app.methods.startup-claude.mjs +70 -71
  50. package/web-ui/modules/app.methods.task-orchestration.mjs +471 -0
  51. package/web-ui/modules/config-mode.computed.mjs +2 -0
  52. package/web-ui/modules/config-template-confirm-pref.mjs +33 -0
  53. package/web-ui/modules/i18n.mjs +1609 -0
  54. package/web-ui/modules/plugins.computed.mjs +220 -0
  55. package/web-ui/modules/plugins.methods.mjs +620 -0
  56. package/web-ui/modules/plugins.storage.mjs +37 -0
  57. package/web-ui/partials/index/layout-footer.html +1 -57
  58. package/web-ui/partials/index/layout-header.html +299 -175
  59. package/web-ui/partials/index/modal-config-template-agents.html +79 -29
  60. package/web-ui/partials/index/modal-confirm-toast.html +1 -1
  61. package/web-ui/partials/index/modal-health-check.html +14 -14
  62. package/web-ui/partials/index/modal-openclaw-config.html +47 -42
  63. package/web-ui/partials/index/modal-skills.html +130 -114
  64. package/web-ui/partials/index/modals-basic.html +71 -102
  65. package/web-ui/partials/index/panel-config-claude.html +50 -12
  66. package/web-ui/partials/index/panel-config-codex.html +34 -37
  67. package/web-ui/partials/index/panel-config-openclaw.html +10 -16
  68. package/web-ui/partials/index/panel-docs.html +147 -0
  69. package/web-ui/partials/index/panel-market.html +38 -38
  70. package/web-ui/partials/index/panel-orchestration.html +397 -0
  71. package/web-ui/partials/index/panel-plugins.html +243 -0
  72. package/web-ui/partials/index/panel-sessions.html +51 -146
  73. package/web-ui/partials/index/panel-settings.html +188 -96
  74. package/web-ui/partials/index/panel-usage.html +353 -0
  75. package/web-ui/session-helpers.mjs +221 -10
  76. package/web-ui/styles/base-theme.css +120 -229
  77. package/web-ui/styles/controls-forms.css +59 -51
  78. package/web-ui/styles/docs-panel.css +247 -0
  79. package/web-ui/styles/layout-shell.css +394 -128
  80. package/web-ui/styles/modals-core.css +18 -3
  81. package/web-ui/styles/navigation-panels.css +184 -183
  82. package/web-ui/styles/plugins-panel.css +518 -0
  83. package/web-ui/styles/responsive.css +102 -62
  84. package/web-ui/styles/sessions-list.css +13 -27
  85. package/web-ui/styles/sessions-preview.css +13 -7
  86. package/web-ui/styles/sessions-toolbar-trash.css +25 -0
  87. package/web-ui/styles/sessions-usage.css +581 -6
  88. package/web-ui/styles/settings-panel.css +166 -0
  89. package/web-ui/styles/skills-list.css +16 -11
  90. package/web-ui/styles/skills-market.css +63 -2
  91. package/web-ui/styles/task-orchestration.css +776 -0
  92. package/web-ui/styles/titles-cards.css +67 -66
  93. package/web-ui/styles.css +4 -0
  94. package/README.en.md +0 -259
  95. package/res/screenshot.png +0 -0
  96. package/res/vue.global.js +0 -18552
package/web-ui/app.js CHANGED
@@ -6,6 +6,7 @@ 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';
9
10
 
10
11
  document.addEventListener('DOMContentLoaded', () => {
11
12
  if (typeof Vue === 'undefined') {
@@ -28,7 +29,9 @@ document.addEventListener('DOMContentLoaded', () => {
28
29
  const app = createApp({
29
30
  data() {
30
31
  return {
31
- mainTab: 'config',
32
+ lang: 'zh',
33
+ // 默认选中首个主标签:Docs
34
+ mainTab: 'docs',
32
35
  configMode: 'codex',
33
36
  currentProvider: '',
34
37
  currentModel: '',
@@ -63,7 +66,24 @@ document.addEventListener('DOMContentLoaded', () => {
63
66
  showHealthCheckDialog: false,
64
67
  showAgentsModal: false,
65
68
  showSkillsModal: false,
66
- showInstallModal: false,
69
+ // Plugins
70
+ pluginsActiveId: 'prompt-templates',
71
+ pluginsLoading: false,
72
+ promptTemplatesListRaw: [],
73
+ promptTemplatesLoadedOnce: false,
74
+ promptTemplatesKeyword: '',
75
+ promptTemplateSelectedId: '',
76
+ promptTemplateDraftRaw: null,
77
+ promptTemplateVarValuesRaw: {},
78
+ promptTemplatesMode: 'compose',
79
+ promptComposerCommand: '',
80
+ promptComposerPickerVisible: false,
81
+ promptComposerPickerKeyword: '',
82
+ promptComposerSelectedTemplateId: '',
83
+ promptComposerVarValuesRaw: {},
84
+ showPromptTemplateVarModal: false,
85
+ promptTemplateVarDraftName: '',
86
+ promptTemplateVarDraftError: '',
67
87
  showConfirmDialog: false,
68
88
  confirmDialogTitle: '',
69
89
  confirmDialogMessage: '',
@@ -75,10 +95,24 @@ document.addEventListener('DOMContentLoaded', () => {
75
95
  confirmDialogResolver: null,
76
96
  configTemplateContent: '',
77
97
  configTemplateApplying: false,
98
+ configTemplateDiffVisible: false,
99
+ configTemplateDiffLoading: false,
100
+ configTemplateDiffError: '',
101
+ configTemplateDiffLines: [],
102
+ configTemplateDiffStats: {
103
+ added: 0,
104
+ removed: 0,
105
+ unchanged: 0
106
+ },
107
+ configTemplateDiffHasChangesValue: false,
108
+ configTemplateDiffFingerprint: '',
109
+ _configTemplateDiffPreviewRequestToken: null,
110
+ configTemplateDiffConfirmEnabled: true,
78
111
  codexApplying: false,
79
112
  _pendingCodexApplyOptions: null,
80
113
  agentsContent: '',
81
114
  agentsPath: '',
115
+ agentsPath: '',
82
116
  agentsExists: false,
83
117
  agentsLineEnding: '\n',
84
118
  agentsLoading: false,
@@ -117,8 +151,18 @@ document.addEventListener('DOMContentLoaded', () => {
117
151
  skillsMarketLocalLoadedOnce: false,
118
152
  skillsMarketImportLoadedOnce: false,
119
153
  sessionPinnedMap: {},
154
+ __mainTabSwitchState: {
155
+ intent: '',
156
+ pendingTarget: '',
157
+ pendingConfigMode: '',
158
+ ticket: 0
159
+ },
120
160
  sessionsViewMode: 'browser',
121
161
  sessionsUsageTimeRange: '7d',
162
+ sessionsUsageList: [],
163
+ sessionsUsageLoadedOnce: false,
164
+ sessionsUsageLoading: false,
165
+ sessionsUsageError: '',
122
166
  sessionsList: [],
123
167
  sessionsLoadedOnce: false,
124
168
  sessionsLoading: false,
@@ -172,6 +216,9 @@ document.addEventListener('DOMContentLoaded', () => {
172
216
  sessionPreviewHeaderEl: null,
173
217
  sessionPreviewHeaderResizeObserver: null,
174
218
  sessionListRenderEnabled: false,
219
+ sessionListVisibleCount: 0,
220
+ sessionListInitialBatchSize: 20,
221
+ sessionListLoadStep: 40,
175
222
  sessionPreviewRenderEnabled: false,
176
223
  sessionTabRenderTicket: 0,
177
224
  sessionPreviewVisibleCount: 0,
@@ -192,12 +239,13 @@ document.addEventListener('DOMContentLoaded', () => {
192
239
  claudeSpeedLoading: {},
193
240
  claudeShareLoading: {},
194
241
  providerShareLoading: {},
242
+ shareCommandPrefix: 'npm start',
195
243
  providerSwitchInProgress: false,
196
244
  pendingProviderSwitch: '',
197
245
  providerSwitchDisplayTarget: '',
198
246
  healthCheckDialogLockedProvider: '',
199
247
  healthCheckDialogSelectedProvider: '',
200
- healthCheckDialogPrompt: '请简短回复:当前提供商连接正常。',
248
+ healthCheckDialogPrompt: '请简短回复:连接正常。',
201
249
  healthCheckDialogMessages: [],
202
250
  healthCheckDialogSending: false,
203
251
  healthCheckDialogLastResult: null,
@@ -227,7 +275,7 @@ document.addEventListener('DOMContentLoaded', () => {
227
275
  error: ''
228
276
  }
229
277
  ],
230
- newProvider: { name: '', url: '', key: '' },
278
+ newProvider: { name: '', url: '', key: '', useTransform: false },
231
279
  resetConfigLoading: false,
232
280
  editingProvider: { name: '', url: '', key: '', readOnly: false, nonEditable: false },
233
281
  newModelName: '',
@@ -259,6 +307,8 @@ document.addEventListener('DOMContentLoaded', () => {
259
307
  openclawConfigPath: '',
260
308
  openclawConfigExists: false,
261
309
  openclawLineEnding: '\n',
310
+ openclawAuthProfilesByProvider: {},
311
+ openclawPendingAuthProfileUpdates: {},
262
312
  openclawFileLoading: false,
263
313
  openclawSaving: false,
264
314
  openclawApplying: false,
@@ -279,7 +329,16 @@ document.addEventListener('DOMContentLoaded', () => {
279
329
  openclawQuick: {
280
330
  providerName: '',
281
331
  baseUrl: '',
332
+ baseUrlReadOnly: false,
333
+ baseUrlDisplayKind: 'missing',
282
334
  apiKey: '',
335
+ apiKeyReadOnly: false,
336
+ apiKeyDisplayKind: 'missing',
337
+ apiKeySourceKind: '',
338
+ apiKeySourceProfileId: '',
339
+ apiKeySourceWriteField: '',
340
+ apiKeySourceOriginalValue: '',
341
+ apiKeySourceCredentialType: '',
283
342
  apiType: 'openai-responses',
284
343
  modelId: '',
285
344
  modelName: '',
@@ -303,6 +362,7 @@ document.addEventListener('DOMContentLoaded', () => {
303
362
  codexDownloadProgress: 0,
304
363
  codexDownloadTimer: null,
305
364
  settingsTab: 'backup',
365
+ sessionTrashEnabled: true,
306
366
  sessionTrashItems: [],
307
367
  sessionTrashVisibleCount: SESSION_TRASH_PAGE_SIZE,
308
368
  sessionTrashTotalCount: 0,
@@ -321,13 +381,60 @@ document.addEventListener('DOMContentLoaded', () => {
321
381
  claudeImportLoading: false,
322
382
  codexImportLoading: false,
323
383
  codexAuthProfiles: [],
324
- forceCompactLayout: false
384
+ forceCompactLayout: false,
385
+ taskOrchestrationTabEnabled: false,
386
+ taskOrchestration: {
387
+ loading: false,
388
+ planning: false,
389
+ running: false,
390
+ queueAdding: false,
391
+ queueStarting: false,
392
+ retrying: false,
393
+ target: '',
394
+ title: '',
395
+ notes: '',
396
+ followUpsText: '',
397
+ workflowIdsText: '',
398
+ selectedEngine: 'codex',
399
+ allowWrite: false,
400
+ dryRun: false,
401
+ concurrency: 2,
402
+ autoFixRounds: 1,
403
+ plan: null,
404
+ planIssues: [],
405
+ planWarnings: [],
406
+ overviewWarnings: [],
407
+ workflows: [],
408
+ queue: [],
409
+ runs: [],
410
+ selectedRunId: '',
411
+ workspaceTab: 'queue',
412
+ selectedRunDetail: null,
413
+ selectedRunLoading: false,
414
+ selectedRunError: '',
415
+ detailRequestToken: 0,
416
+ lastLoadedAt: '',
417
+ lastError: ''
418
+ },
419
+ _taskOrchestrationPollTimer: 0
325
420
  };
326
421
  },
327
422
 
328
423
  mounted() {
424
+ if (typeof this.initI18n === 'function') {
425
+ this.initI18n();
426
+ }
427
+ if (typeof this.t === 'function') {
428
+ this.confirmDialogConfirmText = this.t('confirm.ok');
429
+ this.confirmDialogCancelText = this.t('confirm.cancel');
430
+ this.agentsModalTitle = this.t('modal.agents.title');
431
+ this.agentsModalHint = this.t('modal.agents.hint');
432
+ }
329
433
  this.initSessionStandalone();
330
434
  this.updateCompactLayoutMode();
435
+ if (!this.taskOrchestrationTabEnabled && this.mainTab === 'orchestration') {
436
+ this.mainTab = 'config';
437
+ }
331
438
  const savedSessionYolo = localStorage.getItem('codexmateSessionResumeYolo');
332
439
  if (savedSessionYolo === '0' || savedSessionYolo === 'false') {
333
440
  this.sessionResumeWithYolo = false;
@@ -336,6 +443,9 @@ document.addEventListener('DOMContentLoaded', () => {
336
443
  }
337
444
  this.restoreSessionFilterCache();
338
445
  this.restoreSessionPinnedMap();
446
+ this.shareCommandPrefix = this.normalizeShareCommandPrefix(localStorage.getItem('codexmateShareCommandPrefix'));
447
+ this.sessionTrashEnabled = this.normalizeSessionTrashEnabled(localStorage.getItem('codexmateSessionTrashEnabled'));
448
+ this.configTemplateDiffConfirmEnabled = loadConfigTemplateDiffConfirmEnabledFromStorage(localStorage);
339
449
  window.addEventListener('resize', this.onWindowResize);
340
450
  window.addEventListener('keydown', this.handleGlobalKeydown);
341
451
  window.addEventListener('beforeunload', this.handleBeforeUnload);
@@ -354,35 +464,103 @@ document.addEventListener('DOMContentLoaded', () => {
354
464
  console.error('加载 Claude 配置失败:', e);
355
465
  }
356
466
  }
357
- void this.refreshClaudeSelectionFromSettings({ silent: true });
467
+ const normalizeOpenclawConfigs = (configs) => {
468
+ const source = configs && typeof configs === 'object' && !Array.isArray(configs)
469
+ ? configs
470
+ : {};
471
+ const defaultEntry = source['默认配置']
472
+ && typeof source['默认配置'] === 'object'
473
+ && !Array.isArray(source['默认配置'])
474
+ ? source['默认配置']
475
+ : { content: DEFAULT_OPENCLAW_TEMPLATE };
476
+ const normalized = {
477
+ '默认配置': {
478
+ content: typeof defaultEntry.content === 'string' ? defaultEntry.content : DEFAULT_OPENCLAW_TEMPLATE
479
+ }
480
+ };
481
+ for (const [name, value] of Object.entries(source)) {
482
+ if (name === '默认配置') continue;
483
+ normalized[name] = value;
484
+ }
485
+ return normalized;
486
+ };
358
487
  const savedOpenclawConfigs = localStorage.getItem('openclawConfigs');
359
488
  if (savedOpenclawConfigs) {
360
489
  try {
361
- this.openclawConfigs = JSON.parse(savedOpenclawConfigs);
362
- const configNames = Object.keys(this.openclawConfigs);
363
- if (configNames.length > 0) {
364
- this.currentOpenclawConfig = configNames[0];
365
- }
490
+ this.openclawConfigs = normalizeOpenclawConfigs(JSON.parse(savedOpenclawConfigs));
366
491
  } catch (e) {
367
492
  console.error('加载 OpenClaw 配置失败:', e);
493
+ this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
368
494
  }
369
495
  } else {
370
- const configNames = Object.keys(this.openclawConfigs);
371
- if (configNames.length > 0) {
372
- this.currentOpenclawConfig = configNames[0];
496
+ this.openclawConfigs = normalizeOpenclawConfigs(this.openclawConfigs);
497
+ }
498
+ const configNames = Object.keys(this.openclawConfigs);
499
+ if (configNames.length > 0) {
500
+ this.currentOpenclawConfig = this.openclawConfigs['默认配置'] ? '默认配置' : configNames[0];
501
+ }
502
+ const runInitialLoad = () => {
503
+ const triggerLoad = async () => {
504
+ this._initialLoadTimer = 0;
505
+ const startupOk = await this.loadAll();
506
+ if (!startupOk) {
507
+ return;
508
+ }
509
+ void this.refreshClaudeSelectionFromSettings({ silent: true });
510
+ void this.syncDefaultOpenclawConfigEntry({ silent: true });
511
+ };
512
+ if (typeof requestAnimationFrame === 'function') {
513
+ this._initialLoadRafId = requestAnimationFrame(() => {
514
+ this._initialLoadRafId = 0;
515
+ if (typeof setTimeout === 'function') {
516
+ this._initialLoadTimer = setTimeout(triggerLoad, 120);
517
+ return;
518
+ }
519
+ triggerLoad();
520
+ });
521
+ return;
522
+ }
523
+ if (typeof setTimeout === 'function') {
524
+ this._initialLoadTimer = setTimeout(triggerLoad, 120);
525
+ return;
373
526
  }
527
+ triggerLoad();
528
+ };
529
+ if (document.readyState === 'complete') {
530
+ runInitialLoad();
531
+ } else {
532
+ this._initialLoadOnWindowLoad = () => {
533
+ if (typeof window !== 'undefined' && typeof window.removeEventListener === 'function') {
534
+ window.removeEventListener('load', this._initialLoadOnWindowLoad);
535
+ }
536
+ this._initialLoadOnWindowLoad = null;
537
+ runInitialLoad();
538
+ };
539
+ window.addEventListener('load', this._initialLoadOnWindowLoad, { once: true });
374
540
  }
375
- this.loadAll();
376
541
  },
377
542
 
378
543
  beforeUnmount() {
379
544
  this.teardownSessionTabRender();
380
545
  this.cancelScheduledSessionTabDeferredTeardown();
381
546
  this.disconnectSessionPreviewHeaderResizeObserver();
547
+ if (this._initialLoadOnWindowLoad) {
548
+ window.removeEventListener('load', this._initialLoadOnWindowLoad);
549
+ this._initialLoadOnWindowLoad = null;
550
+ }
551
+ if (this._initialLoadRafId) {
552
+ cancelAnimationFrame(this._initialLoadRafId);
553
+ this._initialLoadRafId = 0;
554
+ }
555
+ if (this._initialLoadTimer) {
556
+ clearTimeout(this._initialLoadTimer);
557
+ this._initialLoadTimer = 0;
558
+ }
382
559
  window.removeEventListener('resize', this.onWindowResize);
383
560
  window.removeEventListener('keydown', this.handleGlobalKeydown);
384
561
  window.removeEventListener('beforeunload', this.handleBeforeUnload);
385
562
  this.applyCompactLayoutClass(false);
563
+ this.stopTaskOrchestrationPolling();
386
564
  this.sessionPreviewScrollEl = null;
387
565
  this.sessionPreviewContainerEl = null;
388
566
  this.sessionPreviewHeaderEl = null;
package/web-ui/index.html CHANGED
@@ -6,7 +6,7 @@
6
6
  <title>Codex Mate</title>
7
7
  <link rel="icon" type="image/png" href="/res/logo.png">
8
8
  <link rel="apple-touch-icon" href="/res/logo.png">
9
- <script src="/res/vue.global.js"></script>
9
+ <script src="/res/vue.global.prod.js"></script>
10
10
  <script src="/res/json5.min.js"></script>
11
11
  <link rel="stylesheet" href="/web-ui/styles.css">
12
12
  </head>
@@ -16,8 +16,12 @@
16
16
  <!-- @include ./partials/index/panel-config-claude.html -->
17
17
  <!-- @include ./partials/index/panel-config-openclaw.html -->
18
18
  <!-- @include ./partials/index/panel-sessions.html -->
19
+ <!-- @include ./partials/index/panel-usage.html -->
20
+ <!-- @include ./partials/index/panel-orchestration.html -->
21
+ <!-- @include ./partials/index/panel-docs.html -->
19
22
  <!-- @include ./partials/index/panel-settings.html -->
20
23
  <!-- @include ./partials/index/panel-market.html -->
24
+ <!-- @include ./partials/index/panel-plugins.html -->
21
25
  <!-- @include ./partials/index/layout-footer.html -->
22
26
  <!-- @include ./partials/index/modals-basic.html -->
23
27
  <!-- @include ./partials/index/modal-health-check.html -->
@@ -4,7 +4,7 @@ const LARGE_DIFF_LINE_LIMIT = 3000;
4
4
  const LARGE_DIFF_SYNC_LOOKAHEAD = 64;
5
5
 
6
6
  function measureUtf8ByteLength(input) {
7
- const text = typeof input === 'string' ? input : String(input ?? '');
7
+ const text = typeof input === 'string' ? input : String(input == null ? '' : input);
8
8
  if (typeof TextEncoder === 'function') {
9
9
  return new TextEncoder().encode(text).length;
10
10
  }
@@ -1,7 +1,67 @@
1
+ const DEFAULT_CLAUDE_MODEL_CATALOG = Object.freeze([
2
+ 'claude-opus-4-6',
3
+ 'claude-opus-4-1',
4
+ 'claude-opus-4',
5
+ 'claude-sonnet-4-6',
6
+ 'claude-sonnet-4-5',
7
+ 'claude-sonnet-4',
8
+ 'claude-haiku-4-5',
9
+ 'claude-3-7-sonnet',
10
+ 'claude-3-5-sonnet',
11
+ 'claude-3-5-haiku',
12
+ 'claude-3-opus',
13
+ 'claude-3-sonnet',
14
+ 'claude-3-haiku'
15
+ ]);
16
+
17
+ const BIGMODEL_CLAUDE_EXTRA_MODELS = Object.freeze([
18
+ 'glm-3-turbo',
19
+ 'glm-4',
20
+ 'glm-4-0520',
21
+ 'glm-4-plus',
22
+ 'glm-4-air',
23
+ 'glm-4-airx',
24
+ 'glm-4-flash',
25
+ 'glm-4-flashx',
26
+ 'glm-4v',
27
+ 'glm-4v-flash',
28
+ 'glm-4v-plus',
29
+ 'glm-4v-plus-0111',
30
+ 'glm-4.5',
31
+ 'glm-4.5-air',
32
+ 'glm-4.5v',
33
+ 'glm-4.6',
34
+ 'glm-4.6v',
35
+ 'glm-4.7',
36
+ 'glm-4.7-flash',
37
+ 'glm-4.7-flashx',
38
+ 'glm-5',
39
+ 'glm-5-turbo',
40
+ 'glm-5.1',
41
+ 'glm-5v',
42
+ 'glm-5v-turbo',
43
+ 'glm-z1',
44
+ 'glm-z1-air',
45
+ 'glm-coding'
46
+ ]);
47
+
1
48
  export function normalizeClaudeValue(value) {
2
49
  return typeof value === 'string' ? value.trim() : '';
3
50
  }
4
51
 
52
+ export function getClaudeModelCatalogForBaseUrl(baseUrl) {
53
+ const normalized = normalizeClaudeValue(baseUrl).toLowerCase().replace(/\/+$/g, '');
54
+ const models = [...DEFAULT_CLAUDE_MODEL_CATALOG];
55
+ if (normalized.includes('bigmodel.cn') && normalized.includes('/anthropic')) {
56
+ for (const model of BIGMODEL_CLAUDE_EXTRA_MODELS) {
57
+ if (!models.includes(model)) {
58
+ models.push(model);
59
+ }
60
+ }
61
+ }
62
+ return models;
63
+ }
64
+
5
65
  export function normalizeClaudeConfig(config) {
6
66
  const safe = config && typeof config === 'object' ? config : {};
7
67
  const apiKey = normalizeClaudeValue(safe.apiKey);
@@ -108,16 +108,20 @@ export function shouldForceCompactLayoutMode(options = {}) {
108
108
  const coarsePointer = !!options.coarsePointer;
109
109
  const noHover = !!options.noHover;
110
110
  const isSmallPhysicalScreen = shortEdge > 0 && shortEdge <= 920;
111
- const isNarrowViewport = viewportWidth > 0 && viewportWidth <= 960;
111
+ const isNarrowViewport = viewportWidth > 0 && viewportWidth <= 720;
112
112
  const pointerSuggestsTouchOnly = coarsePointer && noHover;
113
113
 
114
- if (isMobileUa) {
115
- return isNarrowViewport || isSmallPhysicalScreen;
116
- }
117
- if (!pointerSuggestsTouchOnly) {
118
- return false;
114
+ if (viewportWidth > 0) {
115
+ if (!isNarrowViewport) {
116
+ return false;
117
+ }
118
+ if (isMobileUa) {
119
+ return true;
120
+ }
121
+ return pointerSuggestsTouchOnly && maxTouchPoints > 0;
119
122
  }
120
- if (maxTouchPoints <= 0) {
123
+
124
+ if (!pointerSuggestsTouchOnly || maxTouchPoints <= 0) {
121
125
  return false;
122
126
  }
123
127
  return isSmallPhysicalScreen;