codexmate 0.0.37 → 0.0.39

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 (38) hide show
  1. package/cli/analytics-export-args.js +68 -0
  2. package/cli/builtin-proxy.js +626 -207
  3. package/cli/openai-bridge.js +541 -210
  4. package/cli/session-usage.js +187 -1
  5. package/cli.js +84 -2
  6. package/package.json +1 -1
  7. package/web-ui/app.js +12 -3
  8. package/web-ui/modules/app.computed.main-tabs.mjs +37 -30
  9. package/web-ui/modules/app.methods.claude-config.mjs +111 -9
  10. package/web-ui/modules/app.methods.openclaw-editing.mjs +48 -0
  11. package/web-ui/modules/app.methods.openclaw-persist.mjs +13 -7
  12. package/web-ui/modules/app.methods.providers.mjs +36 -10
  13. package/web-ui/modules/app.methods.runtime.mjs +76 -1
  14. package/web-ui/modules/app.methods.startup-claude.mjs +1 -0
  15. package/web-ui/modules/config-mode.computed.mjs +3 -3
  16. package/web-ui/modules/i18n.dict.mjs +13 -0
  17. package/web-ui/modules/i18n.mjs +65 -16
  18. package/web-ui/modules/skills.methods.mjs +1 -1
  19. package/web-ui/partials/index/layout-header.html +16 -46
  20. package/web-ui/partials/index/modal-openclaw-config.html +135 -71
  21. package/web-ui/partials/index/modal-webhook.html +8 -8
  22. package/web-ui/partials/index/modals-basic.html +56 -16
  23. package/web-ui/partials/index/panel-config-claude.html +20 -20
  24. package/web-ui/partials/index/panel-config-codex.html +5 -5
  25. package/web-ui/partials/index/panel-config-openclaw.html +70 -64
  26. package/web-ui/partials/index/panel-dashboard.html +62 -77
  27. package/web-ui/partials/index/panel-settings.html +28 -7
  28. package/web-ui/partials/index/panel-trash.html +14 -14
  29. package/web-ui/res/web-ui-render.precompiled.js +846 -539
  30. package/web-ui/styles/controls-forms.css +6 -0
  31. package/web-ui/styles/dashboard.css +46 -14
  32. package/web-ui/styles/layout-shell.css +45 -0
  33. package/web-ui/styles/navigation-panels.css +3 -3
  34. package/web-ui/styles/openclaw-structured.css +383 -33
  35. package/web-ui/styles/responsive.css +68 -0
  36. package/web-ui/styles/sessions-usage.css +105 -9
  37. package/web-ui/styles/settings-panel.css +4 -0
  38. package/web-ui/partials/index/panel-config-codex.html.bak +0 -337
@@ -1,5 +1,5 @@
1
1
  window.__CODEXMATE_WEB_UI_RENDER__ = (() => {
2
- const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList, vShow: _vShow, withDirectives: _withDirectives, vModelSelect: _vModelSelect, vModelText: _vModelText, withKeys: _withKeys, withModifiers: _withModifiers, isMemoSame: _isMemoSame, withMemo: _withMemo, normalizeStyle: _normalizeStyle, vModelCheckbox: _vModelCheckbox, vModelDynamic: _vModelDynamic } = Vue
2
+ const { toDisplayString: _toDisplayString, normalizeClass: _normalizeClass, createElementVNode: _createElementVNode, openBlock: _openBlock, createElementBlock: _createElementBlock, createCommentVNode: _createCommentVNode, createTextVNode: _createTextVNode, Fragment: _Fragment, renderList: _renderList, vShow: _vShow, withDirectives: _withDirectives, vModelSelect: _vModelSelect, vModelText: _vModelText, withKeys: _withKeys, withModifiers: _withModifiers, isMemoSame: _isMemoSame, withMemo: _withMemo, normalizeStyle: _normalizeStyle, vModelDynamic: _vModelDynamic, vModelCheckbox: _vModelCheckbox } = Vue
3
3
 
4
4
  return function render(_ctx, _cache) {
5
5
  return (_openBlock(), _createElementBlock(_Fragment, null, [
@@ -127,35 +127,15 @@ return function render(_ctx, _cache) {
127
127
  (!_ctx.sessionStandalone)
128
128
  ? (_openBlock(), _createElementBlock("div", {
129
129
  key: 1,
130
- class: "lang-fab",
131
- role: "group",
132
- "aria-label": _ctx.t('lang.label')
130
+ class: "lang-fab"
133
131
  }, [
134
- _createElementVNode("div", {
135
- class: "lang-choice",
136
- role: "group",
137
- "aria-label": _ctx.t('lang.label')
138
- }, [
139
- _createElementVNode("button", {
140
- type: "button",
141
- class: _normalizeClass(["lang-choice-btn", { active: (_ctx.lang || 'zh') === 'zh' }]),
142
- "aria-pressed": (_ctx.lang || 'zh') === 'zh',
143
- onClick: $event => (_ctx.setLang('zh'))
144
- }, "ZH", 10 /* CLASS, PROPS */, ["aria-pressed", "onClick"]),
145
- _createElementVNode("button", {
146
- type: "button",
147
- class: _normalizeClass(["lang-choice-btn", { active: (_ctx.lang || 'zh') === 'en' }]),
148
- "aria-pressed": (_ctx.lang || 'zh') === 'en',
149
- onClick: $event => (_ctx.setLang('en'))
150
- }, "EN", 10 /* CLASS, PROPS */, ["aria-pressed", "onClick"]),
151
- _createElementVNode("button", {
152
- type: "button",
153
- class: _normalizeClass(["lang-choice-btn", { active: (_ctx.lang || 'zh') === 'ja' }]),
154
- "aria-pressed": (_ctx.lang || 'zh') === 'ja',
155
- onClick: $event => (_ctx.setLang('ja'))
156
- }, "日本語", 10 /* CLASS, PROPS */, ["aria-pressed", "onClick"])
157
- ], 8 /* PROPS */, ["aria-label"])
158
- ], 8 /* PROPS */, ["aria-label"]))
132
+ _createElementVNode("button", {
133
+ type: "button",
134
+ class: "language-settings-link",
135
+ "aria-label": _ctx.t('settings.language.sideLabel', { language: _ctx.currentLanguageLabel() }),
136
+ onClick: _ctx.openLanguageSettings
137
+ }, _toDisplayString(_ctx.t('settings.language.sideLabel', { language: _ctx.currentLanguageLabel() })), 9 /* TEXT, PROPS */, ["aria-label", "onClick"])
138
+ ]))
159
139
  : _createCommentVNode("v-if", true),
160
140
  _createElementVNode("div", {
161
141
  class: _normalizeClass(['app-shell', { standalone: _ctx.sessionStandalone }])
@@ -383,7 +363,7 @@ return function render(_ctx, _cache) {
383
363
  _createElementVNode("div", { class: "side-item-title" }, _toDisplayString(_ctx.t('side.plugins.tools')), 1 /* TEXT */),
384
364
  _createElementVNode("div", { class: "side-item-meta" }, [
385
365
  _createElementVNode("span", null, _toDisplayString(_ctx.t('side.plugins.tools.meta')), 1 /* TEXT */),
386
- _createElementVNode("span", null, _toDisplayString(_ctx.promptTemplatesList.length) + " templates", 1 /* TEXT */)
366
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('side.plugins.templatesCount', { count: _ctx.promptTemplatesList.length })), 1 /* TEXT */)
387
367
  ])
388
368
  ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["aria-current", "onPointerdown", "onClick"])
389
369
  ], 8 /* PROPS */, ["aria-label"]),
@@ -414,9 +394,9 @@ return function render(_ctx, _cache) {
414
394
  onPointerdown: $event => (_ctx.onMainTabPointerDown('trash', $event)),
415
395
  onClick: $event => (_ctx.onMainTabClick('trash', $event))
416
396
  }, [
417
- _createElementVNode("div", { class: "side-item-title" }, "回收站"),
397
+ _createElementVNode("div", { class: "side-item-title" }, _toDisplayString(_ctx.t('settings.trash.title')), 1 /* TEXT */),
418
398
  _createElementVNode("div", { class: "side-item-meta" }, [
419
- _createElementVNode("span", null, "已删除会话"),
399
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('settings.trash.meta')), 1 /* TEXT */),
420
400
  (_ctx.sessionTrashCount > 0)
421
401
  ? (_openBlock(), _createElementBlock("span", {
422
402
  key: 0,
@@ -432,42 +412,20 @@ return function render(_ctx, _cache) {
432
412
  tabindex: "-1",
433
413
  "aria-hidden": "true"
434
414
  }, [
435
- _createElementVNode("div", { class: "side-item-title" }, "New Tab"),
415
+ _createElementVNode("div", { class: "side-item-title" }, _toDisplayString(_ctx.t('side.newTab')), 1 /* TEXT */),
436
416
  _createElementVNode("div", { class: "side-item-meta" }, [
437
417
  _createElementVNode("span", null, " ")
438
418
  ])
439
419
  ])
440
420
  ]),
441
- _createElementVNode("div", {
442
- class: "side-rail-lang",
443
- role: "group",
444
- "aria-label": _ctx.t('lang.label')
445
- }, [
446
- _createElementVNode("div", {
447
- class: "lang-choice",
448
- role: "group",
449
- "aria-label": _ctx.t('lang.label')
450
- }, [
451
- _createElementVNode("button", {
452
- type: "button",
453
- class: _normalizeClass(["lang-choice-btn", { active: (_ctx.lang || 'zh') === 'zh' }]),
454
- "aria-pressed": (_ctx.lang || 'zh') === 'zh',
455
- onClick: $event => (_ctx.setLang('zh'))
456
- }, "ZH", 10 /* CLASS, PROPS */, ["aria-pressed", "onClick"]),
457
- _createElementVNode("button", {
458
- type: "button",
459
- class: _normalizeClass(["lang-choice-btn", { active: (_ctx.lang || 'zh') === 'en' }]),
460
- "aria-pressed": (_ctx.lang || 'zh') === 'en',
461
- onClick: $event => (_ctx.setLang('en'))
462
- }, "EN", 10 /* CLASS, PROPS */, ["aria-pressed", "onClick"]),
463
- _createElementVNode("button", {
464
- type: "button",
465
- class: _normalizeClass(["lang-choice-btn", { active: (_ctx.lang || 'zh') === 'ja' }]),
466
- "aria-pressed": (_ctx.lang || 'zh') === 'ja',
467
- onClick: $event => (_ctx.setLang('ja'))
468
- }, "日本語", 10 /* CLASS, PROPS */, ["aria-pressed", "onClick"])
469
- ], 8 /* PROPS */, ["aria-label"])
470
- ], 8 /* PROPS */, ["aria-label"])
421
+ _createElementVNode("div", { class: "side-rail-lang" }, [
422
+ _createElementVNode("button", {
423
+ type: "button",
424
+ class: "language-settings-link",
425
+ "aria-label": _ctx.t('settings.language.sideLabel', { language: _ctx.currentLanguageLabel() }),
426
+ onClick: _ctx.openLanguageSettings
427
+ }, _toDisplayString(_ctx.t('settings.language.sideLabel', { language: _ctx.currentLanguageLabel() })), 9 /* TEXT, PROPS */, ["aria-label", "onClick"])
428
+ ])
471
429
  ]))
472
430
  : _createCommentVNode("v-if", true),
473
431
  _createElementVNode("main", { class: "main-panel" }, [
@@ -694,6 +652,95 @@ return function render(_ctx, _cache) {
694
652
  }, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('dashboard.doctor.checking') : _ctx.t('dashboard.doctor.runChecks')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
695
653
  ])
696
654
  ]),
655
+ _createElementVNode("div", { class: "doctor-status-row" }, [
656
+ _createElementVNode("div", {
657
+ class: _normalizeClass(["doctor-status-chip", _ctx.inspectorHealthTone])
658
+ }, [
659
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('dashboard.status.health')), 1 /* TEXT */),
660
+ _createElementVNode("strong", null, _toDisplayString(_ctx.inspectorHealthStatus), 1 /* TEXT */)
661
+ ], 2 /* CLASS */),
662
+ _createElementVNode("div", { class: "doctor-status-chip" }, [
663
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('dashboard.status.busy')), 1 /* TEXT */),
664
+ _createElementVNode("strong", null, _toDisplayString(_ctx.inspectorBusyStatus), 1 /* TEXT */)
665
+ ]),
666
+ _createElementVNode("div", { class: "doctor-status-chip" }, [
667
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('dashboard.status.models')), 1 /* TEXT */),
668
+ _createElementVNode("strong", null, _toDisplayString(_ctx.inspectorModelLoadStatus), 1 /* TEXT */)
669
+ ])
670
+ ]),
671
+ (_ctx.healthCheckResult)
672
+ ? (_openBlock(), _createElementBlock("div", {
673
+ key: 0,
674
+ class: _normalizeClass(["doctor-health-result", _ctx.healthCheckResult.ok ? 'ok' : 'error'])
675
+ }, [
676
+ _createElementVNode("div", { class: "doctor-health-title" }, [
677
+ _createTextVNode(_toDisplayString(_ctx.healthCheckResult.ok ? _ctx.t('dashboard.health.ok') : _ctx.t('dashboard.health.fail')) + " ", 1 /* TEXT */),
678
+ (_ctx.healthCheckResult.issues && _ctx.healthCheckResult.issues.length)
679
+ ? (_openBlock(), _createElementBlock("span", { key: 0 }, "(" + _toDisplayString(_ctx.t('dashboard.health.issues', { count: _ctx.healthCheckResult.issues.length })) + ")", 1 /* TEXT */))
680
+ : _createCommentVNode("v-if", true)
681
+ ])
682
+ ], 2 /* CLASS */))
683
+ : _createCommentVNode("v-if", true),
684
+ (_ctx.healthCheckResult && _ctx.healthCheckResult.report)
685
+ ? (_openBlock(), _createElementBlock("div", {
686
+ key: 1,
687
+ class: "doctor-action-list"
688
+ }, [
689
+ (_ctx.healthCheckResult.report.issues && _ctx.healthCheckResult.report.issues.length)
690
+ ? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.healthCheckResult.report.issues, (issue) => {
691
+ return (_openBlock(), _createElementBlock("div", {
692
+ key: issue.id,
693
+ class: "doctor-action-card"
694
+ }, [
695
+ _createElementVNode("div", { class: "doctor-action-head" }, [
696
+ _createElementVNode("div", { class: "doctor-action-title" }, _toDisplayString(issue.problem || (issue.problemKey ? _ctx.t(issue.problemKey, issue.problemParams) : '')), 1 /* TEXT */),
697
+ _createElementVNode("div", {
698
+ class: _normalizeClass(['doctor-action-severity', issue.severity])
699
+ }, _toDisplayString(issue.severityLabel || issue.severity), 3 /* TEXT, CLASS */)
700
+ ]),
701
+ _createElementVNode("div", { class: "doctor-action-impact" }, _toDisplayString(issue.impact || (issue.impactKey ? _ctx.t(issue.impactKey, issue.impactParams) : '')), 1 /* TEXT */),
702
+ (issue.actions && issue.actions.some(action => action && action.type === 'navigate' && action.target))
703
+ ? (_openBlock(), _createElementBlock("div", {
704
+ key: 0,
705
+ class: "doctor-action-buttons"
706
+ }, [
707
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(issue.actions, (action, index) => {
708
+ return (_openBlock(), _createElementBlock(_Fragment, {
709
+ key: issue.id + '-action-' + index
710
+ }, [
711
+ (action.type === 'navigate' && action.target)
712
+ ? (_openBlock(), _createElementBlock("button", {
713
+ key: 0,
714
+ type: "button",
715
+ class: "btn-tool btn-tool-compact",
716
+ onClick: $event => (action.target ? _ctx.switchMainTab(action.target) : null)
717
+ }, _toDisplayString(action.label || (action.labelKey ? _ctx.t(action.labelKey, action.labelParams) : _ctx.t('dashboard.doctor.open'))), 9 /* TEXT, PROPS */, ["onClick"]))
718
+ : _createCommentVNode("v-if", true)
719
+ ], 64 /* STABLE_FRAGMENT */))
720
+ }), 128 /* KEYED_FRAGMENT */))
721
+ ]))
722
+ : _createCommentVNode("v-if", true)
723
+ ]))
724
+ }), 128 /* KEYED_FRAGMENT */))
725
+ : _createCommentVNode("v-if", true),
726
+ _createElementVNode("div", { class: "doctor-action-footer" }, [
727
+ _createElementVNode("button", {
728
+ type: "button",
729
+ class: "btn-tool btn-tool-compact",
730
+ onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
731
+ ? _ctx.downloadTextFile('codexmate-doctor.json', JSON.stringify(_ctx.healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
732
+ : null}
733
+ }, _toDisplayString(_ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]),
734
+ _createElementVNode("button", {
735
+ type: "button",
736
+ class: "btn-tool btn-tool-compact",
737
+ onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
738
+ ? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
739
+ : null}
740
+ }, _toDisplayString(_ctx.t('dashboard.doctor.export.md')), 9 /* TEXT, PROPS */, ["onClick"])
741
+ ])
742
+ ]))
743
+ : _createCommentVNode("v-if", true),
697
744
  _createElementVNode("div", { class: "doctor-grid" }, [
698
745
  _createElementVNode("button", {
699
746
  type: "button",
@@ -835,113 +882,7 @@ return function render(_ctx, _cache) {
835
882
  ]))
836
883
  : _createCommentVNode("v-if", true)
837
884
  ], 8 /* PROPS */, ["onClick", "disabled"])
838
- ]),
839
- _createElementVNode("div", { class: "doctor-status-row" }, [
840
- _createElementVNode("div", {
841
- class: _normalizeClass(["doctor-status-chip", _ctx.inspectorHealthTone])
842
- }, [
843
- _createElementVNode("span", null, _toDisplayString(_ctx.t('dashboard.status.health')), 1 /* TEXT */),
844
- _createElementVNode("strong", null, _toDisplayString(_ctx.inspectorHealthStatus), 1 /* TEXT */)
845
- ], 2 /* CLASS */),
846
- _createElementVNode("div", { class: "doctor-status-chip" }, [
847
- _createElementVNode("span", null, _toDisplayString(_ctx.t('dashboard.status.busy')), 1 /* TEXT */),
848
- _createElementVNode("strong", null, _toDisplayString(_ctx.inspectorBusyStatus), 1 /* TEXT */)
849
- ]),
850
- _createElementVNode("div", { class: "doctor-status-chip" }, [
851
- _createElementVNode("span", null, _toDisplayString(_ctx.t('dashboard.status.models')), 1 /* TEXT */),
852
- _createElementVNode("strong", null, _toDisplayString(_ctx.inspectorModelLoadStatus), 1 /* TEXT */)
853
- ])
854
- ]),
855
- (_ctx.healthCheckResult)
856
- ? (_openBlock(), _createElementBlock("div", {
857
- key: 0,
858
- class: _normalizeClass(["doctor-health-result", _ctx.healthCheckResult.ok ? 'ok' : 'error'])
859
- }, [
860
- _createElementVNode("div", { class: "doctor-health-title" }, [
861
- _createTextVNode(_toDisplayString(_ctx.healthCheckResult.ok ? _ctx.t('dashboard.health.ok') : _ctx.t('dashboard.health.fail')) + " ", 1 /* TEXT */),
862
- (_ctx.healthCheckResult.issues && _ctx.healthCheckResult.issues.length)
863
- ? (_openBlock(), _createElementBlock("span", { key: 0 }, "(" + _toDisplayString(_ctx.t('dashboard.health.issues', { count: _ctx.healthCheckResult.issues.length })) + ")", 1 /* TEXT */))
864
- : _createCommentVNode("v-if", true)
865
- ])
866
- ], 2 /* CLASS */))
867
- : _createCommentVNode("v-if", true),
868
- (_ctx.healthCheckResult && _ctx.healthCheckResult.report && _ctx.healthCheckResult.report.issues && _ctx.healthCheckResult.report.issues.length)
869
- ? (_openBlock(), _createElementBlock("div", {
870
- key: 1,
871
- class: "doctor-action-list"
872
- }, [
873
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.healthCheckResult.report.issues, (issue) => {
874
- return (_openBlock(), _createElementBlock("div", {
875
- key: issue.id,
876
- class: "doctor-action-card"
877
- }, [
878
- _createElementVNode("div", { class: "doctor-action-head" }, [
879
- _createElementVNode("div", { class: "doctor-action-title" }, _toDisplayString(issue.problem || (issue.problemKey ? _ctx.t(issue.problemKey, issue.problemParams) : '')), 1 /* TEXT */),
880
- _createElementVNode("div", {
881
- class: _normalizeClass(['doctor-action-severity', issue.severity])
882
- }, _toDisplayString(issue.severityLabel || issue.severity), 3 /* TEXT, CLASS */)
883
- ]),
884
- _createElementVNode("div", { class: "doctor-action-impact" }, _toDisplayString(issue.impact || (issue.impactKey ? _ctx.t(issue.impactKey, issue.impactParams) : '')), 1 /* TEXT */),
885
- (issue.actions && issue.actions.length)
886
- ? (_openBlock(), _createElementBlock("div", {
887
- key: 0,
888
- class: "doctor-action-buttons"
889
- }, [
890
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(issue.actions, (action, index) => {
891
- return (_openBlock(), _createElementBlock(_Fragment, {
892
- key: issue.id + '-action-' + index
893
- }, [
894
- (action.type === 'navigate')
895
- ? (_openBlock(), _createElementBlock("button", {
896
- key: 0,
897
- type: "button",
898
- class: "btn-tool btn-tool-compact",
899
- onClick: $event => (_ctx.switchMainTab(action.target))
900
- }, _toDisplayString(action.label || (action.labelKey ? _ctx.t(action.labelKey, action.labelParams) : _ctx.t('dashboard.doctor.open'))), 9 /* TEXT, PROPS */, ["onClick"]))
901
- : (action.type === 'run-check')
902
- ? (_openBlock(), _createElementBlock("button", {
903
- key: 1,
904
- type: "button",
905
- class: "btn-tool btn-tool-compact",
906
- onClick: $event => (_ctx.runHealthCheck({ doctor: true, forceRefresh: true })),
907
- disabled: _ctx.healthCheckLoading
908
- }, _toDisplayString(_ctx.t('dashboard.doctor.runChecks')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]))
909
- : (action.type === 'export')
910
- ? (_openBlock(), _createElementBlock("button", {
911
- key: 2,
912
- type: "button",
913
- class: "btn-tool btn-tool-compact",
914
- onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
915
- ? (action.format === 'md'
916
- ? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
917
- : _ctx.downloadTextFile('codexmate-doctor.json', JSON.stringify(_ctx.healthCheckResult.report, null, 2), 'application/json;charset=utf-8'))
918
- : null}
919
- }, _toDisplayString(action.format === 'md' ? _ctx.t('dashboard.doctor.export.md') : _ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]))
920
- : _createCommentVNode("v-if", true)
921
- ], 64 /* STABLE_FRAGMENT */))
922
- }), 128 /* KEYED_FRAGMENT */))
923
- ]))
924
- : _createCommentVNode("v-if", true)
925
- ]))
926
- }), 128 /* KEYED_FRAGMENT */)),
927
- _createElementVNode("div", { class: "doctor-action-footer" }, [
928
- _createElementVNode("button", {
929
- type: "button",
930
- class: "btn-tool btn-tool-compact",
931
- onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
932
- ? _ctx.downloadTextFile('codexmate-doctor.json', JSON.stringify(_ctx.healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
933
- : null}
934
- }, _toDisplayString(_ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]),
935
- _createElementVNode("button", {
936
- type: "button",
937
- class: "btn-tool btn-tool-compact",
938
- onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
939
- ? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
940
- : null}
941
- }, _toDisplayString(_ctx.t('dashboard.doctor.export.md')), 9 /* TEXT, PROPS */, ["onClick"])
942
- ])
943
- ]))
944
- : _createCommentVNode("v-if", true)
885
+ ])
945
886
  ])
946
887
  ], 512 /* NEED_PATCH */), [
947
888
  [_vShow, _ctx.mainTab === 'dashboard']
@@ -1010,7 +951,7 @@ return function render(_ctx, _cache) {
1010
951
  ? (_openBlock(), _createElementBlock("button", {
1011
952
  key: 0,
1012
953
  class: "btn-add",
1013
- onClick: $event => (_ctx.showAddModal = true)
954
+ onClick: $event => {_ctx.showAddProviderKey = false; _ctx.showAddModal = true}
1014
955
  }, [
1015
956
  (_openBlock(), _createElementBlock("svg", {
1016
957
  class: "icon",
@@ -1041,7 +982,7 @@ return function render(_ctx, _cache) {
1041
982
  key: tpl.name,
1042
983
  type: "button",
1043
984
  class: "btn-mini",
1044
- onClick: $event => {_ctx.newProvider.name = tpl.name; _ctx.newProvider.url = tpl.url; _ctx.newProvider._suggestedModel = tpl.model || ''; _ctx.newProvider.useTransform = !!tpl.useTransform; _ctx.showAddModal = true}
985
+ onClick: $event => {_ctx.newProvider.name = tpl.name; _ctx.newProvider.url = tpl.url; _ctx.newProvider.model = tpl.model || ''; _ctx.newProvider.useTransform = !!tpl.useTransform; _ctx.showAddProviderKey = false; _ctx.showAddModal = true}
1045
986
  }, _toDisplayString(tpl.label), 9 /* TEXT, PROPS */, ["onClick"]))
1046
987
  }), 128 /* KEYED_FRAGMENT */))
1047
988
  ])
@@ -1306,8 +1247,8 @@ return function render(_ctx, _cache) {
1306
1247
  ? (_openBlock(), _createElementBlock("span", {
1307
1248
  key: 0,
1308
1249
  class: "card-icon-dot",
1309
- title: "通过内建转换适配"
1310
- }))
1250
+ title: _ctx.t('config.transformProvider.title')
1251
+ }, null, 8 /* PROPS */, ["title"]))
1311
1252
  : _createCommentVNode("v-if", true)
1312
1253
  ]),
1313
1254
  _createElementVNode("div", { class: "card-content" }, [
@@ -1343,7 +1284,7 @@ return function render(_ctx, _cache) {
1343
1284
  _createElementVNode("path", { d: "M6 8v4h6v4" }),
1344
1285
  _createElementVNode("path", { d: "M18 8v4h-6v4" })
1345
1286
  ])),
1346
- _createElementVNode("span", { class: "bridge-pool-summary-text" }, "已启用 " + _toDisplayString(_ctx.localBridgeCandidateProviders().filter(cp => !_ctx.isLocalBridgeExcluded(cp.name)).length) + " / " + _toDisplayString(_ctx.localBridgeCandidateProviders().length), 1 /* TEXT */)
1287
+ _createElementVNode("span", { class: "bridge-pool-summary-text" }, _toDisplayString(_ctx.t('config.localBridge.enabledCount', { enabled: _ctx.localBridgeCandidateProviders().filter(cp => !_ctx.isLocalBridgeExcluded(cp.name)).length, total: _ctx.localBridgeCandidateProviders().length })), 1 /* TEXT */)
1347
1288
  ]))
1348
1289
  : _createCommentVNode("v-if", true),
1349
1290
  _createElementVNode("div", { class: "card-title" }, [
@@ -1388,8 +1329,8 @@ return function render(_ctx, _cache) {
1388
1329
  key: 0,
1389
1330
  class: "card-action-btn bridge-pool-trigger",
1390
1331
  onClick: $event => (_ctx.showCodexBridgePoolModal = true),
1391
- "aria-label": '轮询池设置',
1392
- title: '轮询池设置'
1332
+ "aria-label": _ctx.t('config.localBridge.poolSettings'),
1333
+ title: _ctx.t('config.localBridge.poolSettings')
1393
1334
  }, [
1394
1335
  (_openBlock(), _createElementBlock("svg", {
1395
1336
  viewBox: "0 0 24 24",
@@ -1415,7 +1356,7 @@ return function render(_ctx, _cache) {
1415
1356
  _createElementVNode("path", { d: "M6 8v4h6v4" }),
1416
1357
  _createElementVNode("path", { d: "M18 8v4h-6v4" })
1417
1358
  ]))
1418
- ], 8 /* PROPS */, ["onClick"]))
1359
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1419
1360
  : _createCommentVNode("v-if", true),
1420
1361
  _createElementVNode("button", {
1421
1362
  class: _normalizeClass(["card-action-btn", { loading: _ctx.speedLoading[provider.name] }]),
@@ -1616,102 +1557,102 @@ return function render(_ctx, _cache) {
1616
1557
  _createElementVNode("button", {
1617
1558
  type: "button",
1618
1559
  class: "btn-mini",
1619
- onClick: $event => {_ctx.newClaudeConfig.name = 'Claude Official'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.anthropic.com'; _ctx.newClaudeConfig.model = 'claude-sonnet-4'; _ctx.showClaudeConfigModal = true}
1560
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Claude Official'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.anthropic.com'; _ctx.newClaudeConfig.model = 'claude-sonnet-4'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1620
1561
  }, "Claude Official", 8 /* PROPS */, ["onClick"]),
1621
1562
  _createElementVNode("button", {
1622
1563
  type: "button",
1623
1564
  class: "btn-mini",
1624
- onClick: $event => {_ctx.newClaudeConfig.name = 'DeepSeek'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.deepseek.com/anthropic'; _ctx.newClaudeConfig.model = 'DeepSeek-V3.2'; _ctx.showClaudeConfigModal = true}
1565
+ onClick: $event => {_ctx.newClaudeConfig.name = 'DeepSeek'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.deepseek.com/anthropic'; _ctx.newClaudeConfig.model = 'DeepSeek-V3.2'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1625
1566
  }, "DeepSeek", 8 /* PROPS */, ["onClick"]),
1626
1567
  _createElementVNode("button", {
1627
1568
  type: "button",
1628
1569
  class: "btn-mini",
1629
- onClick: $event => {_ctx.newClaudeConfig.name = 'Zhipu GLM'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://open.bigmodel.cn/api/anthropic'; _ctx.newClaudeConfig.model = 'glm-5'; _ctx.showClaudeConfigModal = true}
1570
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Zhipu GLM'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://open.bigmodel.cn/api/anthropic'; _ctx.newClaudeConfig.model = 'glm-5'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1630
1571
  }, "Zhipu GLM", 8 /* PROPS */, ["onClick"]),
1631
1572
  _createElementVNode("button", {
1632
1573
  type: "button",
1633
1574
  class: "btn-mini",
1634
- onClick: $event => {_ctx.newClaudeConfig.name = 'Z.ai GLM'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.z.ai/api/anthropic'; _ctx.newClaudeConfig.model = 'glm-5'; _ctx.showClaudeConfigModal = true}
1575
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Z.ai GLM'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.z.ai/api/anthropic'; _ctx.newClaudeConfig.model = 'glm-5'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1635
1576
  }, "Z.ai GLM", 8 /* PROPS */, ["onClick"]),
1636
1577
  _createElementVNode("button", {
1637
1578
  type: "button",
1638
1579
  class: "btn-mini",
1639
- onClick: $event => {_ctx.newClaudeConfig.name = 'Qwen Coder'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://coding.dashscope.aliyuncs.com/apps/anthropic'; _ctx.newClaudeConfig.model = 'qwen3-coder'; _ctx.showClaudeConfigModal = true}
1580
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Qwen Coder'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://coding.dashscope.aliyuncs.com/apps/anthropic'; _ctx.newClaudeConfig.model = 'qwen3-coder'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1640
1581
  }, "Qwen Coder", 8 /* PROPS */, ["onClick"]),
1641
1582
  _createElementVNode("button", {
1642
1583
  type: "button",
1643
1584
  class: "btn-mini",
1644
- onClick: $event => {_ctx.newClaudeConfig.name = 'Kimi k2'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.moonshot.cn/anthropic'; _ctx.newClaudeConfig.model = 'kimi-k2.5'; _ctx.showClaudeConfigModal = true}
1585
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Kimi k2'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.moonshot.cn/anthropic'; _ctx.newClaudeConfig.model = 'kimi-k2.5'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1645
1586
  }, "Kimi k2", 8 /* PROPS */, ["onClick"]),
1646
1587
  _createElementVNode("button", {
1647
1588
  type: "button",
1648
1589
  class: "btn-mini",
1649
- onClick: $event => {_ctx.newClaudeConfig.name = 'Kimi For Coding'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.kimi.com/coding/'; _ctx.newClaudeConfig.model = 'kimi-k2.5'; _ctx.showClaudeConfigModal = true}
1590
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Kimi For Coding'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.kimi.com/coding/'; _ctx.newClaudeConfig.model = 'kimi-k2.5'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1650
1591
  }, "Kimi For Coding", 8 /* PROPS */, ["onClick"]),
1651
1592
  _createElementVNode("button", {
1652
1593
  type: "button",
1653
1594
  class: "btn-mini",
1654
- onClick: $event => {_ctx.newClaudeConfig.name = 'KAT-Coder'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://vanchin.streamlake.ai/api/gateway/v1/endpoints/${ENDPOINT_ID}/claude-code-proxy'; _ctx.newClaudeConfig.model = 'KAT-Coder-Pro V1'; _ctx.showClaudeConfigModal = true}
1595
+ onClick: $event => {_ctx.newClaudeConfig.name = 'KAT-Coder'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://vanchin.streamlake.ai/api/gateway/v1/endpoints/${ENDPOINT_ID}/claude-code-proxy'; _ctx.newClaudeConfig.model = 'KAT-Coder-Pro V1'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1655
1596
  }, "KAT-Coder", 8 /* PROPS */, ["onClick"]),
1656
1597
  _createElementVNode("button", {
1657
1598
  type: "button",
1658
1599
  class: "btn-mini",
1659
- onClick: $event => {_ctx.newClaudeConfig.name = 'Longcat'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.longcat.chat/anthropic'; _ctx.newClaudeConfig.model = 'LongCat-Flash-Chat'; _ctx.showClaudeConfigModal = true}
1600
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Longcat'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.longcat.chat/anthropic'; _ctx.newClaudeConfig.model = 'LongCat-Flash-Chat'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1660
1601
  }, "Longcat", 8 /* PROPS */, ["onClick"]),
1661
1602
  _createElementVNode("button", {
1662
1603
  type: "button",
1663
1604
  class: "btn-mini",
1664
- onClick: $event => {_ctx.newClaudeConfig.name = 'MiniMax'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.minimaxi.com/anthropic'; _ctx.newClaudeConfig.model = 'MiniMax-M2.7'; _ctx.showClaudeConfigModal = true}
1605
+ onClick: $event => {_ctx.newClaudeConfig.name = 'MiniMax'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.minimaxi.com/anthropic'; _ctx.newClaudeConfig.model = 'MiniMax-M2.7'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1665
1606
  }, "MiniMax", 8 /* PROPS */, ["onClick"]),
1666
1607
  _createElementVNode("button", {
1667
1608
  type: "button",
1668
1609
  class: "btn-mini",
1669
- onClick: $event => {_ctx.newClaudeConfig.name = 'MiniMax en'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.minimax.io/anthropic'; _ctx.newClaudeConfig.model = 'MiniMax-M2.7'; _ctx.showClaudeConfigModal = true}
1610
+ onClick: $event => {_ctx.newClaudeConfig.name = 'MiniMax en'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.minimax.io/anthropic'; _ctx.newClaudeConfig.model = 'MiniMax-M2.7'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1670
1611
  }, "MiniMax en", 8 /* PROPS */, ["onClick"]),
1671
1612
  _createElementVNode("button", {
1672
1613
  type: "button",
1673
1614
  class: "btn-mini",
1674
- onClick: $event => {_ctx.newClaudeConfig.name = 'DouBaoSeed'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://ark.cn-beijing.volces.com/api/coding'; _ctx.newClaudeConfig.model = 'doubao-seed-2-0-code-preview-latest'; _ctx.showClaudeConfigModal = true}
1615
+ onClick: $event => {_ctx.newClaudeConfig.name = 'DouBaoSeed'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://ark.cn-beijing.volces.com/api/coding'; _ctx.newClaudeConfig.model = 'doubao-seed-2-0-code-preview-latest'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1675
1616
  }, "DouBaoSeed", 8 /* PROPS */, ["onClick"]),
1676
1617
  _createElementVNode("button", {
1677
1618
  type: "button",
1678
1619
  class: "btn-mini",
1679
- onClick: $event => {_ctx.newClaudeConfig.name = 'BaiLing'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.tbox.cn/api/anthropic'; _ctx.newClaudeConfig.model = 'Ling-2.5-1T'; _ctx.showClaudeConfigModal = true}
1620
+ onClick: $event => {_ctx.newClaudeConfig.name = 'BaiLing'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.tbox.cn/api/anthropic'; _ctx.newClaudeConfig.model = 'Ling-2.5-1T'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1680
1621
  }, "BaiLing", 8 /* PROPS */, ["onClick"]),
1681
1622
  _createElementVNode("button", {
1682
1623
  type: "button",
1683
1624
  class: "btn-mini",
1684
- onClick: $event => {_ctx.newClaudeConfig.name = 'ModelScope'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api-inference.modelscope.cn'; _ctx.newClaudeConfig.model = 'ZhipuAI/GLM-5'; _ctx.showClaudeConfigModal = true}
1625
+ onClick: $event => {_ctx.newClaudeConfig.name = 'ModelScope'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api-inference.modelscope.cn'; _ctx.newClaudeConfig.model = 'ZhipuAI/GLM-5'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1685
1626
  }, "ModelScope", 8 /* PROPS */, ["onClick"]),
1686
1627
  _createElementVNode("button", {
1687
1628
  type: "button",
1688
1629
  class: "btn-mini",
1689
- onClick: $event => {_ctx.newClaudeConfig.name = 'AiHubMix'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://aihubmix.com'; _ctx.newClaudeConfig.model = 'glm-4.7'; _ctx.showClaudeConfigModal = true}
1630
+ onClick: $event => {_ctx.newClaudeConfig.name = 'AiHubMix'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://aihubmix.com'; _ctx.newClaudeConfig.model = 'glm-4.7'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1690
1631
  }, "AiHubMix", 8 /* PROPS */, ["onClick"]),
1691
1632
  _createElementVNode("button", {
1692
1633
  type: "button",
1693
1634
  class: "btn-mini",
1694
- onClick: $event => {_ctx.newClaudeConfig.name = 'DMXAPI'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://www.dmxapi.cn'; _ctx.newClaudeConfig.model = 'glm-4.7'; _ctx.showClaudeConfigModal = true}
1635
+ onClick: $event => {_ctx.newClaudeConfig.name = 'DMXAPI'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://www.dmxapi.cn'; _ctx.newClaudeConfig.model = 'glm-4.7'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1695
1636
  }, "DMXAPI", 8 /* PROPS */, ["onClick"]),
1696
1637
  _createElementVNode("button", {
1697
1638
  type: "button",
1698
1639
  class: "btn-mini",
1699
- onClick: $event => {_ctx.newClaudeConfig.name = 'PackyCode'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://www.packyapi.com'; _ctx.newClaudeConfig.model = 'glm-4.7'; _ctx.showClaudeConfigModal = true}
1640
+ onClick: $event => {_ctx.newClaudeConfig.name = 'PackyCode'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://www.packyapi.com'; _ctx.newClaudeConfig.model = 'glm-4.7'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1700
1641
  }, "PackyCode", 8 /* PROPS */, ["onClick"]),
1701
1642
  _createElementVNode("button", {
1702
1643
  type: "button",
1703
1644
  class: "btn-mini",
1704
- onClick: $event => {_ctx.newClaudeConfig.name = 'AnyRouter'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://anyrouter.top'; _ctx.newClaudeConfig.model = 'claude-opus-4-7[1m]'; _ctx.showClaudeConfigModal = true}
1645
+ onClick: $event => {_ctx.newClaudeConfig.name = 'AnyRouter'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://anyrouter.top'; _ctx.newClaudeConfig.model = 'claude-opus-4-7[1m]'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1705
1646
  }, "AnyRouter", 8 /* PROPS */, ["onClick"]),
1706
1647
  _createElementVNode("button", {
1707
1648
  type: "button",
1708
1649
  class: "btn-mini",
1709
- onClick: $event => {_ctx.newClaudeConfig.name = 'Xiaomi MiMo'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.xiaomimimo.com/anthropic'; _ctx.newClaudeConfig.model = 'mimo-v2.5-pro'; _ctx.showClaudeConfigModal = true}
1650
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Xiaomi MiMo'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://api.xiaomimimo.com/anthropic'; _ctx.newClaudeConfig.model = 'mimo-v2.5-pro'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1710
1651
  }, "Xiaomi MiMo", 8 /* PROPS */, ["onClick"]),
1711
1652
  _createElementVNode("button", {
1712
1653
  type: "button",
1713
1654
  class: "btn-mini",
1714
- onClick: $event => {_ctx.newClaudeConfig.name = 'Xiaomi Token Plan'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://token-plan-cn.xiaomimimo.com/anthropic'; _ctx.newClaudeConfig.model = 'mimo-v2.5-pro'; _ctx.showClaudeConfigModal = true}
1655
+ onClick: $event => {_ctx.newClaudeConfig.name = 'Xiaomi Token Plan'; _ctx.newClaudeConfig.apiKey = ''; _ctx.newClaudeConfig.baseUrl = 'https://token-plan-cn.xiaomimimo.com/anthropic'; _ctx.newClaudeConfig.model = 'mimo-v2.5-pro'; _ctx.showAddClaudeConfigKey = false; _ctx.showClaudeConfigModal = true}
1715
1656
  }, "Xiaomi Token Plan", 8 /* PROPS */, ["onClick"])
1716
1657
  ])
1717
1658
  ]),
@@ -2028,117 +1969,141 @@ return function render(_ctx, _cache) {
2028
1969
  }, _toDisplayString(_ctx.t('tab.config.openclaw')), 11 /* TEXT, CLASS, PROPS */, ["onClick"])
2029
1970
  ]))
2030
1971
  : _createCommentVNode("v-if", true),
2031
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('openclaw.applyHint')), 1 /* TEXT */),
2032
- _createElementVNode("div", { class: "selector-section" }, [
2033
- _createElementVNode("div", { class: "selector-header" }, [
2034
- _createElementVNode("span", { class: "selector-title" }, "AGENTS.md")
2035
- ]),
2036
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('openclaw.agents.hint')), 1 /* TEXT */),
2037
- _createElementVNode("button", {
2038
- class: "btn-tool",
2039
- onClick: _ctx.openOpenclawAgentsEditor,
2040
- disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
2041
- }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('openclaw.agents.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
2042
- ]),
2043
- _createElementVNode("div", { class: "selector-section" }, [
2044
- _createElementVNode("div", { class: "selector-header" }, [
2045
- _createElementVNode("label", {
2046
- class: "selector-title",
2047
- for: "openclaw-workspace-file"
2048
- }, _toDisplayString(_ctx.t('openclaw.workspaceFile')), 1 /* TEXT */)
2049
- ]),
2050
- _withDirectives(_createElementVNode("input", {
2051
- id: "openclaw-workspace-file",
2052
- class: "form-input",
2053
- "onUpdate:modelValue": $event => ((_ctx.openclawWorkspaceFileName) = $event),
2054
- placeholder: _ctx.t('openclaw.workspace.placeholder')
2055
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
2056
- [_vModelText, _ctx.openclawWorkspaceFileName]
2057
- ]),
2058
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('openclaw.workspace.hint')), 1 /* TEXT */),
2059
- _createElementVNode("button", {
2060
- class: "btn-tool",
2061
- onClick: _ctx.openOpenclawWorkspaceEditor,
2062
- disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
2063
- }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('openclaw.workspace.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
2064
- ]),
2065
- _createElementVNode("div", { class: "card-list" }, [
2066
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.openclawConfigs, (config, name) => {
2067
- return (_openBlock(), _createElementBlock("div", {
2068
- key: name,
2069
- class: _normalizeClass(['card', { active: _ctx.currentOpenclawConfig === name }]),
2070
- onClick: $event => (_ctx.applyOpenclawConfig(name)),
2071
- onKeydown: [
2072
- _withKeys(_withModifiers($event => (_ctx.applyOpenclawConfig(name)), ["self","prevent"]), ["enter"]),
2073
- _withKeys(_withModifiers($event => (_ctx.applyOpenclawConfig(name)), ["self","prevent"]), ["space"])
2074
- ],
2075
- tabindex: "0",
2076
- role: "button",
2077
- "aria-current": _ctx.currentOpenclawConfig === name ? 'true' : null
2078
- }, [
2079
- _createElementVNode("div", { class: "card-leading" }, [
2080
- _createElementVNode("div", { class: "card-icon" }, _toDisplayString(name.charAt(0).toUpperCase()), 1 /* TEXT */),
2081
- _createElementVNode("div", { class: "card-content" }, [
2082
- _createElementVNode("div", { class: "card-title" }, _toDisplayString(name), 1 /* TEXT */),
2083
- _createElementVNode("div", { class: "card-subtitle" }, _toDisplayString(_ctx.openclawSubtitle(config)), 1 /* TEXT */)
2084
- ])
2085
- ]),
2086
- _createElementVNode("div", { class: "card-trailing" }, [
2087
- _createElementVNode("span", {
2088
- class: _normalizeClass(['pill', _ctx.openclawHasContent(config) ? 'configured' : 'empty'])
2089
- }, _toDisplayString(_ctx.openclawHasContent(config) ? _ctx.t('openclaw.configured') : _ctx.t('openclaw.notConfigured')), 3 /* TEXT, CLASS */),
2090
- _createElementVNode("div", {
2091
- class: "card-actions",
2092
- onClick: _withModifiers(() => {}, ["stop"])
1972
+ _createElementVNode("div", { class: "openclaw-layout" }, [
1973
+ _createElementVNode("section", { class: "settings-card settings-card--wide openclaw-workspace-card" }, [
1974
+ _createElementVNode("div", { class: "settings-card-body" }, [
1975
+ _createElementVNode("div", { class: "openclaw-tools-grid" }, [
1976
+ _createElementVNode("button", {
1977
+ class: "openclaw-tool-btn",
1978
+ onClick: _ctx.openOpenclawAgentsEditor,
1979
+ disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
2093
1980
  }, [
2094
- _createElementVNode("button", {
2095
- class: "card-action-btn",
2096
- onClick: $event => (_ctx.openOpenclawEditModal(name)),
2097
- "aria-label": _ctx.t('openclaw.action.editAria', { name }),
2098
- title: _ctx.t('openclaw.action.edit')
1981
+ _createElementVNode("div", { class: "tool-icon" }, "📄"),
1982
+ _createElementVNode("div", { class: "tool-content" }, [
1983
+ _createElementVNode("div", { class: "tool-title" }, "AGENTS.md"),
1984
+ _createElementVNode("div", { class: "tool-meta" }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('openclaw.agents.hint')), 1 /* TEXT */)
1985
+ ]),
1986
+ (_openBlock(), _createElementBlock("svg", {
1987
+ class: "tool-chevron",
1988
+ viewBox: "0 0 24 24",
1989
+ fill: "none",
1990
+ stroke: "currentColor",
1991
+ "stroke-width": "2"
2099
1992
  }, [
2100
- (_openBlock(), _createElementBlock("svg", {
2101
- viewBox: "0 0 24 24",
2102
- fill: "none",
2103
- stroke: "currentColor",
2104
- "stroke-width": "2"
2105
- }, [
2106
- _createElementVNode("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
2107
- _createElementVNode("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
2108
- ]))
2109
- ], 8 /* PROPS */, ["onClick", "aria-label", "title"]),
2110
- (name !== '默认配置')
2111
- ? (_openBlock(), _createElementBlock("button", {
2112
- key: 0,
2113
- class: "card-action-btn delete",
2114
- onClick: $event => (_ctx.deleteOpenclawConfig(name)),
2115
- "aria-label": _ctx.t('openclaw.action.deleteAria', { name }),
2116
- title: _ctx.t('openclaw.action.delete')
1993
+ _createElementVNode("path", { d: "M9 18l6-6-6-6" })
1994
+ ]))
1995
+ ], 8 /* PROPS */, ["onClick", "disabled"]),
1996
+ _createElementVNode("div", { class: "openclaw-workspace-card" }, [
1997
+ _createElementVNode("label", {
1998
+ class: "workspace-label",
1999
+ for: "openclaw-workspace-file"
2000
+ }, _toDisplayString(_ctx.t('openclaw.workspaceFile')), 1 /* TEXT */),
2001
+ _createElementVNode("div", { class: "workspace-input-group" }, [
2002
+ _withDirectives(_createElementVNode("input", {
2003
+ id: "openclaw-workspace-file",
2004
+ class: "form-input",
2005
+ "onUpdate:modelValue": $event => ((_ctx.openclawWorkspaceFileName) = $event),
2006
+ placeholder: _ctx.t('openclaw.workspace.placeholder')
2007
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
2008
+ [_vModelText, _ctx.openclawWorkspaceFileName]
2009
+ ]),
2010
+ _createElementVNode("button", {
2011
+ class: "btn-tool",
2012
+ onClick: _ctx.openOpenclawWorkspaceEditor,
2013
+ disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
2014
+ }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('openclaw.workspace.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
2015
+ ]),
2016
+ _createElementVNode("div", { class: "workspace-meta" }, _toDisplayString(_ctx.t('openclaw.workspace.hint')), 1 /* TEXT */)
2017
+ ])
2018
+ ])
2019
+ ])
2020
+ ]),
2021
+ _createElementVNode("section", {
2022
+ class: "settings-card settings-card--wide openclaw-configs-card",
2023
+ "aria-labelledby": "openclaw-configs-title"
2024
+ }, [
2025
+ _createElementVNode("div", { class: "settings-card-body" }, [
2026
+ _createElementVNode("div", { class: "card-list openclaw-card-list" }, [
2027
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.openclawConfigs, (config, name) => {
2028
+ return (_openBlock(), _createElementBlock("div", {
2029
+ key: name,
2030
+ class: _normalizeClass(['card', { active: _ctx.currentOpenclawConfig === name }]),
2031
+ onClick: $event => (_ctx.applyOpenclawConfig(name)),
2032
+ onKeydown: [
2033
+ _withKeys(_withModifiers($event => (_ctx.applyOpenclawConfig(name)), ["self","prevent"]), ["enter"]),
2034
+ _withKeys(_withModifiers($event => (_ctx.applyOpenclawConfig(name)), ["self","prevent"]), ["space"])
2035
+ ],
2036
+ tabindex: "0",
2037
+ role: "button",
2038
+ "aria-label": _ctx.t('openclaw.action.applyAria', { name }),
2039
+ "aria-current": _ctx.currentOpenclawConfig === name ? 'true' : null
2040
+ }, [
2041
+ _createElementVNode("div", { class: "card-leading" }, [
2042
+ _createElementVNode("div", { class: "card-icon" }, _toDisplayString(name.charAt(0).toUpperCase()), 1 /* TEXT */),
2043
+ _createElementVNode("div", { class: "card-content" }, [
2044
+ _createElementVNode("div", { class: "card-title" }, _toDisplayString(name), 1 /* TEXT */),
2045
+ _createElementVNode("div", { class: "card-subtitle" }, _toDisplayString(_ctx.openclawSubtitle(config)), 1 /* TEXT */)
2046
+ ])
2047
+ ]),
2048
+ _createElementVNode("div", { class: "card-trailing" }, [
2049
+ _createElementVNode("span", {
2050
+ class: _normalizeClass(['pill', _ctx.openclawHasContent(config) ? 'configured' : 'empty'])
2051
+ }, _toDisplayString(_ctx.openclawHasContent(config) ? _ctx.t('openclaw.configured') : _ctx.t('openclaw.notConfigured')), 3 /* TEXT, CLASS */),
2052
+ _createElementVNode("div", {
2053
+ class: "card-actions",
2054
+ onClick: _withModifiers(() => {}, ["stop"])
2117
2055
  }, [
2118
- (_openBlock(), _createElementBlock("svg", {
2119
- viewBox: "0 0 24 24",
2120
- fill: "none",
2121
- stroke: "currentColor",
2122
- "stroke-width": "2"
2056
+ _createElementVNode("button", {
2057
+ class: "card-action-btn",
2058
+ onClick: $event => (_ctx.openOpenclawEditModal(name)),
2059
+ "aria-label": _ctx.t('openclaw.action.editAria', { name }),
2060
+ title: _ctx.t('openclaw.action.edit')
2123
2061
  }, [
2124
- _createElementVNode("path", { d: "M3 6h18" }),
2125
- _createElementVNode("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2126
- ]))
2127
- ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
2128
- : _createCommentVNode("v-if", true)
2129
- ], 8 /* PROPS */, ["onClick"])
2130
- ])
2131
- ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "aria-current"]))
2132
- }), 128 /* KEYED_FRAGMENT */))
2133
- ])
2134
- ], 8 /* PROPS */, ["aria-labelledby"]), [
2135
- [_vShow, _ctx.mainTab === 'config' && _ctx.configMode === 'openclaw']
2136
- ]),
2137
- _createCommentVNode(" 会话浏览模式 "),
2138
- _withDirectives(_createElementVNode("div", {
2139
- class: "mode-content",
2140
- id: "panel-sessions",
2141
- role: "tabpanel",
2062
+ (_openBlock(), _createElementBlock("svg", {
2063
+ viewBox: "0 0 24 24",
2064
+ fill: "none",
2065
+ stroke: "currentColor",
2066
+ "stroke-width": "2"
2067
+ }, [
2068
+ _createElementVNode("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
2069
+ _createElementVNode("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
2070
+ ]))
2071
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]),
2072
+ (!_ctx.isDefaultOpenclawConfig(name, config))
2073
+ ? (_openBlock(), _createElementBlock("button", {
2074
+ key: 0,
2075
+ class: "card-action-btn delete",
2076
+ onClick: $event => (_ctx.deleteOpenclawConfig(name)),
2077
+ "aria-label": _ctx.t('openclaw.action.deleteAria', { name }),
2078
+ title: _ctx.t('openclaw.action.delete')
2079
+ }, [
2080
+ (_openBlock(), _createElementBlock("svg", {
2081
+ viewBox: "0 0 24 24",
2082
+ fill: "none",
2083
+ stroke: "currentColor",
2084
+ "stroke-width": "2"
2085
+ }, [
2086
+ _createElementVNode("path", { d: "M3 6h18" }),
2087
+ _createElementVNode("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
2088
+ ]))
2089
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
2090
+ : _createCommentVNode("v-if", true)
2091
+ ], 8 /* PROPS */, ["onClick"])
2092
+ ])
2093
+ ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "aria-label", "aria-current"]))
2094
+ }), 128 /* KEYED_FRAGMENT */))
2095
+ ])
2096
+ ])
2097
+ ])
2098
+ ])
2099
+ ], 8 /* PROPS */, ["aria-labelledby"]), [
2100
+ [_vShow, _ctx.mainTab === 'config' && _ctx.configMode === 'openclaw']
2101
+ ]),
2102
+ _createCommentVNode(" 会话浏览模式 "),
2103
+ _withDirectives(_createElementVNode("div", {
2104
+ class: "mode-content",
2105
+ id: "panel-sessions",
2106
+ role: "tabpanel",
2142
2107
  "aria-labelledby": 'tab-sessions'
2143
2108
  }, [
2144
2109
  (_ctx.sessionStandalone)
@@ -4014,6 +3979,36 @@ return function render(_ctx, _cache) {
4014
3979
  "aria-labelledby": "settings-tab-general"
4015
3980
  }, [
4016
3981
  _createElementVNode("div", { class: "settings-grid" }, [
3982
+ _createElementVNode("section", {
3983
+ id: "settings-language",
3984
+ class: "settings-card",
3985
+ "aria-label": _ctx.t('settings.language.title')
3986
+ }, [
3987
+ _createElementVNode("div", { class: "settings-card-main" }, [
3988
+ _createElementVNode("div", { class: "settings-card-content" }, [
3989
+ _createElementVNode("div", { class: "settings-card-title" }, _toDisplayString(_ctx.t('settings.language.title')), 1 /* TEXT */),
3990
+ _createElementVNode("p", { class: "settings-card-desc" }, _toDisplayString(_ctx.t('settings.language.meta')), 1 /* TEXT */),
3991
+ _createElementVNode("label", {
3992
+ class: "selector-label",
3993
+ for: "settings-language-select"
3994
+ }, _toDisplayString(_ctx.t('settings.language.label')), 1 /* TEXT */),
3995
+ _createElementVNode("select", {
3996
+ id: "settings-language-select",
3997
+ class: "model-select settings-language-select",
3998
+ value: _ctx.lang,
3999
+ onChange: $event => (_ctx.setLang($event.target.value))
4000
+ }, [
4001
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.languageOptions(), (option) => {
4002
+ return (_openBlock(), _createElementBlock("option", {
4003
+ key: option.code,
4004
+ value: option.code
4005
+ }, _toDisplayString(option.nativeName) + " · " + _toDisplayString(option.englishName), 9 /* TEXT, PROPS */, ["value"]))
4006
+ }), 128 /* KEYED_FRAGMENT */))
4007
+ ], 40 /* PROPS, NEED_HYDRATION */, ["value", "onChange"]),
4008
+ _createElementVNode("p", { class: "settings-card-hint" }, _toDisplayString(_ctx.t('settings.language.hint')), 1 /* TEXT */)
4009
+ ])
4010
+ ])
4011
+ ], 8 /* PROPS */, ["aria-label"]),
4017
4012
  _createElementVNode("section", {
4018
4013
  class: "settings-card",
4019
4014
  "aria-label": _ctx.t('settings.sharePrefix.title')
@@ -4064,17 +4059,17 @@ return function render(_ctx, _cache) {
4064
4059
  ], 8 /* PROPS */, ["aria-label"]),
4065
4060
  _createElementVNode("section", {
4066
4061
  class: "settings-card",
4067
- "aria-label": 'Webhook'
4062
+ "aria-label": _ctx.t('settings.webhook.title')
4068
4063
  }, [
4069
4064
  _createElementVNode("div", { class: "settings-card-main" }, [
4070
4065
  _createElementVNode("div", { class: "settings-card-content" }, [
4071
- _createElementVNode("div", { class: "settings-card-title" }, "Webhook"),
4072
- _createElementVNode("p", { class: "settings-card-desc" }, "配置变更时外发通知"),
4066
+ _createElementVNode("div", { class: "settings-card-title" }, _toDisplayString(_ctx.t('settings.webhook.title')), 1 /* TEXT */),
4067
+ _createElementVNode("p", { class: "settings-card-desc" }, _toDisplayString(_ctx.t('settings.webhook.meta')), 1 /* TEXT */),
4073
4068
  _createElementVNode("div", { class: "webhook-status" }, [
4074
4069
  _createElementVNode("span", {
4075
4070
  class: _normalizeClass(["webhook-status-dot", { active: _ctx.webhookConfig.enabled }])
4076
4071
  }, null, 2 /* CLASS */),
4077
- _createElementVNode("span", { class: "webhook-status-label" }, _toDisplayString(_ctx.webhookConfig.enabled ? '已启用' : '已禁用'), 1 /* TEXT */),
4072
+ _createElementVNode("span", { class: "webhook-status-label" }, _toDisplayString(_ctx.webhookConfig.enabled ? _ctx.t('settings.webhook.enabled') : _ctx.t('settings.webhook.disabled')), 1 /* TEXT */),
4078
4073
  (_ctx.webhookConfig.url)
4079
4074
  ? (_openBlock(), _createElementBlock("code", {
4080
4075
  key: 0,
@@ -4089,10 +4084,10 @@ return function render(_ctx, _cache) {
4089
4084
  onClick: _ctx.openWebhookModal
4090
4085
  }, [
4091
4086
  (_ctx.webhookConfig.enabled)
4092
- ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.webhookConfig.url ? '编辑' : '配置'), 1 /* TEXT */))
4093
- : (_openBlock(), _createElementBlock("span", { key: 1 }, "启用"))
4087
+ ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.webhookConfig.url ? _ctx.t('settings.webhook.edit') : _ctx.t('settings.webhook.configure')), 1 /* TEXT */))
4088
+ : (_openBlock(), _createElementBlock("span", { key: 1 }, _toDisplayString(_ctx.t('settings.webhook.enable')), 1 /* TEXT */))
4094
4089
  ], 10 /* CLASS, PROPS */, ["onClick"])
4095
- ])
4090
+ ], 8 /* PROPS */, ["aria-label"])
4096
4091
  ])
4097
4092
  ], 512 /* NEED_PATCH */), [
4098
4093
  [_vShow, _ctx.settingsTab === 'general']
@@ -4174,7 +4169,7 @@ return function render(_ctx, _cache) {
4174
4169
  onChange: $event => (_ctx.setSessionTrashRetentionDays(Number($event.target.value))),
4175
4170
  class: "settings-retention-input"
4176
4171
  }, null, 40 /* PROPS, NEED_HYDRATION */, ["value", "onChange"]),
4177
- _createElementVNode("span", null, "天")
4172
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('settings.trash.retentionUnit')), 1 /* TEXT */)
4178
4173
  ]),
4179
4174
  _createElementVNode("p", { class: "settings-card-hint" }, _toDisplayString(_ctx.t('settings.trash.retentionHint')), 1 /* TEXT */)
4180
4175
  ])
@@ -4204,7 +4199,7 @@ return function render(_ctx, _cache) {
4204
4199
  ], 512 /* NEED_PATCH */), [
4205
4200
  [_vShow, _ctx.mainTab === 'settings']
4206
4201
  ]),
4207
- _createCommentVNode(" 回收站面板 "),
4202
+ _createCommentVNode(" Trash panel "),
4208
4203
  _withDirectives(_createElementVNode("div", {
4209
4204
  class: "mode-content",
4210
4205
  id: "panel-trash",
@@ -4216,7 +4211,7 @@ return function render(_ctx, _cache) {
4216
4211
  key: 0,
4217
4212
  class: "trash-panel-shell"
4218
4213
  }, [
4219
- _createCommentVNode(" 空态 "),
4214
+ _createCommentVNode(" Empty state "),
4220
4215
  (_ctx.getSessionTrashViewState() === 'empty')
4221
4216
  ? (_openBlock(), _createElementBlock("div", {
4222
4217
  key: 0,
@@ -4239,11 +4234,11 @@ return function render(_ctx, _cache) {
4239
4234
  })
4240
4235
  ])),
4241
4236
  _createElementVNode("div", { class: "trash-empty-title" }, _toDisplayString(_ctx.t('settings.trash.empty')), 1 /* TEXT */),
4242
- _createElementVNode("div", { class: "trash-empty-hint" }, "删除的会话保留 " + _toDisplayString(_ctx.sessionTrashRetentionDays) + " 天后自动清理", 1 /* TEXT */)
4237
+ _createElementVNode("div", { class: "trash-empty-hint" }, _toDisplayString(_ctx.t('settings.trash.emptyHint', { days: _ctx.sessionTrashRetentionDays })), 1 /* TEXT */)
4243
4238
  ]))
4244
4239
  : (_ctx.getSessionTrashViewState() === 'loading')
4245
4240
  ? (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
4246
- _createCommentVNode(" 加载态 "),
4241
+ _createCommentVNode(" Loading state "),
4247
4242
  _createElementVNode("div", { class: "trash-empty-state" }, [
4248
4243
  _createElementVNode("div", { class: "trash-spinner" }),
4249
4244
  _createElementVNode("div", { class: "trash-empty-title" }, _toDisplayString(_ctx.t('settings.trash.loading')), 1 /* TEXT */)
@@ -4251,7 +4246,7 @@ return function render(_ctx, _cache) {
4251
4246
  ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
4252
4247
  : (_ctx.getSessionTrashViewState() === 'retry')
4253
4248
  ? (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [
4254
- _createCommentVNode(" 错误态 "),
4249
+ _createCommentVNode(" Error state "),
4255
4250
  _createElementVNode("div", { class: "trash-empty-state" }, [
4256
4251
  (_openBlock(), _createElementBlock("svg", {
4257
4252
  class: "trash-empty-svg",
@@ -4275,21 +4270,22 @@ return function render(_ctx, _cache) {
4275
4270
  _createElementVNode("button", {
4276
4271
  class: "btn-tool",
4277
4272
  onClick: $event => (_ctx.loadSessionTrash({ forceRefresh: true }))
4278
- }, "重试", 8 /* PROPS */, ["onClick"])
4273
+ }, _toDisplayString(_ctx.t('common.retry')), 9 /* TEXT, PROPS */, ["onClick"])
4279
4274
  ])
4280
4275
  ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
4281
4276
  : (_openBlock(), _createElementBlock(_Fragment, { key: 3 }, [
4282
- _createCommentVNode(" 列表态 "),
4277
+ _createCommentVNode(" List state "),
4283
4278
  _createElementVNode("div", { class: "trash-toolbar" }, [
4284
4279
  _createElementVNode("div", { class: "trash-toolbar-left" }, [
4285
- _createElementVNode("span", { class: "trash-toolbar-count" }, _toDisplayString(_ctx.sessionTrashCount) + " 个已删除会话", 1 /* TEXT */),
4286
- _createElementVNode("span", { class: "trash-toolbar-retention" }, _toDisplayString(_ctx.sessionTrashRetentionDays) + " 天后自动清理", 1 /* TEXT */)
4280
+ _createElementVNode("span", { class: "trash-toolbar-count" }, _toDisplayString(_ctx.t('settings.trash.count', { count: _ctx.sessionTrashCount })), 1 /* TEXT */),
4281
+ _createElementVNode("span", { class: "trash-toolbar-retention" }, _toDisplayString(_ctx.t('settings.trash.retentionShort', { days: _ctx.sessionTrashRetentionDays })), 1 /* TEXT */)
4287
4282
  ]),
4288
4283
  _createElementVNode("div", { class: "trash-toolbar-right" }, [
4289
4284
  _createElementVNode("button", {
4290
4285
  class: "btn-mini",
4291
4286
  onClick: $event => (_ctx.loadSessionTrash({ forceRefresh: true })),
4292
4287
  disabled: _ctx.sessionTrashLoading,
4288
+ "aria-label": _ctx.t('sessions.refresh'),
4293
4289
  title: _ctx.t('sessions.refresh')
4294
4290
  }, [
4295
4291
  (_openBlock(), _createElementBlock("svg", {
@@ -4301,12 +4297,12 @@ return function render(_ctx, _cache) {
4301
4297
  }, [
4302
4298
  _createElementVNode("path", { d: "M21 2v6h-6M3 12a9 9 0 0115-6.7L21 8M3 22v-6h6M21 12a9 9 0 01-15 6.7L3 16" })
4303
4299
  ]))
4304
- ], 8 /* PROPS */, ["onClick", "disabled", "title"]),
4300
+ ], 8 /* PROPS */, ["onClick", "disabled", "aria-label", "title"]),
4305
4301
  _createElementVNode("button", {
4306
4302
  class: "btn-mini delete",
4307
4303
  onClick: _ctx.clearSessionTrash,
4308
4304
  disabled: _ctx.sessionTrashClearing || _ctx.sessionTrashLoading || !(Number(_ctx.sessionTrashCount) > 0)
4309
- }, _toDisplayString(_ctx.sessionTrashClearing ? '清空中…' : '清空'), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4305
+ }, _toDisplayString(_ctx.sessionTrashClearing ? _ctx.t('settings.trash.clearing') : _ctx.t('settings.trash.clearShort')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4310
4306
  ])
4311
4307
  ]),
4312
4308
  _createElementVNode("div", { class: "trash-list" }, [
@@ -4337,7 +4333,8 @@ return function render(_ctx, _cache) {
4337
4333
  class: "trash-action-btn restore",
4338
4334
  onClick: $event => (_ctx.restoreSessionTrash(item)),
4339
4335
  disabled: _ctx.sessionTrashLoading || _ctx.sessionTrashClearing || _ctx.isSessionTrashActionBusy(item),
4340
- title: _ctx.sessionTrashRestoring[_ctx.getSessionTrashActionKey(item)] ? '恢复中…' : '恢复'
4336
+ "aria-label": _ctx.sessionTrashRestoring[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.restoring') : _ctx.t('settings.trash.restore'),
4337
+ title: _ctx.sessionTrashRestoring[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.restoring') : _ctx.t('settings.trash.restore')
4341
4338
  }, [
4342
4339
  (_openBlock(), _createElementBlock("svg", {
4343
4340
  viewBox: "0 0 24 24",
@@ -4348,12 +4345,13 @@ return function render(_ctx, _cache) {
4348
4345
  _createElementVNode("path", { d: "M3 12a9 9 0 119 9" }),
4349
4346
  _createElementVNode("path", { d: "M3 4v6h6" })
4350
4347
  ]))
4351
- ], 8 /* PROPS */, ["onClick", "disabled", "title"]),
4348
+ ], 8 /* PROPS */, ["onClick", "disabled", "aria-label", "title"]),
4352
4349
  _createElementVNode("button", {
4353
4350
  class: "trash-action-btn delete",
4354
4351
  onClick: $event => (_ctx.purgeSessionTrash(item)),
4355
4352
  disabled: _ctx.sessionTrashLoading || _ctx.sessionTrashClearing || _ctx.isSessionTrashActionBusy(item),
4356
- title: _ctx.sessionTrashPurging[_ctx.getSessionTrashActionKey(item)] ? '删除中…' : '彻底删除'
4353
+ "aria-label": _ctx.sessionTrashPurging[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.purging') : _ctx.t('settings.trash.purge'),
4354
+ title: _ctx.sessionTrashPurging[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.purging') : _ctx.t('settings.trash.purge')
4357
4355
  }, [
4358
4356
  (_openBlock(), _createElementBlock("svg", {
4359
4357
  viewBox: "0 0 24 24",
@@ -4363,7 +4361,7 @@ return function render(_ctx, _cache) {
4363
4361
  }, [
4364
4362
  _createElementVNode("path", { d: "M3 6h18M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6M10 11v6M14 11v6" })
4365
4363
  ]))
4366
- ], 8 /* PROPS */, ["onClick", "disabled", "title"])
4364
+ ], 8 /* PROPS */, ["onClick", "disabled", "aria-label", "title"])
4367
4365
  ])
4368
4366
  ])
4369
4367
  ]))
@@ -4377,7 +4375,7 @@ return function render(_ctx, _cache) {
4377
4375
  class: "btn-tool btn-tool-compact",
4378
4376
  onClick: _ctx.loadMoreSessionTrashItems,
4379
4377
  disabled: _ctx.sessionTrashLoading || _ctx.sessionTrashClearing
4380
- }, " 加载更多(" + _toDisplayString(_ctx.sessionTrashHiddenCount) + " 条) ", 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4378
+ }, _toDisplayString(_ctx.t('settings.trash.loadMoreItems', { count: _ctx.sessionTrashHiddenCount })), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4381
4379
  ]))
4382
4380
  : _createCommentVNode("v-if", true)
4383
4381
  ])
@@ -5280,15 +5278,81 @@ return function render(_ctx, _cache) {
5280
5278
  : _createCommentVNode("v-if", true)
5281
5279
  ]),
5282
5280
  _createElementVNode("div", { class: "form-group" }, [
5283
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiKey')), 1 /* TEXT */),
5281
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelName')), 1 /* TEXT */),
5284
5282
  _withDirectives(_createElementVNode("input", {
5285
- "onUpdate:modelValue": $event => ((_ctx.newProvider.key) = $event),
5286
- class: "form-input",
5287
- type: "password",
5288
- placeholder: "sk-..."
5289
- }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
5290
- [_vModelText, _ctx.newProvider.key]
5291
- ])
5283
+ "onUpdate:modelValue": $event => ((_ctx.newProvider.model) = $event),
5284
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.providerFieldError('add', 'model') }]),
5285
+ placeholder: _ctx.t('placeholder.modelExample'),
5286
+ autocomplete: "off",
5287
+ spellcheck: "false",
5288
+ onBlur: $event => (_ctx.normalizeProviderDraft('add'))
5289
+ }, null, 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onBlur"]), [
5290
+ [_vModelText, _ctx.newProvider.model]
5291
+ ]),
5292
+ (_ctx.providerFieldError('add', 'model'))
5293
+ ? (_openBlock(), _createElementBlock("div", {
5294
+ key: 0,
5295
+ class: "form-hint form-error"
5296
+ }, _toDisplayString(_ctx.providerFieldError('add', 'model')), 1 /* TEXT */))
5297
+ : _createCommentVNode("v-if", true)
5298
+ ]),
5299
+ _createElementVNode("div", { class: "form-group" }, [
5300
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiKey')), 1 /* TEXT */),
5301
+ _createElementVNode("div", { class: "input-with-toggle" }, [
5302
+ _withDirectives(_createElementVNode("input", {
5303
+ "onUpdate:modelValue": $event => ((_ctx.newProvider.key) = $event),
5304
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.providerFieldError('add', 'key') }]),
5305
+ type: _ctx.showAddProviderKey ? 'text' : 'password',
5306
+ placeholder: "sk-...",
5307
+ autocomplete: "off",
5308
+ spellcheck: "false",
5309
+ onBlur: $event => (_ctx.normalizeProviderDraft('add'))
5310
+ }, null, 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "type", "onBlur"]), [
5311
+ [_vModelDynamic, _ctx.newProvider.key]
5312
+ ]),
5313
+ _createElementVNode("button", {
5314
+ type: "button",
5315
+ class: "input-toggle-btn",
5316
+ onClick: _ctx.toggleAddProviderKey,
5317
+ title: _ctx.showAddProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5318
+ "aria-label": _ctx.showAddProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5319
+ }, [
5320
+ (!_ctx.showAddProviderKey)
5321
+ ? (_openBlock(), _createElementBlock("svg", {
5322
+ key: 0,
5323
+ viewBox: "0 0 20 20",
5324
+ fill: "none",
5325
+ stroke: "currentColor",
5326
+ "stroke-width": "1.5",
5327
+ width: "16",
5328
+ height: "16"
5329
+ }, [
5330
+ _createElementVNode("path", { d: "M10 4C5 4 1.73 8.11 1 10c.73 1.89 4 6 9 6s8.27-4.11 9-6c-.73-1.89-4-6-9-6z" }),
5331
+ _createElementVNode("circle", {
5332
+ cx: "10",
5333
+ cy: "10",
5334
+ r: "3"
5335
+ })
5336
+ ]))
5337
+ : (_openBlock(), _createElementBlock("svg", {
5338
+ key: 1,
5339
+ viewBox: "0 0 20 20",
5340
+ fill: "none",
5341
+ stroke: "currentColor",
5342
+ "stroke-width": "1.5",
5343
+ width: "16",
5344
+ height: "16"
5345
+ }, [
5346
+ _createElementVNode("path", { d: "M2 2l16 16M8.2 4.2A9.9 9.9 0 0 1 10 4c5 0 8.27 4.11 9 6-.44.94-1.5 2.7-3.2 4.2M14.5 14.5A5.9 5.9 0 0 1 10 16c-5 0-8.27-4.11-9-6 .76-1.66 2.2-3.6 4.3-5" })
5347
+ ]))
5348
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5349
+ ]),
5350
+ (_ctx.providerFieldError('add', 'key'))
5351
+ ? (_openBlock(), _createElementBlock("div", {
5352
+ key: 0,
5353
+ class: "form-hint form-error"
5354
+ }, _toDisplayString(_ctx.providerFieldError('add', 'key')), 1 /* TEXT */))
5355
+ : _createCommentVNode("v-if", true)
5292
5356
  ]),
5293
5357
  _createElementVNode("div", { class: "form-group" }, [
5294
5358
  _createElementVNode("label", { class: "form-label" }, [
@@ -5379,7 +5443,8 @@ return function render(_ctx, _cache) {
5379
5443
  type: "button",
5380
5444
  class: "input-toggle-btn",
5381
5445
  onClick: _ctx.toggleEditProviderKey,
5382
- title: _ctx.showEditProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5446
+ title: _ctx.showEditProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5447
+ "aria-label": _ctx.showEditProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5383
5448
  }, [
5384
5449
  (!_ctx.showEditProviderKey)
5385
5450
  ? (_openBlock(), _createElementBlock("svg", {
@@ -5409,7 +5474,7 @@ return function render(_ctx, _cache) {
5409
5474
  }, [
5410
5475
  _createElementVNode("path", { d: "M2 2l16 16M8.2 4.2A9.9 9.9 0 0 1 10 4c5 0 8.27 4.11 9 6-.44.94-1.5 2.7-3.2 4.2M14.5 14.5A5.9 5.9 0 0 1 10 16c-5 0-8.27-4.11-9-6 .76-1.66 2.2-3.6 4.3-5" })
5411
5476
  ]))
5412
- ], 8 /* PROPS */, ["onClick", "title"])
5477
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5413
5478
  ])
5414
5479
  ]),
5415
5480
  _createElementVNode("div", { class: "btn-group" }, [
@@ -5528,34 +5593,108 @@ return function render(_ctx, _cache) {
5528
5593
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.configName')), 1 /* TEXT */),
5529
5594
  _withDirectives(_createElementVNode("input", {
5530
5595
  "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.name) = $event),
5531
- class: "form-input",
5596
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'name') }]),
5532
5597
  placeholder: _ctx.t('placeholder.configNameExample')
5533
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5598
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5534
5599
  [_vModelText, _ctx.newClaudeConfig.name]
5535
- ])
5600
+ ]),
5601
+ (_ctx.claudeConfigFieldError('add', 'name'))
5602
+ ? (_openBlock(), _createElementBlock("div", {
5603
+ key: 0,
5604
+ class: "form-hint form-error"
5605
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'name')), 1 /* TEXT */))
5606
+ : _createCommentVNode("v-if", true)
5536
5607
  ]),
5537
5608
  _createElementVNode("div", { class: "form-group" }, [
5538
5609
  _createElementVNode("label", { class: "form-label" }, "API Key"),
5539
- _withDirectives(_createElementVNode("input", {
5540
- "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.apiKey) = $event),
5541
- class: "form-input",
5542
- type: "password",
5543
- autocomplete: "off",
5544
- spellcheck: "false",
5545
- placeholder: _ctx.t('placeholder.apiKeyExampleClaude')
5546
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5547
- [_vModelText, _ctx.newClaudeConfig.apiKey]
5548
- ])
5610
+ _createElementVNode("div", { class: "input-with-toggle" }, [
5611
+ _withDirectives(_createElementVNode("input", {
5612
+ "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.apiKey) = $event),
5613
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'apiKey') }]),
5614
+ type: _ctx.showAddClaudeConfigKey ? 'text' : 'password',
5615
+ autocomplete: "off",
5616
+ spellcheck: "false",
5617
+ placeholder: _ctx.t('placeholder.apiKeyExampleClaude')
5618
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "type", "placeholder"]), [
5619
+ [_vModelDynamic, _ctx.newClaudeConfig.apiKey]
5620
+ ]),
5621
+ _createElementVNode("button", {
5622
+ type: "button",
5623
+ class: "input-toggle-btn",
5624
+ onClick: _ctx.toggleAddClaudeConfigKey,
5625
+ title: _ctx.showAddClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5626
+ "aria-label": _ctx.showAddClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5627
+ }, [
5628
+ (!_ctx.showAddClaudeConfigKey)
5629
+ ? (_openBlock(), _createElementBlock("svg", {
5630
+ key: 0,
5631
+ viewBox: "0 0 20 20",
5632
+ fill: "none",
5633
+ stroke: "currentColor",
5634
+ "stroke-width": "1.5",
5635
+ width: "16",
5636
+ height: "16"
5637
+ }, [
5638
+ _createElementVNode("path", { d: "M10 4C5 4 1.73 8.11 1 10c.73 1.89 4 6 9 6s8.27-4.11 9-6c-.73-1.89-4-6-9-6z" }),
5639
+ _createElementVNode("circle", {
5640
+ cx: "10",
5641
+ cy: "10",
5642
+ r: "3"
5643
+ })
5644
+ ]))
5645
+ : (_openBlock(), _createElementBlock("svg", {
5646
+ key: 1,
5647
+ viewBox: "0 0 20 20",
5648
+ fill: "none",
5649
+ stroke: "currentColor",
5650
+ "stroke-width": "1.5",
5651
+ width: "16",
5652
+ height: "16"
5653
+ }, [
5654
+ _createElementVNode("path", { d: "M2 2l16 16M8.2 4.2A9.9 9.9 0 0 1 10 4c5 0 8.27 4.11 9 6-.44.94-1.5 2.7-3.2 4.2M14.5 14.5A5.9 5.9 0 0 1 10 16c-5 0-8.27-4.11-9-6 .76-1.66 2.2-3.6 4.3-5" })
5655
+ ]))
5656
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5657
+ ]),
5658
+ (_ctx.claudeConfigFieldError('add', 'apiKey'))
5659
+ ? (_openBlock(), _createElementBlock("div", {
5660
+ key: 0,
5661
+ class: "form-hint form-error"
5662
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'apiKey')), 1 /* TEXT */))
5663
+ : _createCommentVNode("v-if", true)
5549
5664
  ]),
5550
5665
  _createElementVNode("div", { class: "form-group" }, [
5551
5666
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
5552
5667
  _withDirectives(_createElementVNode("input", {
5553
5668
  "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.baseUrl) = $event),
5554
- class: "form-input",
5669
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'baseUrl') }]),
5555
5670
  placeholder: _ctx.t('placeholder.baseUrlExampleClaude')
5556
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5671
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5557
5672
  [_vModelText, _ctx.newClaudeConfig.baseUrl]
5558
- ])
5673
+ ]),
5674
+ (_ctx.claudeConfigFieldError('add', 'baseUrl'))
5675
+ ? (_openBlock(), _createElementBlock("div", {
5676
+ key: 0,
5677
+ class: "form-hint form-error"
5678
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'baseUrl')), 1 /* TEXT */))
5679
+ : _createCommentVNode("v-if", true)
5680
+ ]),
5681
+ _createElementVNode("div", { class: "form-group" }, [
5682
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelName')), 1 /* TEXT */),
5683
+ _withDirectives(_createElementVNode("input", {
5684
+ "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.model) = $event),
5685
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'model') }]),
5686
+ placeholder: _ctx.t('placeholder.modelExample'),
5687
+ autocomplete: "off",
5688
+ spellcheck: "false"
5689
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5690
+ [_vModelText, _ctx.newClaudeConfig.model]
5691
+ ]),
5692
+ (_ctx.claudeConfigFieldError('add', 'model'))
5693
+ ? (_openBlock(), _createElementBlock("div", {
5694
+ key: 0,
5695
+ class: "form-hint form-error"
5696
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'model')), 1 /* TEXT */))
5697
+ : _createCommentVNode("v-if", true)
5559
5698
  ]),
5560
5699
  _createElementVNode("div", { class: "btn-group" }, [
5561
5700
  _createElementVNode("button", {
@@ -5564,8 +5703,9 @@ return function render(_ctx, _cache) {
5564
5703
  }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"]),
5565
5704
  _createElementVNode("button", {
5566
5705
  class: "btn btn-confirm",
5567
- onClick: _ctx.addClaudeConfig
5568
- }, _toDisplayString(_ctx.t('common.add')), 9 /* TEXT, PROPS */, ["onClick"])
5706
+ onClick: _ctx.addClaudeConfig,
5707
+ disabled: !_ctx.canSubmitClaudeConfig('add')
5708
+ }, _toDisplayString(_ctx.t('common.add')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
5569
5709
  ])
5570
5710
  ])
5571
5711
  ], 8 /* PROPS */, ["onClick"]))
@@ -5591,31 +5731,38 @@ return function render(_ctx, _cache) {
5591
5731
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.configName')), 1 /* TEXT */),
5592
5732
  _withDirectives(_createElementVNode("input", {
5593
5733
  "onUpdate:modelValue": $event => ((_ctx.editingConfig.name) = $event),
5594
- class: "form-input",
5734
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'name') }]),
5595
5735
  placeholder: _ctx.t('field.configName'),
5596
5736
  readonly: ""
5597
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5737
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5598
5738
  [_vModelText, _ctx.editingConfig.name]
5599
- ])
5739
+ ]),
5740
+ (_ctx.claudeConfigFieldError('edit', 'name'))
5741
+ ? (_openBlock(), _createElementBlock("div", {
5742
+ key: 0,
5743
+ class: "form-hint form-error"
5744
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'name')), 1 /* TEXT */))
5745
+ : _createCommentVNode("v-if", true)
5600
5746
  ]),
5601
5747
  _createElementVNode("div", { class: "form-group" }, [
5602
5748
  _createElementVNode("label", { class: "form-label" }, "API Key"),
5603
5749
  _createElementVNode("div", { class: "input-with-toggle" }, [
5604
5750
  _withDirectives(_createElementVNode("input", {
5605
5751
  "onUpdate:modelValue": $event => ((_ctx.editingConfig.apiKey) = $event),
5606
- class: "form-input",
5752
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'apiKey') }]),
5607
5753
  type: _ctx.showEditClaudeConfigKey ? 'text' : 'password',
5608
5754
  autocomplete: "off",
5609
5755
  spellcheck: "false",
5610
5756
  placeholder: _ctx.t('placeholder.apiKeyExampleClaude')
5611
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "type", "placeholder"]), [
5757
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "type", "placeholder"]), [
5612
5758
  [_vModelDynamic, _ctx.editingConfig.apiKey]
5613
5759
  ]),
5614
5760
  _createElementVNode("button", {
5615
5761
  type: "button",
5616
5762
  class: "input-toggle-btn",
5617
5763
  onClick: _ctx.toggleEditClaudeConfigKey,
5618
- title: _ctx.showEditClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5764
+ title: _ctx.showEditClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5765
+ "aria-label": _ctx.showEditClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5619
5766
  }, [
5620
5767
  (!_ctx.showEditClaudeConfigKey)
5621
5768
  ? (_openBlock(), _createElementBlock("svg", {
@@ -5645,18 +5792,48 @@ return function render(_ctx, _cache) {
5645
5792
  }, [
5646
5793
  _createElementVNode("path", { d: "M2 2l16 16M8.2 4.2A9.9 9.9 0 0 1 10 4c5 0 8.27 4.11 9 6-.44.94-1.5 2.7-3.2 4.2M14.5 14.5A5.9 5.9 0 0 1 10 16c-5 0-8.27-4.11-9-6 .76-1.66 2.2-3.6 4.3-5" })
5647
5794
  ]))
5648
- ], 8 /* PROPS */, ["onClick", "title"])
5649
- ])
5795
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5796
+ ]),
5797
+ (_ctx.claudeConfigFieldError('edit', 'apiKey'))
5798
+ ? (_openBlock(), _createElementBlock("div", {
5799
+ key: 0,
5800
+ class: "form-hint form-error"
5801
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'apiKey')), 1 /* TEXT */))
5802
+ : _createCommentVNode("v-if", true)
5650
5803
  ]),
5651
5804
  _createElementVNode("div", { class: "form-group" }, [
5652
5805
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
5653
5806
  _withDirectives(_createElementVNode("input", {
5654
5807
  "onUpdate:modelValue": $event => ((_ctx.editingConfig.baseUrl) = $event),
5655
- class: "form-input",
5808
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'baseUrl') }]),
5656
5809
  placeholder: _ctx.t('placeholder.baseUrlExampleClaude')
5657
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5810
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5658
5811
  [_vModelText, _ctx.editingConfig.baseUrl]
5659
- ])
5812
+ ]),
5813
+ (_ctx.claudeConfigFieldError('edit', 'baseUrl'))
5814
+ ? (_openBlock(), _createElementBlock("div", {
5815
+ key: 0,
5816
+ class: "form-hint form-error"
5817
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'baseUrl')), 1 /* TEXT */))
5818
+ : _createCommentVNode("v-if", true)
5819
+ ]),
5820
+ _createElementVNode("div", { class: "form-group" }, [
5821
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelName')), 1 /* TEXT */),
5822
+ _withDirectives(_createElementVNode("input", {
5823
+ "onUpdate:modelValue": $event => ((_ctx.editingConfig.model) = $event),
5824
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'model') }]),
5825
+ placeholder: _ctx.t('placeholder.modelExample'),
5826
+ autocomplete: "off",
5827
+ spellcheck: "false"
5828
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5829
+ [_vModelText, _ctx.editingConfig.model]
5830
+ ]),
5831
+ (_ctx.claudeConfigFieldError('edit', 'model'))
5832
+ ? (_openBlock(), _createElementBlock("div", {
5833
+ key: 0,
5834
+ class: "form-hint form-error"
5835
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'model')), 1 /* TEXT */))
5836
+ : _createCommentVNode("v-if", true)
5660
5837
  ]),
5661
5838
  _createElementVNode("div", { class: "btn-group" }, [
5662
5839
  _createElementVNode("button", {
@@ -5665,13 +5842,14 @@ return function render(_ctx, _cache) {
5665
5842
  }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"]),
5666
5843
  _createElementVNode("button", {
5667
5844
  class: "btn btn-confirm",
5668
- onClick: _ctx.saveAndApplyConfig
5669
- }, _toDisplayString(_ctx.t('common.saveApply')), 9 /* TEXT, PROPS */, ["onClick"])
5845
+ onClick: _ctx.saveAndApplyConfig,
5846
+ disabled: !_ctx.canSubmitClaudeConfig('edit')
5847
+ }, _toDisplayString(_ctx.t('common.saveApply')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
5670
5848
  ])
5671
5849
  ])
5672
5850
  ], 8 /* PROPS */, ["onClick"]))
5673
5851
  : _createCommentVNode("v-if", true),
5674
- _createCommentVNode(" Codex 轮询池控制模态框 "),
5852
+ _createCommentVNode(" Codex bridge pool modal "),
5675
5853
  (_ctx.showCodexBridgePoolModal)
5676
5854
  ? (_openBlock(), _createElementBlock("div", {
5677
5855
  key: 8,
@@ -5715,9 +5893,9 @@ return function render(_ctx, _cache) {
5715
5893
  _createElementVNode("path", { d: "M6 8v4h6v4" }),
5716
5894
  _createElementVNode("path", { d: "M18 8v4h-6v4" })
5717
5895
  ])),
5718
- _createTextVNode(" 轮询池设置 ")
5896
+ _createTextVNode(" " + _toDisplayString(_ctx.t('config.localBridge.poolSettings')), 1 /* TEXT */)
5719
5897
  ]),
5720
- _createElementVNode("div", { class: "bridge-pool-modal-hint" }, "勾选参与负载均衡的提供商"),
5898
+ _createElementVNode("div", { class: "bridge-pool-modal-hint" }, _toDisplayString(_ctx.t('config.localBridge.poolHint')), 1 /* TEXT */),
5721
5899
  (_ctx.localBridgeCandidateProviders().length === 0)
5722
5900
  ? (_openBlock(), _createElementBlock("div", {
5723
5901
  key: 0,
@@ -5733,7 +5911,7 @@ return function render(_ctx, _cache) {
5733
5911
  }, [
5734
5912
  _createElementVNode("path", { d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z" })
5735
5913
  ])),
5736
- _createElementVNode("span", null, "暂无可用上游 provider,请先添加直连 provider")
5914
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('config.localBridge.noProviders')), 1 /* TEXT */)
5737
5915
  ]))
5738
5916
  : (_openBlock(), _createElementBlock("div", {
5739
5917
  key: 1,
@@ -5747,7 +5925,7 @@ return function render(_ctx, _cache) {
5747
5925
  _createElementVNode("span", { class: "bridge-pool-item-name" }, _toDisplayString(cp.name), 1 /* TEXT */),
5748
5926
  _createElementVNode("span", {
5749
5927
  class: _normalizeClass(["bridge-pool-item-status", { active: !_ctx.isLocalBridgeExcluded(cp.name) }])
5750
- }, _toDisplayString(_ctx.isLocalBridgeExcluded(cp.name) ? '未启用' : '已启用'), 3 /* TEXT, CLASS */),
5928
+ }, _toDisplayString(_ctx.isLocalBridgeExcluded(cp.name) ? _ctx.t('common.disabled') : _ctx.t('common.enabled')), 3 /* TEXT, CLASS */),
5751
5929
  _createElementVNode("input", {
5752
5930
  type: "checkbox",
5753
5931
  checked: !_ctx.isLocalBridgeExcluded(cp.name),
@@ -5858,7 +6036,7 @@ return function render(_ctx, _cache) {
5858
6036
  ])
5859
6037
  ], 8 /* PROPS */, ["onClick"]))
5860
6038
  : _createCommentVNode("v-if", true),
5861
- _createCommentVNode(" Webhook 配置模态框 "),
6039
+ _createCommentVNode(" Webhook settings modal "),
5862
6040
  (_ctx.showWebhookModal)
5863
6041
  ? (_openBlock(), _createElementBlock("div", {
5864
6042
  key: 10,
@@ -5874,9 +6052,9 @@ return function render(_ctx, _cache) {
5874
6052
  _createElementVNode("div", {
5875
6053
  class: "modal-title",
5876
6054
  id: "webhook-modal-title"
5877
- }, "Webhook 配置"),
6055
+ }, _toDisplayString(_ctx.t('settings.webhook.modalTitle')), 1 /* TEXT */),
5878
6056
  _createElementVNode("div", { class: "form-group" }, [
5879
- _createElementVNode("label", { class: "form-label" }, "启用状态"),
6057
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('settings.webhook.enabledLabel')), 1 /* TEXT */),
5880
6058
  _createElementVNode("label", { class: "settings-toggle" }, [
5881
6059
  _withDirectives(_createElementVNode("input", {
5882
6060
  type: "checkbox",
@@ -5884,11 +6062,11 @@ return function render(_ctx, _cache) {
5884
6062
  }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
5885
6063
  [_vModelCheckbox, _ctx.webhookConfig.enabled]
5886
6064
  ]),
5887
- _createElementVNode("span", null, "启用 Webhook")
6065
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('settings.webhook.enableToggle')), 1 /* TEXT */)
5888
6066
  ])
5889
6067
  ]),
5890
6068
  _createElementVNode("div", { class: "form-group" }, [
5891
- _createElementVNode("label", { class: "form-label" }, "URL"),
6069
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('settings.webhook.urlLabel')), 1 /* TEXT */),
5892
6070
  _withDirectives(_createElementVNode("input", {
5893
6071
  "onUpdate:modelValue": $event => ((_ctx.webhookConfig.url) = $event),
5894
6072
  class: "form-input",
@@ -5901,7 +6079,7 @@ return function render(_ctx, _cache) {
5901
6079
  ])
5902
6080
  ]),
5903
6081
  _createElementVNode("div", { class: "form-group" }, [
5904
- _createElementVNode("label", { class: "form-label" }, "事件"),
6082
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('settings.webhook.eventsLabel')), 1 /* TEXT */),
5905
6083
  _createElementVNode("div", { class: "webhook-events-checkbox-list" }, [
5906
6084
  (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.webhookEventOptions, (ev) => {
5907
6085
  return (_openBlock(), _createElementBlock("label", {
@@ -5922,12 +6100,12 @@ return function render(_ctx, _cache) {
5922
6100
  _createElementVNode("button", {
5923
6101
  class: "btn btn-cancel",
5924
6102
  onClick: _ctx.closeWebhookModal
5925
- }, "取消", 8 /* PROPS */, ["onClick"]),
6103
+ }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"]),
5926
6104
  _createElementVNode("button", {
5927
6105
  class: "btn btn-confirm",
5928
6106
  onClick: _ctx.saveWebhookSettings,
5929
6107
  disabled: _ctx.webhookSaving
5930
- }, _toDisplayString(_ctx.webhookSaving ? '保存中...' : '保存'), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
6108
+ }, _toDisplayString(_ctx.webhookSaving ? _ctx.t('common.saving') : _ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
5931
6109
  ])
5932
6110
  ])
5933
6111
  ], 8 /* PROPS */, ["onClick"]))
@@ -5995,183 +6173,312 @@ return function render(_ctx, _cache) {
5995
6173
  }, _toDisplayString(_ctx.t('common.clear')), 9 /* TEXT, PROPS */, ["onClick"])
5996
6174
  ])
5997
6175
  ]),
5998
- _createElementVNode("div", { class: "quick-steps" }, [
5999
- _createElementVNode("div", { class: "quick-step" }, [
6000
- _createElementVNode("span", { class: "step-badge" }, "1"),
6001
- _createElementVNode("span", null, _toDisplayString(_ctx.t('modal.openclaw.quick.step1')), 1 /* TEXT */)
6002
- ]),
6003
- _createElementVNode("div", { class: "quick-step" }, [
6004
- _createElementVNode("span", { class: "step-badge" }, "2"),
6005
- _createElementVNode("span", null, _toDisplayString(_ctx.t('modal.openclaw.quick.step2')), 1 /* TEXT */)
6006
- ]),
6007
- _createElementVNode("div", { class: "quick-step" }, [
6008
- _createElementVNode("span", { class: "step-badge" }, "3"),
6009
- _createElementVNode("span", null, _toDisplayString(_ctx.t('modal.openclaw.quick.step3')), 1 /* TEXT */)
6010
- ])
6011
- ]),
6012
- _createElementVNode("div", { class: "quick-grid" }, [
6013
- _createElementVNode("div", { class: "quick-card" }, [
6014
- _createElementVNode("div", { class: "structured-card-title" }, "Provider"),
6015
- _createElementVNode("div", { class: "form-group" }, [
6016
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.providerName')), 1 /* TEXT */),
6017
- _withDirectives(_createElementVNode("input", {
6018
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.providerName) = $event),
6019
- class: "form-input",
6020
- placeholder: "例如: custom-myapi"
6021
- }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6022
- [_vModelText, _ctx.openclawQuick.providerName]
6023
- ]),
6024
- _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('modal.openclaw.quick.providerHint')), 1 /* TEXT */)
6025
- ]),
6026
- _createElementVNode("div", { class: "form-group" }, [
6027
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
6028
- _withDirectives(_createElementVNode("input", {
6029
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.baseUrl) = $event),
6030
- class: "form-input",
6031
- placeholder: "https://api.example.com/v1",
6032
- readonly: _ctx.openclawQuick.baseUrlReadOnly
6033
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "readonly"]), [
6034
- [_vModelText, _ctx.openclawQuick.baseUrl]
6176
+ _createCommentVNode(" Accordion Stepper "),
6177
+ _createElementVNode("div", { class: "quick-accordion" }, [
6178
+ _createCommentVNode(" Step 1: Provider "),
6179
+ _createElementVNode("div", {
6180
+ class: _normalizeClass(['accordion-panel', { active: _ctx.openclawAccordionStep === 1, completed: _ctx.openclawAccordionStep > 1 }])
6181
+ }, [
6182
+ _createElementVNode("button", {
6183
+ class: "accordion-trigger",
6184
+ onClick: $event => (_ctx.toggleAccordionStep(1)),
6185
+ type: "button"
6186
+ }, [
6187
+ _createElementVNode("span", { class: "accordion-step-badge" }, [
6188
+ (_ctx.openclawAccordionStep > 1)
6189
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
6190
+ _createTextVNode("")
6191
+ ], 64 /* STABLE_FRAGMENT */))
6192
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
6193
+ _createTextVNode("1")
6194
+ ], 64 /* STABLE_FRAGMENT */))
6035
6195
  ]),
6036
- (_ctx.openclawQuick.baseUrlDisplayKind === 'builtin-default')
6037
- ? (_openBlock(), _createElementBlock("div", {
6196
+ _createElementVNode("span", { class: "accordion-title" }, "Provider"),
6197
+ (_ctx.openclawQuick.providerName)
6198
+ ? (_openBlock(), _createElementBlock("span", {
6038
6199
  key: 0,
6039
- class: "form-hint"
6040
- }, _toDisplayString(_ctx.t('modal.openclaw.quick.baseUrlHintDefault')), 1 /* TEXT */))
6041
- : (_ctx.openclawQuick.baseUrlReadOnly)
6042
- ? (_openBlock(), _createElementBlock("div", {
6043
- key: 1,
6044
- class: "form-hint"
6045
- }, _toDisplayString(_ctx.t('modal.openclaw.quick.baseUrlHintReadonly')), 1 /* TEXT */))
6046
- : _createCommentVNode("v-if", true)
6047
- ]),
6048
- _createElementVNode("div", { class: "form-group" }, [
6049
- _createElementVNode("label", { class: "form-label" }, "API Key"),
6050
- _createElementVNode("div", { class: "list-row" }, [
6200
+ class: "accordion-status"
6201
+ }, _toDisplayString(_ctx.openclawQuick.providerName), 1 /* TEXT */))
6202
+ : _createCommentVNode("v-if", true),
6203
+ (_openBlock(), _createElementBlock("svg", {
6204
+ class: "accordion-chevron",
6205
+ viewBox: "0 0 24 24",
6206
+ fill: "none",
6207
+ stroke: "currentColor",
6208
+ "stroke-width": "2"
6209
+ }, [
6210
+ _createElementVNode("path", { d: "M6 9l6 6 6-6" })
6211
+ ]))
6212
+ ], 8 /* PROPS */, ["onClick"]),
6213
+ _withDirectives(_createElementVNode("div", { class: "accordion-content" }, [
6214
+ _createElementVNode("div", { class: "form-group" }, [
6215
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.providerName')), 1 /* TEXT */),
6051
6216
  _withDirectives(_createElementVNode("input", {
6052
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiKey) = $event),
6217
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.providerName) = $event),
6053
6218
  class: "form-input",
6054
- readonly: _ctx.openclawQuick.apiKeyReadOnly,
6055
- type: (_ctx.openclawQuick.apiKeyReadOnly || _ctx.openclawQuick.showKey) ? 'text' : 'password',
6056
- placeholder: "sk-..."
6057
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "readonly", "type"]), [
6058
- [_vModelDynamic, _ctx.openclawQuick.apiKey]
6219
+ placeholder: "例如: custom-myapi",
6220
+ onInput: _ctx.validateProviderName
6221
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onInput"]), [
6222
+ [_vModelText, _ctx.openclawQuick.providerName]
6059
6223
  ]),
6060
- (!_ctx.openclawQuick.apiKeyReadOnly)
6061
- ? (_openBlock(), _createElementBlock("button", {
6062
- key: 0,
6063
- class: "btn-mini",
6064
- onClick: _ctx.toggleOpenclawQuickKey
6065
- }, _toDisplayString(_ctx.openclawQuick.showKey ? _ctx.t('common.hide') : _ctx.t('common.show')), 9 /* TEXT, PROPS */, ["onClick"]))
6066
- : _createCommentVNode("v-if", true)
6224
+ _createElementVNode("div", {
6225
+ class: _normalizeClass(["form-hint", { 'hint-error': !_ctx.openclawValidation.providerName.valid }])
6226
+ }, _toDisplayString(_ctx.openclawValidation.providerName.message || _ctx.t('modal.openclaw.quick.providerHint')), 3 /* TEXT, CLASS */)
6067
6227
  ]),
6068
- (_ctx.openclawQuick.apiKeyDisplayKind === 'auth-profile-value')
6069
- ? (_openBlock(), _createElementBlock("div", {
6070
- key: 0,
6071
- class: "form-hint"
6072
- }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintFromAuth')), 1 /* TEXT */))
6073
- : (_ctx.openclawQuick.apiKeyReadOnly)
6228
+ _createElementVNode("div", { class: "form-group" }, [
6229
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
6230
+ _withDirectives(_createElementVNode("input", {
6231
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.baseUrl) = $event),
6232
+ class: "form-input",
6233
+ placeholder: "https://api.example.com/v1",
6234
+ readonly: _ctx.openclawQuick.baseUrlReadOnly
6235
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "readonly"]), [
6236
+ [_vModelText, _ctx.openclawQuick.baseUrl]
6237
+ ]),
6238
+ (_ctx.openclawQuick.baseUrlDisplayKind === 'builtin-default')
6074
6239
  ? (_openBlock(), _createElementBlock("div", {
6075
- key: 1,
6240
+ key: 0,
6076
6241
  class: "form-hint"
6077
- }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintReadonly')), 1 /* TEXT */))
6078
- : (_openBlock(), _createElementBlock("div", {
6079
- key: 2,
6242
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.baseUrlHintDefault')), 1 /* TEXT */))
6243
+ : (_ctx.openclawQuick.baseUrlReadOnly)
6244
+ ? (_openBlock(), _createElementBlock("div", {
6245
+ key: 1,
6246
+ class: "form-hint"
6247
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.baseUrlHintReadonly')), 1 /* TEXT */))
6248
+ : _createCommentVNode("v-if", true)
6249
+ ]),
6250
+ _createElementVNode("div", { class: "form-group" }, [
6251
+ _createElementVNode("label", { class: "form-label" }, "API Key"),
6252
+ _createElementVNode("div", { class: "list-row" }, [
6253
+ _withDirectives(_createElementVNode("input", {
6254
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiKey) = $event),
6255
+ class: "form-input",
6256
+ readonly: _ctx.openclawQuick.apiKeyReadOnly,
6257
+ type: (_ctx.openclawQuick.apiKeyReadOnly || _ctx.openclawQuick.showKey) ? 'text' : 'password',
6258
+ placeholder: "sk-..."
6259
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "readonly", "type"]), [
6260
+ [_vModelDynamic, _ctx.openclawQuick.apiKey]
6261
+ ]),
6262
+ (!_ctx.openclawQuick.apiKeyReadOnly)
6263
+ ? (_openBlock(), _createElementBlock("button", {
6264
+ key: 0,
6265
+ class: "btn-mini",
6266
+ onClick: _ctx.toggleOpenclawQuickKey
6267
+ }, _toDisplayString(_ctx.openclawQuick.showKey ? _ctx.t('common.hide') : _ctx.t('common.show')), 9 /* TEXT, PROPS */, ["onClick"]))
6268
+ : _createCommentVNode("v-if", true)
6269
+ ]),
6270
+ (_ctx.openclawQuick.apiKeyDisplayKind === 'auth-profile-value')
6271
+ ? (_openBlock(), _createElementBlock("div", {
6272
+ key: 0,
6080
6273
  class: "form-hint"
6081
- }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintKeep')), 1 /* TEXT */))
6082
- ]),
6083
- _createElementVNode("div", { class: "form-group" }, [
6084
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiType')), 1 /* TEXT */),
6085
- _withDirectives(_createElementVNode("input", {
6086
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiType) = $event),
6087
- class: "form-input",
6088
- list: "openclawApiTypeList",
6089
- placeholder: _ctx.t('placeholder.apiTypeExample')
6090
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6091
- [_vModelText, _ctx.openclawQuick.apiType]
6274
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintFromAuth')), 1 /* TEXT */))
6275
+ : (_ctx.openclawQuick.apiKeyReadOnly)
6276
+ ? (_openBlock(), _createElementBlock("div", {
6277
+ key: 1,
6278
+ class: "form-hint"
6279
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintReadonly')), 1 /* TEXT */))
6280
+ : (_openBlock(), _createElementBlock("div", {
6281
+ key: 2,
6282
+ class: "form-hint"
6283
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintKeep')), 1 /* TEXT */))
6284
+ ]),
6285
+ _createElementVNode("div", { class: "form-group" }, [
6286
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiType')), 1 /* TEXT */),
6287
+ _withDirectives(_createElementVNode("input", {
6288
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiType) = $event),
6289
+ class: "form-input",
6290
+ list: "openclawApiTypeList",
6291
+ placeholder: _ctx.t('placeholder.apiTypeExample')
6292
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6293
+ [_vModelText, _ctx.openclawQuick.apiType]
6294
+ ]),
6295
+ _createElementVNode("datalist", { id: "openclawApiTypeList" }, [
6296
+ _createElementVNode("option", { value: "openai-responses" }),
6297
+ _createElementVNode("option", { value: "openai-chat" }),
6298
+ _createElementVNode("option", { value: "anthropic" }),
6299
+ _createElementVNode("option", { value: "custom" })
6300
+ ])
6092
6301
  ]),
6093
- _createElementVNode("datalist", { id: "openclawApiTypeList" }, [
6094
- _createElementVNode("option", { value: "openai-responses" }),
6095
- _createElementVNode("option", { value: "openai-chat" }),
6096
- _createElementVNode("option", { value: "anthropic" }),
6097
- _createElementVNode("option", { value: "custom" })
6302
+ _createElementVNode("div", { class: "accordion-actions" }, [
6303
+ _createElementVNode("button", {
6304
+ class: "btn btn-confirm btn-sm",
6305
+ onClick: _ctx.nextAccordionStep,
6306
+ disabled: !_ctx.openclawQuick.providerName
6307
+ }, " 下一步 → ", 8 /* PROPS */, ["onClick", "disabled"])
6098
6308
  ])
6309
+ ], 512 /* NEED_PATCH */), [
6310
+ [_vShow, _ctx.openclawAccordionStep === 1]
6099
6311
  ])
6100
- ]),
6101
- _createElementVNode("div", { class: "quick-card" }, [
6102
- _createElementVNode("div", { class: "structured-card-title" }, _toDisplayString(_ctx.t('modal.openclaw.quick.modelTitle')), 1 /* TEXT */),
6103
- _createElementVNode("div", { class: "form-group" }, [
6104
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelId')), 1 /* TEXT */),
6105
- _withDirectives(_createElementVNode("input", {
6106
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.modelId) = $event),
6107
- class: "form-input",
6108
- placeholder: _ctx.t('placeholder.modelIdExample')
6109
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6110
- [_vModelText, _ctx.openclawQuick.modelId]
6111
- ])
6112
- ]),
6113
- _createElementVNode("div", { class: "form-group" }, [
6114
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.displayName')), 1 /* TEXT */),
6115
- _withDirectives(_createElementVNode("input", {
6116
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.modelName) = $event),
6117
- class: "form-input",
6118
- placeholder: _ctx.t('placeholder.modelNameOptional')
6119
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6120
- [_vModelText, _ctx.openclawQuick.modelName]
6121
- ])
6122
- ]),
6123
- _createElementVNode("div", { class: "form-group" }, [
6124
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.contextAndMaxOutput')), 1 /* TEXT */),
6125
- _createElementVNode("div", { class: "list-row" }, [
6312
+ ], 2 /* CLASS */),
6313
+ _createCommentVNode(" Step 2: Model "),
6314
+ _createElementVNode("div", {
6315
+ class: _normalizeClass(['accordion-panel', { active: _ctx.openclawAccordionStep === 2, completed: _ctx.openclawAccordionStep > 2 }])
6316
+ }, [
6317
+ _createElementVNode("button", {
6318
+ class: "accordion-trigger",
6319
+ onClick: $event => (_ctx.toggleAccordionStep(2)),
6320
+ type: "button"
6321
+ }, [
6322
+ _createElementVNode("span", { class: "accordion-step-badge" }, [
6323
+ (_ctx.openclawAccordionStep > 2)
6324
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
6325
+ _createTextVNode("")
6326
+ ], 64 /* STABLE_FRAGMENT */))
6327
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
6328
+ _createTextVNode("2")
6329
+ ], 64 /* STABLE_FRAGMENT */))
6330
+ ]),
6331
+ _createElementVNode("span", { class: "accordion-title" }, _toDisplayString(_ctx.t('modal.openclaw.quick.modelTitle')), 1 /* TEXT */),
6332
+ (_ctx.openclawQuick.modelId)
6333
+ ? (_openBlock(), _createElementBlock("span", {
6334
+ key: 0,
6335
+ class: "accordion-status"
6336
+ }, _toDisplayString(_ctx.openclawQuick.modelName || _ctx.openclawQuick.modelId), 1 /* TEXT */))
6337
+ : _createCommentVNode("v-if", true),
6338
+ (_openBlock(), _createElementBlock("svg", {
6339
+ class: "accordion-chevron",
6340
+ viewBox: "0 0 24 24",
6341
+ fill: "none",
6342
+ stroke: "currentColor",
6343
+ "stroke-width": "2"
6344
+ }, [
6345
+ _createElementVNode("path", { d: "M6 9l6 6 6-6" })
6346
+ ]))
6347
+ ], 8 /* PROPS */, ["onClick"]),
6348
+ _withDirectives(_createElementVNode("div", { class: "accordion-content" }, [
6349
+ _createElementVNode("div", { class: "form-group" }, [
6350
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelId')), 1 /* TEXT */),
6126
6351
  _withDirectives(_createElementVNode("input", {
6127
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.contextWindow) = $event),
6352
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.modelId) = $event),
6128
6353
  class: "form-input",
6129
- placeholder: _ctx.t('field.contextWindow')
6130
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6131
- [_vModelText, _ctx.openclawQuick.contextWindow]
6354
+ placeholder: _ctx.t('placeholder.modelIdExample'),
6355
+ onInput: _ctx.validateModelId
6356
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onInput"]), [
6357
+ [_vModelText, _ctx.openclawQuick.modelId]
6132
6358
  ]),
6359
+ _createElementVNode("div", {
6360
+ class: _normalizeClass(["form-hint", { 'hint-error': !_ctx.openclawValidation.modelId.valid }])
6361
+ }, _toDisplayString(_ctx.openclawValidation.modelId.message || '必填,例如: gpt-4'), 3 /* TEXT, CLASS */)
6362
+ ]),
6363
+ _createElementVNode("div", { class: "form-group" }, [
6364
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.displayName')), 1 /* TEXT */),
6133
6365
  _withDirectives(_createElementVNode("input", {
6134
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.maxTokens) = $event),
6366
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.modelName) = $event),
6135
6367
  class: "form-input",
6136
- placeholder: _ctx.t('field.maxOutput')
6368
+ placeholder: _ctx.t('placeholder.modelNameOptional')
6137
6369
  }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6138
- [_vModelText, _ctx.openclawQuick.maxTokens]
6139
- ])
6370
+ [_vModelText, _ctx.openclawQuick.modelName]
6371
+ ]),
6372
+ _createElementVNode("div", { class: "form-hint" }, "可选,用于显示")
6373
+ ]),
6374
+ _createElementVNode("div", { class: "form-group" }, [
6375
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.contextAndMaxOutput')), 1 /* TEXT */),
6376
+ _createElementVNode("div", { class: "list-row" }, [
6377
+ _withDirectives(_createElementVNode("input", {
6378
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.contextWindow) = $event),
6379
+ class: "form-input",
6380
+ placeholder: _ctx.t('field.contextWindow')
6381
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6382
+ [_vModelText, _ctx.openclawQuick.contextWindow]
6383
+ ]),
6384
+ _withDirectives(_createElementVNode("input", {
6385
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.maxTokens) = $event),
6386
+ class: "form-input",
6387
+ placeholder: _ctx.t('field.maxOutput')
6388
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6389
+ [_vModelText, _ctx.openclawQuick.maxTokens]
6390
+ ])
6391
+ ]),
6392
+ _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('hint.emptyNoChange')), 1 /* TEXT */)
6140
6393
  ]),
6141
- _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('hint.emptyNoChange')), 1 /* TEXT */)
6394
+ _createElementVNode("div", { class: "accordion-actions" }, [
6395
+ _createElementVNode("button", {
6396
+ class: "btn btn-cancel btn-sm",
6397
+ onClick: _ctx.prevAccordionStep
6398
+ }, " ← 上一步 ", 8 /* PROPS */, ["onClick"]),
6399
+ _createElementVNode("button", {
6400
+ class: "btn btn-confirm btn-sm",
6401
+ onClick: _ctx.nextAccordionStep,
6402
+ disabled: !_ctx.openclawQuick.modelId
6403
+ }, " 下一步 → ", 8 /* PROPS */, ["onClick", "disabled"])
6404
+ ])
6405
+ ], 512 /* NEED_PATCH */), [
6406
+ [_vShow, _ctx.openclawAccordionStep === 2]
6142
6407
  ])
6143
- ]),
6144
- _createElementVNode("div", { class: "quick-card" }, [
6145
- _createElementVNode("div", { class: "structured-card-title" }, _toDisplayString(_ctx.t('modal.openclaw.quick.optionsTitle')), 1 /* TEXT */),
6146
- _createElementVNode("label", { class: "quick-option" }, [
6147
- _withDirectives(_createElementVNode("input", {
6148
- type: "checkbox",
6149
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.setPrimary) = $event)
6150
- }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6151
- [_vModelCheckbox, _ctx.openclawQuick.setPrimary]
6408
+ ], 2 /* CLASS */),
6409
+ _createCommentVNode(" Step 3: Options "),
6410
+ _createElementVNode("div", {
6411
+ class: _normalizeClass(['accordion-panel', { active: _ctx.openclawAccordionStep === 3, completed: _ctx.openclawAccordionStep > 3 }])
6412
+ }, [
6413
+ _createElementVNode("button", {
6414
+ class: "accordion-trigger",
6415
+ onClick: $event => (_ctx.toggleAccordionStep(3)),
6416
+ type: "button"
6417
+ }, [
6418
+ _createElementVNode("span", { class: "accordion-step-badge" }, [
6419
+ (_ctx.openclawAccordionStep > 3)
6420
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
6421
+ _createTextVNode("✓")
6422
+ ], 64 /* STABLE_FRAGMENT */))
6423
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
6424
+ _createTextVNode("3")
6425
+ ], 64 /* STABLE_FRAGMENT */))
6152
6426
  ]),
6153
- _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.setPrimary')), 1 /* TEXT */)
6154
- ]),
6155
- _createElementVNode("label", { class: "quick-option" }, [
6156
- _withDirectives(_createElementVNode("input", {
6157
- type: "checkbox",
6158
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.overrideProvider) = $event)
6159
- }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6160
- [_vModelCheckbox, _ctx.openclawQuick.overrideProvider]
6427
+ _createElementVNode("span", { class: "accordion-title" }, _toDisplayString(_ctx.t('modal.openclaw.quick.optionsTitle')), 1 /* TEXT */),
6428
+ _createElementVNode("span", { class: "accordion-status" }, "高级选项"),
6429
+ (_openBlock(), _createElementBlock("svg", {
6430
+ class: "accordion-chevron",
6431
+ viewBox: "0 0 24 24",
6432
+ fill: "none",
6433
+ stroke: "currentColor",
6434
+ "stroke-width": "2"
6435
+ }, [
6436
+ _createElementVNode("path", { d: "M6 9l6 6 6-6" })
6437
+ ]))
6438
+ ], 8 /* PROPS */, ["onClick"]),
6439
+ _withDirectives(_createElementVNode("div", { class: "accordion-content" }, [
6440
+ _createElementVNode("label", { class: "quick-option" }, [
6441
+ _withDirectives(_createElementVNode("input", {
6442
+ type: "checkbox",
6443
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.setPrimary) = $event)
6444
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6445
+ [_vModelCheckbox, _ctx.openclawQuick.setPrimary]
6446
+ ]),
6447
+ _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.setPrimary')), 1 /* TEXT */)
6161
6448
  ]),
6162
- _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.overrideProvider')), 1 /* TEXT */)
6163
- ]),
6164
- _createElementVNode("label", { class: "quick-option" }, [
6165
- _withDirectives(_createElementVNode("input", {
6166
- type: "checkbox",
6167
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.overrideModels) = $event)
6168
- }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6169
- [_vModelCheckbox, _ctx.openclawQuick.overrideModels]
6449
+ _createElementVNode("label", { class: "quick-option" }, [
6450
+ _withDirectives(_createElementVNode("input", {
6451
+ type: "checkbox",
6452
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.overrideProvider) = $event)
6453
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6454
+ [_vModelCheckbox, _ctx.openclawQuick.overrideProvider]
6455
+ ]),
6456
+ _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.overrideProvider')), 1 /* TEXT */)
6170
6457
  ]),
6171
- _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.overrideModels')), 1 /* TEXT */)
6172
- ]),
6173
- _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('modal.openclaw.quick.optionsHint')), 1 /* TEXT */)
6174
- ])
6458
+ _createElementVNode("label", { class: "quick-option" }, [
6459
+ _withDirectives(_createElementVNode("input", {
6460
+ type: "checkbox",
6461
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.overrideModels) = $event)
6462
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6463
+ [_vModelCheckbox, _ctx.openclawQuick.overrideModels]
6464
+ ]),
6465
+ _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.overrideModels')), 1 /* TEXT */)
6466
+ ]),
6467
+ _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('modal.openclaw.quick.optionsHint')), 1 /* TEXT */),
6468
+ _createElementVNode("div", { class: "accordion-actions" }, [
6469
+ _createElementVNode("button", {
6470
+ class: "btn btn-cancel btn-sm",
6471
+ onClick: _ctx.prevAccordionStep
6472
+ }, " ← 上一步 ", 8 /* PROPS */, ["onClick"]),
6473
+ _createElementVNode("button", {
6474
+ class: "btn btn-confirm btn-sm",
6475
+ onClick: _ctx.finishAccordionStep
6476
+ }, " 完成 ✓ ", 8 /* PROPS */, ["onClick"])
6477
+ ])
6478
+ ], 512 /* NEED_PATCH */), [
6479
+ [_vShow, _ctx.openclawAccordionStep === 3]
6480
+ ])
6481
+ ], 2 /* CLASS */)
6175
6482
  ]),
6176
6483
  _createElementVNode("div", { class: "btn-group" }, [
6177
6484
  _createElementVNode("button", {
@@ -6490,7 +6797,7 @@ return function render(_ctx, _cache) {
6490
6797
  [_vModelText, _ctx.openclawEditing.content]
6491
6798
  ]),
6492
6799
  _createElementVNode("div", { class: "template-editor-warning" }, [
6493
- (_ctx.openclawEditing.lockName && _ctx.openclawEditing.name === '默认配置')
6800
+ (_ctx.openclawEditing.lockName && _ctx.isDefaultOpenclawConfig(_ctx.openclawEditing.name))
6494
6801
  ? (_openBlock(), _createElementBlock("span", { key: 0 }, "默认配置始终映射当前 openclaw.json,请直接使用“保存并应用”。"))
6495
6802
  : (_openBlock(), _createElementBlock("span", { key: 1 }, "保存仅写入本地配置库。点击“保存并应用”后会写入 openclaw.json。"))
6496
6803
  ])
@@ -6504,7 +6811,7 @@ return function render(_ctx, _cache) {
6504
6811
  _createElementVNode("button", {
6505
6812
  class: "btn btn-confirm",
6506
6813
  onClick: _ctx.saveOpenclawConfig,
6507
- disabled: _ctx.openclawSaving || _ctx.openclawApplying || (_ctx.openclawEditing.lockName && _ctx.openclawEditing.name === '默认配置')
6814
+ disabled: _ctx.openclawSaving || _ctx.openclawApplying || (_ctx.openclawEditing.lockName && _ctx.isDefaultOpenclawConfig(_ctx.openclawEditing.name))
6508
6815
  }, _toDisplayString(_ctx.openclawSaving ? '保存中...' : '保存'), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
6509
6816
  _createElementVNode("button", {
6510
6817
  class: "btn btn-confirm secondary",