codexmate 0.0.38 → 0.0.40

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 (43) hide show
  1. package/cli/builtin-proxy.js +626 -207
  2. package/cli/config-bootstrap.js +6 -1
  3. package/cli/openai-bridge.js +541 -210
  4. package/cli.js +189 -4
  5. package/package.json +1 -1
  6. package/plugins/prompt-templates/computed.mjs +61 -3
  7. package/plugins/prompt-templates/manifest.mjs +3 -0
  8. package/web-ui/app.js +14 -3
  9. package/web-ui/modules/app.computed.main-tabs.mjs +39 -30
  10. package/web-ui/modules/app.methods.claude-config.mjs +111 -9
  11. package/web-ui/modules/app.methods.index.mjs +2 -0
  12. package/web-ui/modules/app.methods.openclaw-editing.mjs +48 -0
  13. package/web-ui/modules/app.methods.openclaw-persist.mjs +13 -7
  14. package/web-ui/modules/app.methods.providers.mjs +36 -10
  15. package/web-ui/modules/app.methods.runtime.mjs +76 -1
  16. package/web-ui/modules/app.methods.startup-claude.mjs +7 -0
  17. package/web-ui/modules/app.methods.tool-config-permissions.mjs +87 -0
  18. package/web-ui/modules/config-mode.computed.mjs +3 -3
  19. package/web-ui/modules/i18n/locales/en.mjs +1140 -0
  20. package/web-ui/modules/i18n/locales/ja.mjs +1130 -0
  21. package/web-ui/modules/i18n/locales/vi.mjs +239 -0
  22. package/web-ui/modules/i18n/locales/zh.mjs +1143 -0
  23. package/web-ui/modules/i18n.dict.mjs +9 -3195
  24. package/web-ui/modules/i18n.mjs +65 -16
  25. package/web-ui/partials/index/layout-header.html +16 -46
  26. package/web-ui/partials/index/modal-openclaw-config.html +135 -71
  27. package/web-ui/partials/index/modal-webhook.html +8 -8
  28. package/web-ui/partials/index/modals-basic.html +56 -16
  29. package/web-ui/partials/index/panel-config-claude.html +51 -21
  30. package/web-ui/partials/index/panel-config-codex.html +34 -5
  31. package/web-ui/partials/index/panel-config-openclaw.html +70 -64
  32. package/web-ui/partials/index/panel-dashboard.html +62 -77
  33. package/web-ui/partials/index/panel-settings.html +28 -7
  34. package/web-ui/partials/index/panel-trash.html +14 -14
  35. package/web-ui/res/web-ui-render.precompiled.js +1783 -1386
  36. package/web-ui/styles/controls-forms.css +99 -0
  37. package/web-ui/styles/dashboard.css +46 -14
  38. package/web-ui/styles/layout-shell.css +45 -0
  39. package/web-ui/styles/navigation-panels.css +3 -3
  40. package/web-ui/styles/openclaw-structured.css +383 -33
  41. package/web-ui/styles/responsive.css +68 -0
  42. package/web-ui/styles/sessions-usage.css +105 -9
  43. package/web-ui/styles/settings-panel.css +4 -0
@@ -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']
@@ -1006,483 +947,449 @@ return function render(_ctx, _cache) {
1006
947
  ])
1007
948
  ]))
1008
949
  : (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [
1009
- (!_ctx.loading && !_ctx.initError)
1010
- ? (_openBlock(), _createElementBlock("button", {
1011
- key: 0,
1012
- class: "btn-add",
1013
- onClick: $event => (_ctx.showAddModal = true)
1014
- }, [
1015
- (_openBlock(), _createElementBlock("svg", {
1016
- class: "icon",
1017
- viewBox: "0 0 20 20",
1018
- fill: "none",
1019
- stroke: "currentColor",
1020
- "stroke-width": "2"
1021
- }, [
1022
- _createElementVNode("path", { d: "M10 4v12M4 10h12" })
1023
- ])),
1024
- _createTextVNode(" " + _toDisplayString(_ctx.t('config.addProvider')), 1 /* TEXT */)
1025
- ], 8 /* PROPS */, ["onClick"]))
1026
- : _createCommentVNode("v-if", true),
1027
- (_ctx.isCodexConfigMode && _ctx.codexProviderTemplates.length)
1028
- ? (_openBlock(), _createElementBlock("div", {
1029
- key: 1,
1030
- class: "selector-section"
1031
- }, [
950
+ _createElementVNode("section", {
951
+ class: "tool-config-write-card",
952
+ "aria-label": _ctx.t('toolConfig.codex.title')
953
+ }, [
954
+ _createElementVNode("div", { class: "tool-config-write-copy" }, [
955
+ _createElementVNode("div", { class: "tool-config-write-title" }, _toDisplayString(_ctx.t('toolConfig.codex.title')), 1 /* TEXT */),
956
+ _createElementVNode("p", { class: "tool-config-write-desc" }, _toDisplayString(_ctx.t('toolConfig.codex.desc')), 1 /* TEXT */)
957
+ ]),
958
+ _createElementVNode("label", { class: "settings-toggle-row tool-config-write-toggle" }, [
959
+ _createElementVNode("input", {
960
+ type: "checkbox",
961
+ checked: _ctx.isToolConfigWriteAllowed('codex'),
962
+ disabled: _ctx.toolConfigPermissionSaving.codex,
963
+ onChange: $event => (_ctx.setToolConfigPermission('codex', $event.target.checked))
964
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["checked", "disabled", "onChange"]),
965
+ _createElementVNode("span", { class: "toggle-track" }, [
966
+ _createElementVNode("span", { class: "toggle-thumb" })
967
+ ]),
968
+ _createElementVNode("span", null, _toDisplayString(_ctx.toolConfigPermissionStatusLabel('codex')), 1 /* TEXT */)
969
+ ])
970
+ ], 8 /* PROPS */, ["aria-label"]),
971
+ _createElementVNode("div", {
972
+ class: _normalizeClass(["tool-config-write-scope", { locked: !_ctx.isToolConfigWriteAllowed('codex') }])
973
+ }, [
974
+ _createElementVNode("div", { class: "tool-config-write-body" }, [
975
+ (!_ctx.loading && !_ctx.initError)
976
+ ? (_openBlock(), _createElementBlock("button", {
977
+ key: 0,
978
+ class: "btn-add",
979
+ onClick: $event => {_ctx.showAddProviderKey = false; _ctx.showAddModal = true},
980
+ disabled: !_ctx.isToolConfigWriteAllowed('codex')
981
+ }, [
982
+ (_openBlock(), _createElementBlock("svg", {
983
+ class: "icon",
984
+ viewBox: "0 0 20 20",
985
+ fill: "none",
986
+ stroke: "currentColor",
987
+ "stroke-width": "2"
988
+ }, [
989
+ _createElementVNode("path", { d: "M10 4v12M4 10h12" })
990
+ ])),
991
+ _createTextVNode(" " + _toDisplayString(_ctx.t('config.addProvider')), 1 /* TEXT */)
992
+ ], 8 /* PROPS */, ["onClick", "disabled"]))
993
+ : _createCommentVNode("v-if", true),
994
+ (_ctx.isCodexConfigMode && _ctx.codexProviderTemplates.length)
995
+ ? (_openBlock(), _createElementBlock("div", {
996
+ key: 1,
997
+ class: "selector-section"
998
+ }, [
999
+ _createElementVNode("div", { class: "selector-header" }, [
1000
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.providerTemplate.title')), 1 /* TEXT */)
1001
+ ]),
1002
+ _createElementVNode("div", {
1003
+ class: "btn-group",
1004
+ style: {"flex-wrap":"wrap","gap":"8px","margin-top":"0"}
1005
+ }, [
1006
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.codexProviderTemplates, (tpl) => {
1007
+ return (_openBlock(), _createElementBlock("button", {
1008
+ key: tpl.name,
1009
+ type: "button",
1010
+ class: "btn-mini",
1011
+ 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}
1012
+ }, _toDisplayString(tpl.label), 9 /* TEXT, PROPS */, ["onClick"]))
1013
+ }), 128 /* KEYED_FRAGMENT */))
1014
+ ])
1015
+ ]))
1016
+ : _createCommentVNode("v-if", true),
1017
+ _createElementVNode("div", { class: "selector-section" }, [
1032
1018
  _createElementVNode("div", { class: "selector-header" }, [
1033
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.providerTemplate.title')), 1 /* TEXT */)
1019
+ _createElementVNode("span", { class: "selector-title" }, "AGENTS.md")
1034
1020
  ]),
1035
- _createElementVNode("div", {
1036
- class: "btn-group",
1037
- style: {"flex-wrap":"wrap","gap":"8px","margin-top":"0"}
1038
- }, [
1039
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.codexProviderTemplates, (tpl) => {
1040
- return (_openBlock(), _createElementBlock("button", {
1041
- key: tpl.name,
1042
- type: "button",
1043
- 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}
1045
- }, _toDisplayString(tpl.label), 9 /* TEXT, PROPS */, ["onClick"]))
1046
- }), 128 /* KEYED_FRAGMENT */))
1047
- ])
1048
- ]))
1049
- : _createCommentVNode("v-if", true),
1050
- _createElementVNode("div", { class: "selector-section" }, [
1051
- _createElementVNode("div", { class: "selector-header" }, [
1052
- _createElementVNode("span", { class: "selector-title" }, "AGENTS.md")
1053
- ]),
1054
- _createElementVNode("button", {
1055
- class: "btn-tool",
1056
- onClick: _ctx.openAgentsEditor,
1057
- disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
1058
- }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('config.agents.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1059
- ]),
1060
- _createElementVNode("div", { class: "selector-section" }, [
1061
- _createElementVNode("div", { class: "selector-header" }, [
1062
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.models')), 1 /* TEXT */),
1063
- _createElementVNode("div", { class: "selector-actions" }, [
1064
- (_ctx.modelsSource === 'legacy')
1065
- ? (_openBlock(), _createElementBlock("button", {
1021
+ _createElementVNode("button", {
1022
+ class: "btn-tool",
1023
+ onClick: _ctx.openAgentsEditor,
1024
+ disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
1025
+ }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('config.agents.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1026
+ ]),
1027
+ _createElementVNode("div", { class: "selector-section" }, [
1028
+ _createElementVNode("div", { class: "selector-header" }, [
1029
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.models')), 1 /* TEXT */),
1030
+ _createElementVNode("div", { class: "selector-actions" }, [
1031
+ (_ctx.modelsSource === 'legacy')
1032
+ ? (_openBlock(), _createElementBlock("button", {
1033
+ key: 0,
1034
+ class: "btn-icon",
1035
+ onClick: $event => (_ctx.showModelModal = true),
1036
+ "aria-label": _ctx.t('modal.modelAdd.title'),
1037
+ title: _ctx.t('modal.modelAdd.title')
1038
+ }, "+", 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1039
+ : _createCommentVNode("v-if", true),
1040
+ (_ctx.modelsSource === 'legacy')
1041
+ ? (_openBlock(), _createElementBlock("button", {
1042
+ key: 1,
1043
+ class: "btn-icon",
1044
+ onClick: $event => (_ctx.showModelListModal = true),
1045
+ "aria-label": _ctx.t('modal.modelManage.title'),
1046
+ title: _ctx.t('modal.modelManage.title')
1047
+ }, "", 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1048
+ : _createCommentVNode("v-if", true)
1049
+ ])
1050
+ ]),
1051
+ (_ctx.codexModelsLoading || _ctx.modelsSource === 'remote')
1052
+ ? _withDirectives((_openBlock(), _createElementBlock("select", {
1066
1053
  key: 0,
1067
- class: "btn-icon",
1068
- onClick: $event => (_ctx.showModelModal = true),
1069
- "aria-label": _ctx.t('modal.modelAdd.title'),
1070
- title: _ctx.t('modal.modelAdd.title')
1071
- }, "+", 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1054
+ class: "model-select",
1055
+ "onUpdate:modelValue": $event => ((_ctx.currentModel) = $event),
1056
+ onChange: _ctx.onModelChange,
1057
+ disabled: _ctx.codexModelsLoading
1058
+ }, [
1059
+ (_ctx.codexModelsLoading)
1060
+ ? (_openBlock(), _createElementBlock("option", {
1061
+ key: 0,
1062
+ value: ""
1063
+ }, _toDisplayString(_ctx.t('config.modelLoading')), 1 /* TEXT */))
1064
+ : (_openBlock(true), _createElementBlock(_Fragment, { key: 1 }, _renderList(_ctx.codexModelOptions, (model) => {
1065
+ return (_openBlock(), _createElementBlock("option", {
1066
+ key: model,
1067
+ value: model
1068
+ }, _toDisplayString(model), 9 /* TEXT, PROPS */, ["value"]))
1069
+ }), 128 /* KEYED_FRAGMENT */))
1070
+ ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange", "disabled"])), [
1071
+ [_vModelSelect, _ctx.currentModel]
1072
+ ])
1072
1073
  : _createCommentVNode("v-if", true),
1073
- (_ctx.modelsSource === 'legacy')
1074
- ? (_openBlock(), _createElementBlock("button", {
1074
+ (!_ctx.codexModelsLoading && (_ctx.modelsSource !== 'remote' || !_ctx.modelsHasCurrent))
1075
+ ? _withDirectives((_openBlock(), _createElementBlock("input", {
1075
1076
  key: 1,
1076
- class: "btn-icon",
1077
- onClick: $event => (_ctx.showModelListModal = true),
1078
- "aria-label": _ctx.t('modal.modelManage.title'),
1079
- title: _ctx.t('modal.modelManage.title')
1080
- }, "≡", 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1081
- : _createCommentVNode("v-if", true)
1082
- ])
1083
- ]),
1084
- (_ctx.codexModelsLoading || _ctx.modelsSource === 'remote')
1085
- ? _withDirectives((_openBlock(), _createElementBlock("select", {
1086
- key: 0,
1087
- class: "model-select",
1088
- "onUpdate:modelValue": $event => ((_ctx.currentModel) = $event),
1089
- onChange: _ctx.onModelChange,
1090
- disabled: _ctx.codexModelsLoading
1091
- }, [
1092
- (_ctx.codexModelsLoading)
1093
- ? (_openBlock(), _createElementBlock("option", {
1094
- key: 0,
1095
- value: ""
1096
- }, _toDisplayString(_ctx.t('config.modelLoading')), 1 /* TEXT */))
1097
- : (_openBlock(true), _createElementBlock(_Fragment, { key: 1 }, _renderList(_ctx.codexModelOptions, (model) => {
1077
+ class: "model-input",
1078
+ "onUpdate:modelValue": $event => ((_ctx.currentModel) = $event),
1079
+ onBlur: _ctx.onModelChange,
1080
+ onKeyup: _withKeys(_ctx.onModelChange, ["enter"]),
1081
+ placeholder: _ctx.activeProviderModelPlaceholder,
1082
+ list: _ctx.codexModelHasList ? 'codex-model-options' : null
1083
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onBlur", "onKeyup", "placeholder", "list"])), [
1084
+ [_vModelText, _ctx.currentModel]
1085
+ ])
1086
+ : _createCommentVNode("v-if", true),
1087
+ (_ctx.codexModelHasList)
1088
+ ? (_openBlock(), _createElementBlock("datalist", {
1089
+ key: 2,
1090
+ id: "codex-model-options"
1091
+ }, [
1092
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.codexModelOptions, (model) => {
1098
1093
  return (_openBlock(), _createElementBlock("option", {
1099
1094
  key: model,
1100
1095
  value: model
1101
- }, _toDisplayString(model), 9 /* TEXT, PROPS */, ["value"]))
1096
+ }, null, 8 /* PROPS */, ["value"]))
1102
1097
  }), 128 /* KEYED_FRAGMENT */))
1103
- ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange", "disabled"])), [
1104
- [_vModelSelect, _ctx.currentModel]
1105
- ])
1106
- : _createCommentVNode("v-if", true),
1107
- (!_ctx.codexModelsLoading && (_ctx.modelsSource !== 'remote' || !_ctx.modelsHasCurrent))
1108
- ? _withDirectives((_openBlock(), _createElementBlock("input", {
1109
- key: 1,
1110
- class: "model-input",
1111
- "onUpdate:modelValue": $event => ((_ctx.currentModel) = $event),
1112
- onBlur: _ctx.onModelChange,
1113
- onKeyup: _withKeys(_ctx.onModelChange, ["enter"]),
1114
- placeholder: _ctx.activeProviderModelPlaceholder,
1115
- list: _ctx.codexModelHasList ? 'codex-model-options' : null
1116
- }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onBlur", "onKeyup", "placeholder", "list"])), [
1117
- [_vModelText, _ctx.currentModel]
1118
- ])
1119
- : _createCommentVNode("v-if", true),
1120
- (_ctx.codexModelHasList)
1121
- ? (_openBlock(), _createElementBlock("datalist", {
1122
- key: 2,
1123
- id: "codex-model-options"
1124
- }, [
1125
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.codexModelOptions, (model) => {
1126
- return (_openBlock(), _createElementBlock("option", {
1127
- key: model,
1128
- value: model
1129
- }, null, 8 /* PROPS */, ["value"]))
1130
- }), 128 /* KEYED_FRAGMENT */))
1131
- ]))
1132
- : _createCommentVNode("v-if", true),
1133
- (_ctx.modelsSource === 'unlimited')
1134
- ? (_openBlock(), _createElementBlock("div", {
1135
- key: 3,
1136
- class: "config-template-hint"
1137
- }, _toDisplayString(_ctx.t('config.models.unlimited')), 1 /* TEXT */))
1138
- : _createCommentVNode("v-if", true),
1139
- (_ctx.modelsSource === 'error')
1140
- ? (_openBlock(), _createElementBlock("div", {
1141
- key: 4,
1142
- class: "config-template-hint"
1143
- }, _toDisplayString(_ctx.t('config.models.error')), 1 /* TEXT */))
1144
- : _createCommentVNode("v-if", true),
1145
- (_ctx.modelsSource === 'remote' && !_ctx.modelsHasCurrent)
1146
- ? (_openBlock(), _createElementBlock("div", {
1147
- key: 5,
1148
- class: "config-template-hint"
1149
- }, _toDisplayString(_ctx.isCodexConfigMode ? _ctx.t('config.models.notInList.codex') : _ctx.t('config.models.notInList.other')), 1 /* TEXT */))
1150
- : _createCommentVNode("v-if", true),
1151
- (_ctx.isCodexConfigMode)
1152
- ? (_openBlock(), _createElementBlock("div", {
1153
- key: 6,
1154
- class: "config-template-hint"
1155
- }, _toDisplayString(_ctx.t('config.template.editFirst')), 1 /* TEXT */))
1156
- : (_ctx.activeProviderBridgeHint)
1157
- ? (_openBlock(), _createElementBlock("div", {
1158
- key: 7,
1159
- class: "config-template-hint"
1160
- }, _toDisplayString(_ctx.t('config.template.bridgeCodexOnly', { hint: _ctx.activeProviderBridgeHint })), 1 /* TEXT */))
1161
- : _createCommentVNode("v-if", true),
1162
- (_ctx.isCodexConfigMode)
1163
- ? (_openBlock(), _createElementBlock("button", {
1164
- key: 8,
1165
- class: "btn-tool btn-template-editor",
1166
- onClick: _ctx.openConfigTemplateEditor,
1167
- disabled: _ctx.loading || !!_ctx.initError
1168
- }, _toDisplayString(_ctx.t('config.template.openEditor')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]))
1169
- : _createCommentVNode("v-if", true)
1170
- ]),
1171
- (_ctx.isCodexConfigMode)
1172
- ? (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [
1173
- _createElementVNode("div", { class: "config-row" }, [
1174
- _createElementVNode("div", {
1175
- class: "selector-section",
1176
- style: {"flex":"1"}
1177
- }, [
1178
- _createElementVNode("div", { class: "selector-header" }, [
1179
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.serviceTier')), 1 /* TEXT */)
1180
- ]),
1181
- _withDirectives(_createElementVNode("select", {
1182
- class: "model-select",
1183
- "onUpdate:modelValue": $event => ((_ctx.serviceTier) = $event),
1184
- onChange: _ctx.onServiceTierChange
1185
- }, [
1186
- _createElementVNode("option", { value: "fast" }, _toDisplayString(_ctx.t('config.serviceTier.fast')), 1 /* TEXT */),
1187
- _createElementVNode("option", { value: "standard" }, _toDisplayString(_ctx.t('config.serviceTier.standard')), 1 /* TEXT */)
1188
- ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange"]), [
1189
- [_vModelSelect, _ctx.serviceTier]
1190
- ]),
1191
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.serviceTier.hint', { field: 'service_tier' })), 1 /* TEXT */)
1192
- ]),
1193
- _createElementVNode("div", {
1194
- class: "selector-section",
1195
- style: {"flex":"1"}
1196
- }, [
1197
- _createElementVNode("div", { class: "selector-header" }, [
1198
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.reasoningEffort')), 1 /* TEXT */)
1199
- ]),
1200
- _withDirectives(_createElementVNode("select", {
1201
- class: "model-select",
1202
- "onUpdate:modelValue": $event => ((_ctx.modelReasoningEffort) = $event),
1203
- onChange: _ctx.onReasoningEffortChange
1204
- }, [
1205
- _createElementVNode("option", { value: "high" }, "high"),
1206
- _createElementVNode("option", { value: "medium" }, _toDisplayString(_ctx.t('config.reasoningEffort.medium')), 1 /* TEXT */),
1207
- _createElementVNode("option", { value: "low" }, "low"),
1208
- _createElementVNode("option", { value: "xhigh" }, "xhigh")
1209
- ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange"]), [
1210
- [_vModelSelect, _ctx.modelReasoningEffort]
1098
+ ]))
1099
+ : _createCommentVNode("v-if", true),
1100
+ (_ctx.modelsSource === 'unlimited')
1101
+ ? (_openBlock(), _createElementBlock("div", {
1102
+ key: 3,
1103
+ class: "config-template-hint"
1104
+ }, _toDisplayString(_ctx.t('config.models.unlimited')), 1 /* TEXT */))
1105
+ : _createCommentVNode("v-if", true),
1106
+ (_ctx.modelsSource === 'error')
1107
+ ? (_openBlock(), _createElementBlock("div", {
1108
+ key: 4,
1109
+ class: "config-template-hint"
1110
+ }, _toDisplayString(_ctx.t('config.models.error')), 1 /* TEXT */))
1111
+ : _createCommentVNode("v-if", true),
1112
+ (_ctx.modelsSource === 'remote' && !_ctx.modelsHasCurrent)
1113
+ ? (_openBlock(), _createElementBlock("div", {
1114
+ key: 5,
1115
+ class: "config-template-hint"
1116
+ }, _toDisplayString(_ctx.isCodexConfigMode ? _ctx.t('config.models.notInList.codex') : _ctx.t('config.models.notInList.other')), 1 /* TEXT */))
1117
+ : _createCommentVNode("v-if", true),
1118
+ (_ctx.isCodexConfigMode)
1119
+ ? (_openBlock(), _createElementBlock("div", {
1120
+ key: 6,
1121
+ class: "config-template-hint"
1122
+ }, _toDisplayString(_ctx.t('config.template.editFirst')), 1 /* TEXT */))
1123
+ : (_ctx.activeProviderBridgeHint)
1124
+ ? (_openBlock(), _createElementBlock("div", {
1125
+ key: 7,
1126
+ class: "config-template-hint"
1127
+ }, _toDisplayString(_ctx.t('config.template.bridgeCodexOnly', { hint: _ctx.activeProviderBridgeHint })), 1 /* TEXT */))
1128
+ : _createCommentVNode("v-if", true),
1129
+ (_ctx.isCodexConfigMode)
1130
+ ? (_openBlock(), _createElementBlock("button", {
1131
+ key: 8,
1132
+ class: "btn-tool btn-template-editor",
1133
+ onClick: _ctx.openConfigTemplateEditor,
1134
+ disabled: _ctx.loading || !!_ctx.initError
1135
+ }, _toDisplayString(_ctx.t('config.template.openEditor')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]))
1136
+ : _createCommentVNode("v-if", true)
1137
+ ]),
1138
+ (_ctx.isCodexConfigMode)
1139
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [
1140
+ _createElementVNode("div", { class: "config-row" }, [
1141
+ _createElementVNode("div", {
1142
+ class: "selector-section",
1143
+ style: {"flex":"1"}
1144
+ }, [
1145
+ _createElementVNode("div", { class: "selector-header" }, [
1146
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.serviceTier')), 1 /* TEXT */)
1147
+ ]),
1148
+ _withDirectives(_createElementVNode("select", {
1149
+ class: "model-select",
1150
+ "onUpdate:modelValue": $event => ((_ctx.serviceTier) = $event),
1151
+ onChange: _ctx.onServiceTierChange
1152
+ }, [
1153
+ _createElementVNode("option", { value: "fast" }, _toDisplayString(_ctx.t('config.serviceTier.fast')), 1 /* TEXT */),
1154
+ _createElementVNode("option", { value: "standard" }, _toDisplayString(_ctx.t('config.serviceTier.standard')), 1 /* TEXT */)
1155
+ ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange"]), [
1156
+ [_vModelSelect, _ctx.serviceTier]
1157
+ ]),
1158
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.serviceTier.hint', { field: 'service_tier' })), 1 /* TEXT */)
1159
+ ]),
1160
+ _createElementVNode("div", {
1161
+ class: "selector-section",
1162
+ style: {"flex":"1"}
1163
+ }, [
1164
+ _createElementVNode("div", { class: "selector-header" }, [
1165
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.reasoningEffort')), 1 /* TEXT */)
1166
+ ]),
1167
+ _withDirectives(_createElementVNode("select", {
1168
+ class: "model-select",
1169
+ "onUpdate:modelValue": $event => ((_ctx.modelReasoningEffort) = $event),
1170
+ onChange: _ctx.onReasoningEffortChange
1171
+ }, [
1172
+ _createElementVNode("option", { value: "high" }, "high"),
1173
+ _createElementVNode("option", { value: "medium" }, _toDisplayString(_ctx.t('config.reasoningEffort.medium')), 1 /* TEXT */),
1174
+ _createElementVNode("option", { value: "low" }, "low"),
1175
+ _createElementVNode("option", { value: "xhigh" }, "xhigh")
1176
+ ], 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange"]), [
1177
+ [_vModelSelect, _ctx.modelReasoningEffort]
1178
+ ]),
1179
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.reasoningEffort.hint')), 1 /* TEXT */)
1180
+ ])
1211
1181
  ]),
1212
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.reasoningEffort.hint')), 1 /* TEXT */)
1213
- ])
1214
- ]),
1215
- _createElementVNode("div", { class: "selector-section" }, [
1216
- _createElementVNode("div", { class: "selector-header" }, [
1217
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.contextBudget')), 1 /* TEXT */),
1218
- _createElementVNode("div", { class: "selector-actions" }, [
1219
- _createElementVNode("button", {
1220
- class: "btn-tool btn-tool-compact",
1221
- onClick: _ctx.resetCodexContextBudgetDefaults,
1222
- disabled: _ctx.loading || !!_ctx.initError || _ctx.codexApplying
1223
- }, _toDisplayString(_ctx.t('config.reset')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1224
- ])
1225
- ]),
1226
- _createElementVNode("div", { class: "codex-config-grid" }, [
1227
- _createElementVNode("div", { class: "form-group codex-config-field" }, [
1228
- _createElementVNode("label", {
1229
- class: "form-label",
1230
- for: "codex-model-context-window"
1231
- }, "model_context_window"),
1232
- _withDirectives(_createElementVNode("input", {
1233
- id: "codex-model-context-window",
1234
- "onUpdate:modelValue": $event => ((_ctx.modelContextWindowInput) = $event),
1235
- class: "form-input",
1236
- inputmode: "numeric",
1237
- autocomplete: "off",
1238
- placeholder: _ctx.t('config.example', { value: 190000 }),
1239
- onFocus: $event => (_ctx.editingCodexBudgetField = 'modelContextWindowInput'),
1240
- onInput: $event => (_ctx.sanitizePositiveIntegerDraft('modelContextWindowInput')),
1241
- onBlur: _ctx.onModelContextWindowBlur,
1242
- onKeydown: _withKeys(_withModifiers(_ctx.onModelContextWindowBlur, ["prevent"]), ["enter"])
1243
- }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onFocus", "onInput", "onBlur", "onKeydown"]), [
1244
- [_vModelText, _ctx.modelContextWindowInput]
1182
+ _createElementVNode("div", { class: "selector-section" }, [
1183
+ _createElementVNode("div", { class: "selector-header" }, [
1184
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.contextBudget')), 1 /* TEXT */),
1185
+ _createElementVNode("div", { class: "selector-actions" }, [
1186
+ _createElementVNode("button", {
1187
+ class: "btn-tool btn-tool-compact",
1188
+ onClick: _ctx.resetCodexContextBudgetDefaults,
1189
+ disabled: _ctx.loading || !!_ctx.initError || _ctx.codexApplying
1190
+ }, _toDisplayString(_ctx.t('config.reset')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1191
+ ])
1245
1192
  ]),
1246
- _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('config.contextWindow.hint')), 1 /* TEXT */)
1193
+ _createElementVNode("div", { class: "codex-config-grid" }, [
1194
+ _createElementVNode("div", { class: "form-group codex-config-field" }, [
1195
+ _createElementVNode("label", {
1196
+ class: "form-label",
1197
+ for: "codex-model-context-window"
1198
+ }, "model_context_window"),
1199
+ _withDirectives(_createElementVNode("input", {
1200
+ id: "codex-model-context-window",
1201
+ "onUpdate:modelValue": $event => ((_ctx.modelContextWindowInput) = $event),
1202
+ class: "form-input",
1203
+ inputmode: "numeric",
1204
+ autocomplete: "off",
1205
+ placeholder: _ctx.t('config.example', { value: 190000 }),
1206
+ onFocus: $event => (_ctx.editingCodexBudgetField = 'modelContextWindowInput'),
1207
+ onInput: $event => (_ctx.sanitizePositiveIntegerDraft('modelContextWindowInput')),
1208
+ onBlur: _ctx.onModelContextWindowBlur,
1209
+ onKeydown: _withKeys(_withModifiers(_ctx.onModelContextWindowBlur, ["prevent"]), ["enter"])
1210
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onFocus", "onInput", "onBlur", "onKeydown"]), [
1211
+ [_vModelText, _ctx.modelContextWindowInput]
1212
+ ]),
1213
+ _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('config.contextWindow.hint')), 1 /* TEXT */)
1214
+ ]),
1215
+ _createElementVNode("div", { class: "form-group codex-config-field" }, [
1216
+ _createElementVNode("label", {
1217
+ class: "form-label",
1218
+ for: "codex-model-auto-compact-token-limit"
1219
+ }, "model_auto_compact_token_limit"),
1220
+ _withDirectives(_createElementVNode("input", {
1221
+ id: "codex-model-auto-compact-token-limit",
1222
+ "onUpdate:modelValue": $event => ((_ctx.modelAutoCompactTokenLimitInput) = $event),
1223
+ class: "form-input",
1224
+ inputmode: "numeric",
1225
+ autocomplete: "off",
1226
+ placeholder: _ctx.t('config.example', { value: 185000 }),
1227
+ onFocus: $event => (_ctx.editingCodexBudgetField = 'modelAutoCompactTokenLimitInput'),
1228
+ onInput: $event => (_ctx.sanitizePositiveIntegerDraft('modelAutoCompactTokenLimitInput')),
1229
+ onBlur: _ctx.onModelAutoCompactTokenLimitBlur,
1230
+ onKeydown: _withKeys(_withModifiers(_ctx.onModelAutoCompactTokenLimitBlur, ["prevent"]), ["enter"])
1231
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onFocus", "onInput", "onBlur", "onKeydown"]), [
1232
+ [_vModelText, _ctx.modelAutoCompactTokenLimitInput]
1233
+ ]),
1234
+ _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('config.autoCompact.hint')), 1 /* TEXT */)
1235
+ ])
1236
+ ])
1247
1237
  ]),
1248
- _createElementVNode("div", { class: "form-group codex-config-field" }, [
1249
- _createElementVNode("label", {
1250
- class: "form-label",
1251
- for: "codex-model-auto-compact-token-limit"
1252
- }, "model_auto_compact_token_limit"),
1253
- _withDirectives(_createElementVNode("input", {
1254
- id: "codex-model-auto-compact-token-limit",
1255
- "onUpdate:modelValue": $event => ((_ctx.modelAutoCompactTokenLimitInput) = $event),
1256
- class: "form-input",
1257
- inputmode: "numeric",
1258
- autocomplete: "off",
1259
- placeholder: _ctx.t('config.example', { value: 185000 }),
1260
- onFocus: $event => (_ctx.editingCodexBudgetField = 'modelAutoCompactTokenLimitInput'),
1261
- onInput: $event => (_ctx.sanitizePositiveIntegerDraft('modelAutoCompactTokenLimitInput')),
1262
- onBlur: _ctx.onModelAutoCompactTokenLimitBlur,
1263
- onKeydown: _withKeys(_withModifiers(_ctx.onModelAutoCompactTokenLimitBlur, ["prevent"]), ["enter"])
1264
- }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onFocus", "onInput", "onBlur", "onKeydown"]), [
1265
- [_vModelText, _ctx.modelAutoCompactTokenLimitInput]
1238
+ _createElementVNode("div", { class: "selector-section" }, [
1239
+ _createElementVNode("div", { class: "selector-header" }, [
1240
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.health.title')), 1 /* TEXT */)
1266
1241
  ]),
1267
- _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('config.autoCompact.hint')), 1 /* TEXT */)
1242
+ _createElementVNode("button", {
1243
+ class: "btn-tool",
1244
+ onClick: _ctx.runHealthCheck,
1245
+ disabled: _ctx.healthCheckLoading || _ctx.loading || !!_ctx.initError
1246
+ }, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('config.health.running') : _ctx.t('config.health.run')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1247
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.health.hint')), 1 /* TEXT */)
1268
1248
  ])
1269
- ])
1270
- ]),
1271
- _createElementVNode("div", { class: "selector-section" }, [
1272
- _createElementVNode("div", { class: "selector-header" }, [
1273
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.health.title')), 1 /* TEXT */)
1274
- ]),
1275
- _createElementVNode("button", {
1276
- class: "btn-tool",
1277
- onClick: _ctx.runHealthCheck,
1278
- disabled: _ctx.healthCheckLoading || _ctx.loading || !!_ctx.initError
1279
- }, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('config.health.running') : _ctx.t('config.health.run')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1280
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.health.hint')), 1 /* TEXT */)
1281
- ])
1282
- ], 64 /* STABLE_FRAGMENT */))
1283
- : _createCommentVNode("v-if", true),
1284
- (!_ctx.loading && !_ctx.initError)
1285
- ? (_openBlock(), _createElementBlock("div", {
1286
- key: 3,
1287
- class: "card-list"
1288
- }, [
1289
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.displayProvidersList, (provider) => {
1290
- return (_openBlock(), _createElementBlock("div", {
1291
- key: provider.name,
1292
- class: _normalizeClass(['card', { active: _ctx.displayCurrentProvider === provider.name, disabled: provider.name === 'local' && _ctx.isLocalProviderDisabled }]),
1293
- onClick: $event => ((provider.name === 'local' && _ctx.isLocalProviderDisabled) ? null : _ctx.switchProvider(provider.name)),
1294
- onKeydown: [
1295
- _withKeys(_withModifiers($event => ((provider.name === 'local' && _ctx.isLocalProviderDisabled) ? null : _ctx.switchProvider(provider.name)), ["self","prevent"]), ["enter"]),
1296
- _withKeys(_withModifiers($event => ((provider.name === 'local' && _ctx.isLocalProviderDisabled) ? null : _ctx.switchProvider(provider.name)), ["self","prevent"]), ["space"])
1297
- ],
1298
- tabindex: provider.name === 'local' && _ctx.isLocalProviderDisabled ? -1 : 0,
1299
- role: "button",
1300
- "aria-current": _ctx.displayCurrentProvider === provider.name ? 'true' : null
1249
+ ], 64 /* STABLE_FRAGMENT */))
1250
+ : _createCommentVNode("v-if", true),
1251
+ (!_ctx.loading && !_ctx.initError)
1252
+ ? (_openBlock(), _createElementBlock("div", {
1253
+ key: 3,
1254
+ class: "card-list"
1301
1255
  }, [
1302
- _createElementVNode("div", { class: "card-leading" }, [
1303
- _createElementVNode("div", { class: "card-icon" }, [
1304
- _createTextVNode(_toDisplayString(provider.name.charAt(0).toUpperCase()), 1 /* TEXT */),
1305
- (_ctx.isTransformProvider(provider))
1306
- ? (_openBlock(), _createElementBlock("span", {
1307
- key: 0,
1308
- class: "card-icon-dot",
1309
- title: "通过内建转换适配"
1310
- }))
1311
- : _createCommentVNode("v-if", true)
1312
- ]),
1313
- _createElementVNode("div", { class: "card-content" }, [
1314
- (provider.name === 'local')
1315
- ? (_openBlock(), _createElementBlock("div", {
1316
- key: 0,
1317
- class: "bridge-pool-summary"
1318
- }, [
1319
- (_openBlock(), _createElementBlock("svg", {
1320
- class: "bridge-pool-summary-icon",
1321
- viewBox: "0 0 24 24",
1322
- fill: "none",
1323
- stroke: "currentColor",
1324
- "stroke-width": "2",
1325
- width: "12",
1326
- height: "12"
1327
- }, [
1328
- _createElementVNode("circle", {
1329
- cx: "6",
1330
- cy: "6",
1331
- r: "2"
1332
- }),
1333
- _createElementVNode("circle", {
1334
- cx: "18",
1335
- cy: "6",
1336
- r: "2"
1337
- }),
1338
- _createElementVNode("circle", {
1339
- cx: "12",
1340
- cy: "18",
1341
- r: "2"
1342
- }),
1343
- _createElementVNode("path", { d: "M6 8v4h6v4" }),
1344
- _createElementVNode("path", { d: "M18 8v4h-6v4" })
1345
- ])),
1346
- _createElementVNode("span", { class: "bridge-pool-summary-text" }, "已启用 " + _toDisplayString(_ctx.localBridgeCandidateProviders().filter(cp => !_ctx.isLocalBridgeExcluded(cp.name)).length) + " / " + _toDisplayString(_ctx.localBridgeCandidateProviders().length), 1 /* TEXT */)
1347
- ]))
1348
- : _createCommentVNode("v-if", true),
1349
- _createElementVNode("div", { class: "card-title" }, [
1350
- _createElementVNode("span", null, _toDisplayString(provider.name), 1 /* TEXT */),
1351
- (provider.readOnly)
1256
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.displayProvidersList, (provider) => {
1257
+ return (_openBlock(), _createElementBlock("div", {
1258
+ key: provider.name,
1259
+ class: _normalizeClass(['card', { active: _ctx.displayCurrentProvider === provider.name, disabled: provider.name === 'local' && _ctx.isLocalProviderDisabled }]),
1260
+ onClick: $event => ((provider.name === 'local' && _ctx.isLocalProviderDisabled) ? null : _ctx.switchProvider(provider.name)),
1261
+ onKeydown: [
1262
+ _withKeys(_withModifiers($event => ((provider.name === 'local' && _ctx.isLocalProviderDisabled) ? null : _ctx.switchProvider(provider.name)), ["self","prevent"]), ["enter"]),
1263
+ _withKeys(_withModifiers($event => ((provider.name === 'local' && _ctx.isLocalProviderDisabled) ? null : _ctx.switchProvider(provider.name)), ["self","prevent"]), ["space"])
1264
+ ],
1265
+ tabindex: provider.name === 'local' && _ctx.isLocalProviderDisabled ? -1 : 0,
1266
+ role: "button",
1267
+ "aria-current": _ctx.displayCurrentProvider === provider.name ? 'true' : null
1268
+ }, [
1269
+ _createElementVNode("div", { class: "card-leading" }, [
1270
+ _createElementVNode("div", { class: "card-icon" }, [
1271
+ _createTextVNode(_toDisplayString(provider.name.charAt(0).toUpperCase()), 1 /* TEXT */),
1272
+ (_ctx.isTransformProvider(provider))
1273
+ ? (_openBlock(), _createElementBlock("span", {
1274
+ key: 0,
1275
+ class: "card-icon-dot",
1276
+ title: _ctx.t('config.transformProvider.title')
1277
+ }, null, 8 /* PROPS */, ["title"]))
1278
+ : _createCommentVNode("v-if", true)
1279
+ ]),
1280
+ _createElementVNode("div", { class: "card-content" }, [
1281
+ (provider.name === 'local')
1282
+ ? (_openBlock(), _createElementBlock("div", {
1283
+ key: 0,
1284
+ class: "bridge-pool-summary"
1285
+ }, [
1286
+ (_openBlock(), _createElementBlock("svg", {
1287
+ class: "bridge-pool-summary-icon",
1288
+ viewBox: "0 0 24 24",
1289
+ fill: "none",
1290
+ stroke: "currentColor",
1291
+ "stroke-width": "2",
1292
+ width: "12",
1293
+ height: "12"
1294
+ }, [
1295
+ _createElementVNode("circle", {
1296
+ cx: "6",
1297
+ cy: "6",
1298
+ r: "2"
1299
+ }),
1300
+ _createElementVNode("circle", {
1301
+ cx: "18",
1302
+ cy: "6",
1303
+ r: "2"
1304
+ }),
1305
+ _createElementVNode("circle", {
1306
+ cx: "12",
1307
+ cy: "18",
1308
+ r: "2"
1309
+ }),
1310
+ _createElementVNode("path", { d: "M6 8v4h6v4" }),
1311
+ _createElementVNode("path", { d: "M18 8v4h-6v4" })
1312
+ ])),
1313
+ _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 */)
1314
+ ]))
1315
+ : _createCommentVNode("v-if", true),
1316
+ _createElementVNode("div", { class: "card-title" }, [
1317
+ _createElementVNode("span", null, _toDisplayString(provider.name), 1 /* TEXT */),
1318
+ (provider.readOnly)
1319
+ ? (_openBlock(), _createElementBlock("span", {
1320
+ key: 0,
1321
+ class: "provider-readonly-badge"
1322
+ }, _toDisplayString(_ctx.t('config.badge.system')), 1 /* TEXT */))
1323
+ : _createCommentVNode("v-if", true)
1324
+ ]),
1325
+ (provider.name !== 'local')
1326
+ ? (_openBlock(), _createElementBlock("div", {
1327
+ key: 1,
1328
+ class: "card-subtitle card-subtitle-model"
1329
+ }, _toDisplayString(_ctx.activeProviderModel(provider.name) || _ctx.t('config.model.unset')), 1 /* TEXT */))
1330
+ : _createCommentVNode("v-if", true),
1331
+ (provider.name !== 'local')
1332
+ ? (_openBlock(), _createElementBlock("div", {
1333
+ key: 2,
1334
+ class: "card-subtitle card-subtitle-url"
1335
+ }, _toDisplayString(_ctx.displayProviderUrl(provider) || _ctx.t('config.url.unset')), 1 /* TEXT */))
1336
+ : _createCommentVNode("v-if", true)
1337
+ ])
1338
+ ]),
1339
+ _createElementVNode("div", { class: "card-trailing" }, [
1340
+ (_ctx.speedResults[provider.name])
1352
1341
  ? (_openBlock(), _createElementBlock("span", {
1353
1342
  key: 0,
1354
- class: "provider-readonly-badge"
1355
- }, _toDisplayString(_ctx.t('config.badge.system')), 1 /* TEXT */))
1356
- : _createCommentVNode("v-if", true)
1357
- ]),
1358
- (provider.name !== 'local')
1359
- ? (_openBlock(), _createElementBlock("div", {
1360
- key: 1,
1361
- class: "card-subtitle card-subtitle-model"
1362
- }, _toDisplayString(_ctx.activeProviderModel(provider.name) || _ctx.t('config.model.unset')), 1 /* TEXT */))
1363
- : _createCommentVNode("v-if", true),
1364
- (provider.name !== 'local')
1365
- ? (_openBlock(), _createElementBlock("div", {
1366
- key: 2,
1367
- class: "card-subtitle card-subtitle-url"
1368
- }, _toDisplayString(_ctx.displayProviderUrl(provider) || _ctx.t('config.url.unset')), 1 /* TEXT */))
1369
- : _createCommentVNode("v-if", true)
1370
- ])
1371
- ]),
1372
- _createElementVNode("div", { class: "card-trailing" }, [
1373
- (_ctx.speedResults[provider.name])
1374
- ? (_openBlock(), _createElementBlock("span", {
1375
- key: 0,
1376
- class: _normalizeClass(['latency', _ctx.speedResults[provider.name].ok ? 'ok' : 'error'])
1377
- }, _toDisplayString(_ctx.formatLatency(_ctx.speedResults[provider.name])), 3 /* TEXT, CLASS */))
1378
- : _createCommentVNode("v-if", true),
1379
- _createElementVNode("span", {
1380
- class: _normalizeClass(['pill', _ctx.providerPillConfigured(provider) ? 'configured' : 'empty'])
1381
- }, _toDisplayString(_ctx.providerPillText(provider)), 3 /* TEXT, CLASS */),
1382
- _createElementVNode("div", {
1383
- class: "card-actions",
1384
- onClick: _withModifiers(() => {}, ["stop"])
1385
- }, [
1386
- (provider.name === 'local')
1387
- ? (_openBlock(), _createElementBlock("button", {
1388
- key: 0,
1389
- class: "card-action-btn bridge-pool-trigger",
1390
- onClick: $event => (_ctx.showCodexBridgePoolModal = true),
1391
- "aria-label": '轮询池设置',
1392
- title: '轮询池设置'
1393
- }, [
1394
- (_openBlock(), _createElementBlock("svg", {
1395
- viewBox: "0 0 24 24",
1396
- fill: "none",
1397
- stroke: "currentColor",
1398
- "stroke-width": "2"
1399
- }, [
1400
- _createElementVNode("circle", {
1401
- cx: "6",
1402
- cy: "6",
1403
- r: "2"
1404
- }),
1405
- _createElementVNode("circle", {
1406
- cx: "18",
1407
- cy: "6",
1408
- r: "2"
1409
- }),
1410
- _createElementVNode("circle", {
1411
- cx: "12",
1412
- cy: "18",
1413
- r: "2"
1414
- }),
1415
- _createElementVNode("path", { d: "M6 8v4h6v4" }),
1416
- _createElementVNode("path", { d: "M18 8v4h-6v4" })
1417
- ]))
1418
- ], 8 /* PROPS */, ["onClick"]))
1419
- : _createCommentVNode("v-if", true),
1420
- _createElementVNode("button", {
1421
- class: _normalizeClass(["card-action-btn", { loading: _ctx.speedLoading[provider.name] }]),
1422
- disabled: !!_ctx.speedLoading[provider.name],
1423
- onClick: $event => (_ctx.runSpeedTest(provider.name, { silent: true })),
1424
- "aria-label": _ctx.t('config.availabilityTestAria', { name: provider.name }),
1425
- title: _ctx.t('config.availabilityTest')
1426
- }, [
1427
- (_openBlock(), _createElementBlock("svg", {
1428
- viewBox: "0 0 24 24",
1429
- fill: "none",
1430
- stroke: "currentColor",
1431
- "stroke-width": "2"
1432
- }, [
1433
- _createElementVNode("path", { d: "M13 2L3 14h9l-1 8 10-12h-9l1-8z" })
1434
- ]))
1435
- ], 10 /* CLASS, PROPS */, ["disabled", "onClick", "aria-label", "title"]),
1436
- _createElementVNode("button", {
1437
- class: "card-action-btn",
1438
- disabled: !_ctx.shouldShowProviderEdit(provider),
1439
- onClick: $event => (_ctx.openEditModal(provider)),
1440
- "aria-label": _ctx.t('config.provider.edit.aria', { name: provider.name }),
1441
- title: _ctx.shouldShowProviderEdit(provider) ? _ctx.t('common.edit') : _ctx.t('common.notEditable')
1442
- }, [
1443
- (_openBlock(), _createElementBlock("svg", {
1444
- viewBox: "0 0 24 24",
1445
- fill: "none",
1446
- stroke: "currentColor",
1447
- "stroke-width": "2"
1343
+ class: _normalizeClass(['latency', _ctx.speedResults[provider.name].ok ? 'ok' : 'error'])
1344
+ }, _toDisplayString(_ctx.formatLatency(_ctx.speedResults[provider.name])), 3 /* TEXT, CLASS */))
1345
+ : _createCommentVNode("v-if", true),
1346
+ _createElementVNode("span", {
1347
+ class: _normalizeClass(['pill', _ctx.providerPillConfigured(provider) ? 'configured' : 'empty'])
1348
+ }, _toDisplayString(_ctx.providerPillText(provider)), 3 /* TEXT, CLASS */),
1349
+ _createElementVNode("div", {
1350
+ class: "card-actions",
1351
+ onClick: _withModifiers(() => {}, ["stop"])
1448
1352
  }, [
1449
- _createElementVNode("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
1450
- _createElementVNode("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
1451
- ]))
1452
- ], 8 /* PROPS */, ["disabled", "onClick", "aria-label", "title"]),
1453
- (!provider.readOnly)
1454
- ? (_openBlock(), _createElementBlock("button", {
1455
- key: 1,
1456
- class: "card-action-btn",
1457
- onClick: $event => (_ctx.openCloneProviderModal(provider)),
1458
- "aria-label": _ctx.t('config.provider.clone.aria', { name: provider.name }),
1459
- title: _ctx.t('config.provider.clone')
1460
- }, [
1461
- (_openBlock(), _createElementBlock("svg", {
1462
- viewBox: "0 0 24 24",
1463
- fill: "none",
1464
- stroke: "currentColor",
1465
- "stroke-width": "2"
1466
- }, [
1467
- _createElementVNode("rect", {
1468
- x: "9",
1469
- y: "9",
1470
- width: "13",
1471
- height: "13",
1472
- rx: "2"
1473
- }),
1474
- _createElementVNode("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
1475
- ]))
1476
- ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1477
- : _createCommentVNode("v-if", true),
1478
- (!provider.readOnly)
1479
- ? (_openBlock(), _createElementBlock("button", {
1480
- key: 2,
1481
- class: _normalizeClass(["card-action-btn", { loading: _ctx.providerShareLoading[provider.name], disabled: !_ctx.shouldAllowProviderShare(provider) }]),
1482
- disabled: _ctx.providerShareLoading[provider.name] || !_ctx.shouldAllowProviderShare(provider),
1483
- onClick: $event => (_ctx.copyProviderShareCommand(provider)),
1484
- title: _ctx.shouldAllowProviderShare(provider) ? _ctx.t('config.shareCommand') : _ctx.t('config.shareDisabled'),
1485
- "aria-label": _ctx.t('config.shareCommand.aria')
1353
+ (provider.name === 'local')
1354
+ ? (_openBlock(), _createElementBlock("button", {
1355
+ key: 0,
1356
+ class: "card-action-btn bridge-pool-trigger",
1357
+ onClick: $event => (_ctx.showCodexBridgePoolModal = true),
1358
+ "aria-label": _ctx.t('config.localBridge.poolSettings'),
1359
+ title: _ctx.t('config.localBridge.poolSettings')
1360
+ }, [
1361
+ (_openBlock(), _createElementBlock("svg", {
1362
+ viewBox: "0 0 24 24",
1363
+ fill: "none",
1364
+ stroke: "currentColor",
1365
+ "stroke-width": "2"
1366
+ }, [
1367
+ _createElementVNode("circle", {
1368
+ cx: "6",
1369
+ cy: "6",
1370
+ r: "2"
1371
+ }),
1372
+ _createElementVNode("circle", {
1373
+ cx: "18",
1374
+ cy: "6",
1375
+ r: "2"
1376
+ }),
1377
+ _createElementVNode("circle", {
1378
+ cx: "12",
1379
+ cy: "18",
1380
+ r: "2"
1381
+ }),
1382
+ _createElementVNode("path", { d: "M6 8v4h6v4" }),
1383
+ _createElementVNode("path", { d: "M18 8v4h-6v4" })
1384
+ ]))
1385
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1386
+ : _createCommentVNode("v-if", true),
1387
+ _createElementVNode("button", {
1388
+ class: _normalizeClass(["card-action-btn", { loading: _ctx.speedLoading[provider.name] }]),
1389
+ disabled: !!_ctx.speedLoading[provider.name],
1390
+ onClick: $event => (_ctx.runSpeedTest(provider.name, { silent: true })),
1391
+ "aria-label": _ctx.t('config.availabilityTestAria', { name: provider.name }),
1392
+ title: _ctx.t('config.availabilityTest')
1486
1393
  }, [
1487
1394
  (_openBlock(), _createElementBlock("svg", {
1488
1395
  viewBox: "0 0 24 24",
@@ -1490,20 +1397,15 @@ return function render(_ctx, _cache) {
1490
1397
  stroke: "currentColor",
1491
1398
  "stroke-width": "2"
1492
1399
  }, [
1493
- _createElementVNode("path", { d: "M4 12v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7" }),
1494
- _createElementVNode("path", { d: "M16 6l-4-4-4 4" }),
1495
- _createElementVNode("path", { d: "M12 2v14" })
1400
+ _createElementVNode("path", { d: "M13 2L3 14h9l-1 8 10-12h-9l1-8z" })
1496
1401
  ]))
1497
- ], 10 /* CLASS, PROPS */, ["disabled", "onClick", "title", "aria-label"]))
1498
- : _createCommentVNode("v-if", true),
1499
- (!provider.readOnly)
1500
- ? (_openBlock(), _createElementBlock("button", {
1501
- key: 3,
1502
- class: _normalizeClass(["card-action-btn delete", { disabled: !_ctx.shouldShowProviderDelete(provider) }]),
1503
- disabled: !_ctx.shouldShowProviderDelete(provider),
1504
- onClick: $event => (_ctx.deleteProvider(provider.name)),
1505
- "aria-label": _ctx.t('config.provider.delete.aria', { name: provider.name }),
1506
- title: _ctx.shouldShowProviderDelete(provider) ? _ctx.t('common.delete') : _ctx.t('common.notDeletable')
1402
+ ], 10 /* CLASS, PROPS */, ["disabled", "onClick", "aria-label", "title"]),
1403
+ _createElementVNode("button", {
1404
+ class: "card-action-btn",
1405
+ disabled: !_ctx.shouldShowProviderEdit(provider),
1406
+ onClick: $event => (_ctx.openEditModal(provider)),
1407
+ "aria-label": _ctx.t('config.provider.edit.aria', { name: provider.name }),
1408
+ title: _ctx.shouldShowProviderEdit(provider) ? _ctx.t('common.edit') : _ctx.t('common.notEditable')
1507
1409
  }, [
1508
1410
  (_openBlock(), _createElementBlock("svg", {
1509
1411
  viewBox: "0 0 24 24",
@@ -1511,17 +1413,101 @@ return function render(_ctx, _cache) {
1511
1413
  stroke: "currentColor",
1512
1414
  "stroke-width": "2"
1513
1415
  }, [
1514
- _createElementVNode("path", { d: "M3 6h18" }),
1515
- _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" })
1416
+ _createElementVNode("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
1417
+ _createElementVNode("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
1516
1418
  ]))
1517
- ], 10 /* CLASS, PROPS */, ["disabled", "onClick", "aria-label", "title"]))
1518
- : _createCommentVNode("v-if", true)
1519
- ], 8 /* PROPS */, ["onClick"])
1520
- ])
1521
- ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "tabindex", "aria-current"]))
1522
- }), 128 /* KEYED_FRAGMENT */))
1523
- ]))
1524
- : _createCommentVNode("v-if", true)
1419
+ ], 8 /* PROPS */, ["disabled", "onClick", "aria-label", "title"]),
1420
+ (!provider.readOnly)
1421
+ ? (_openBlock(), _createElementBlock("button", {
1422
+ key: 1,
1423
+ class: "card-action-btn",
1424
+ onClick: $event => (_ctx.openCloneProviderModal(provider)),
1425
+ "aria-label": _ctx.t('config.provider.clone.aria', { name: provider.name }),
1426
+ title: _ctx.t('config.provider.clone')
1427
+ }, [
1428
+ (_openBlock(), _createElementBlock("svg", {
1429
+ viewBox: "0 0 24 24",
1430
+ fill: "none",
1431
+ stroke: "currentColor",
1432
+ "stroke-width": "2"
1433
+ }, [
1434
+ _createElementVNode("rect", {
1435
+ x: "9",
1436
+ y: "9",
1437
+ width: "13",
1438
+ height: "13",
1439
+ rx: "2"
1440
+ }),
1441
+ _createElementVNode("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
1442
+ ]))
1443
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
1444
+ : _createCommentVNode("v-if", true),
1445
+ (!provider.readOnly)
1446
+ ? (_openBlock(), _createElementBlock("button", {
1447
+ key: 2,
1448
+ class: _normalizeClass(["card-action-btn", { loading: _ctx.providerShareLoading[provider.name], disabled: !_ctx.shouldAllowProviderShare(provider) }]),
1449
+ disabled: _ctx.providerShareLoading[provider.name] || !_ctx.shouldAllowProviderShare(provider),
1450
+ onClick: $event => (_ctx.copyProviderShareCommand(provider)),
1451
+ title: _ctx.shouldAllowProviderShare(provider) ? _ctx.t('config.shareCommand') : _ctx.t('config.shareDisabled'),
1452
+ "aria-label": _ctx.t('config.shareCommand.aria')
1453
+ }, [
1454
+ (_openBlock(), _createElementBlock("svg", {
1455
+ viewBox: "0 0 24 24",
1456
+ fill: "none",
1457
+ stroke: "currentColor",
1458
+ "stroke-width": "2"
1459
+ }, [
1460
+ _createElementVNode("path", { d: "M4 12v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7" }),
1461
+ _createElementVNode("path", { d: "M16 6l-4-4-4 4" }),
1462
+ _createElementVNode("path", { d: "M12 2v14" })
1463
+ ]))
1464
+ ], 10 /* CLASS, PROPS */, ["disabled", "onClick", "title", "aria-label"]))
1465
+ : _createCommentVNode("v-if", true),
1466
+ (!provider.readOnly)
1467
+ ? (_openBlock(), _createElementBlock("button", {
1468
+ key: 3,
1469
+ class: _normalizeClass(["card-action-btn delete", { disabled: !_ctx.shouldShowProviderDelete(provider) }]),
1470
+ disabled: !_ctx.shouldShowProviderDelete(provider),
1471
+ onClick: $event => (_ctx.deleteProvider(provider.name)),
1472
+ "aria-label": _ctx.t('config.provider.delete.aria', { name: provider.name }),
1473
+ title: _ctx.shouldShowProviderDelete(provider) ? _ctx.t('common.delete') : _ctx.t('common.notDeletable')
1474
+ }, [
1475
+ (_openBlock(), _createElementBlock("svg", {
1476
+ viewBox: "0 0 24 24",
1477
+ fill: "none",
1478
+ stroke: "currentColor",
1479
+ "stroke-width": "2"
1480
+ }, [
1481
+ _createElementVNode("path", { d: "M3 6h18" }),
1482
+ _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" })
1483
+ ]))
1484
+ ], 10 /* CLASS, PROPS */, ["disabled", "onClick", "aria-label", "title"]))
1485
+ : _createCommentVNode("v-if", true)
1486
+ ], 8 /* PROPS */, ["onClick"])
1487
+ ])
1488
+ ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "tabindex", "aria-current"]))
1489
+ }), 128 /* KEYED_FRAGMENT */))
1490
+ ]))
1491
+ : _createCommentVNode("v-if", true)
1492
+ ]),
1493
+ (!_ctx.isToolConfigWriteAllowed('codex'))
1494
+ ? (_openBlock(), _createElementBlock("div", {
1495
+ key: 0,
1496
+ class: "tool-config-write-overlay"
1497
+ }, [
1498
+ _createElementVNode("div", { class: "tool-config-write-overlay-card" }, [
1499
+ _createElementVNode("div", { class: "tool-config-write-overlay-title" }, _toDisplayString(_ctx.t('toolConfig.codex.lockedTitle')), 1 /* TEXT */),
1500
+ _createElementVNode("p", null, _toDisplayString(_ctx.t('toolConfig.codex.lockedDesc')), 1 /* TEXT */),
1501
+ _createElementVNode("button", {
1502
+ type: "button",
1503
+ class: "btn-tool",
1504
+ onClick: $event => (_ctx.setToolConfigPermission('codex', true)),
1505
+ disabled: _ctx.toolConfigPermissionSaving.codex
1506
+ }, _toDisplayString(_ctx.t('toolConfig.enableWrite')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1507
+ ])
1508
+ ]))
1509
+ : _createCommentVNode("v-if", true)
1510
+ ], 2 /* CLASS */)
1525
1511
  ], 64 /* STABLE_FRAGMENT */))
1526
1512
  ], 8 /* PROPS */, ["aria-labelledby"]), [
1527
1513
  [_vShow, _ctx.mainTab === 'config' && _ctx.isProviderConfigMode]
@@ -1586,344 +1572,582 @@ return function render(_ctx, _cache) {
1586
1572
  ])
1587
1573
  ]))
1588
1574
  : (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [
1589
- (!_ctx.loading && !_ctx.initError)
1590
- ? (_openBlock(), _createElementBlock("button", {
1591
- key: 0,
1592
- class: "btn-add",
1593
- onClick: _ctx.openClaudeConfigModal
1594
- }, [
1595
- (_openBlock(), _createElementBlock("svg", {
1596
- class: "icon",
1597
- viewBox: "0 0 20 20",
1598
- fill: "none",
1599
- stroke: "currentColor",
1600
- "stroke-width": "2"
1601
- }, [
1602
- _createElementVNode("path", { d: "M10 4v12M4 10h12" })
1603
- ])),
1604
- _createTextVNode(" " + _toDisplayString(_ctx.t('claude.addProvider')), 1 /* TEXT */)
1605
- ], 8 /* PROPS */, ["onClick"]))
1606
- : _createCommentVNode("v-if", true),
1607
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('claude.applyDefault')), 1 /* TEXT */),
1608
- _createElementVNode("div", { class: "selector-section" }, [
1609
- _createElementVNode("div", { class: "selector-header" }, [
1610
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('claude.presetProviders')), 1 /* TEXT */)
1575
+ _createElementVNode("section", {
1576
+ class: "tool-config-write-card",
1577
+ "aria-label": _ctx.t('toolConfig.claude.title')
1578
+ }, [
1579
+ _createElementVNode("div", { class: "tool-config-write-copy" }, [
1580
+ _createElementVNode("div", { class: "tool-config-write-title" }, _toDisplayString(_ctx.t('toolConfig.claude.title')), 1 /* TEXT */),
1581
+ _createElementVNode("p", { class: "tool-config-write-desc" }, _toDisplayString(_ctx.t('toolConfig.claude.desc')), 1 /* TEXT */)
1611
1582
  ]),
1612
- _createElementVNode("div", {
1613
- class: "btn-group",
1614
- style: {"flex-wrap":"wrap","gap":"8px","margin-top":"0"}
1615
- }, [
1616
- _createElementVNode("button", {
1617
- type: "button",
1618
- 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}
1620
- }, "Claude Official", 8 /* PROPS */, ["onClick"]),
1621
- _createElementVNode("button", {
1622
- type: "button",
1623
- 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}
1625
- }, "DeepSeek", 8 /* PROPS */, ["onClick"]),
1626
- _createElementVNode("button", {
1627
- type: "button",
1628
- 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}
1630
- }, "Zhipu GLM", 8 /* PROPS */, ["onClick"]),
1631
- _createElementVNode("button", {
1632
- type: "button",
1633
- 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}
1635
- }, "Z.ai GLM", 8 /* PROPS */, ["onClick"]),
1636
- _createElementVNode("button", {
1637
- type: "button",
1638
- 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}
1640
- }, "Qwen Coder", 8 /* PROPS */, ["onClick"]),
1641
- _createElementVNode("button", {
1642
- type: "button",
1643
- 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}
1645
- }, "Kimi k2", 8 /* PROPS */, ["onClick"]),
1646
- _createElementVNode("button", {
1647
- type: "button",
1648
- 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}
1650
- }, "Kimi For Coding", 8 /* PROPS */, ["onClick"]),
1651
- _createElementVNode("button", {
1652
- type: "button",
1653
- 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}
1655
- }, "KAT-Coder", 8 /* PROPS */, ["onClick"]),
1656
- _createElementVNode("button", {
1657
- type: "button",
1658
- 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}
1660
- }, "Longcat", 8 /* PROPS */, ["onClick"]),
1661
- _createElementVNode("button", {
1662
- type: "button",
1663
- 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}
1665
- }, "MiniMax", 8 /* PROPS */, ["onClick"]),
1666
- _createElementVNode("button", {
1667
- type: "button",
1668
- 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}
1670
- }, "MiniMax en", 8 /* PROPS */, ["onClick"]),
1671
- _createElementVNode("button", {
1672
- type: "button",
1673
- 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}
1675
- }, "DouBaoSeed", 8 /* PROPS */, ["onClick"]),
1676
- _createElementVNode("button", {
1677
- type: "button",
1678
- 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}
1680
- }, "BaiLing", 8 /* PROPS */, ["onClick"]),
1681
- _createElementVNode("button", {
1682
- type: "button",
1683
- 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}
1685
- }, "ModelScope", 8 /* PROPS */, ["onClick"]),
1686
- _createElementVNode("button", {
1687
- type: "button",
1688
- 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}
1690
- }, "AiHubMix", 8 /* PROPS */, ["onClick"]),
1691
- _createElementVNode("button", {
1692
- type: "button",
1693
- 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}
1695
- }, "DMXAPI", 8 /* PROPS */, ["onClick"]),
1696
- _createElementVNode("button", {
1697
- type: "button",
1698
- 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}
1700
- }, "PackyCode", 8 /* PROPS */, ["onClick"]),
1701
- _createElementVNode("button", {
1702
- type: "button",
1703
- 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}
1705
- }, "AnyRouter", 8 /* PROPS */, ["onClick"]),
1706
- _createElementVNode("button", {
1707
- type: "button",
1708
- 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}
1710
- }, "Xiaomi MiMo", 8 /* PROPS */, ["onClick"]),
1711
- _createElementVNode("button", {
1712
- type: "button",
1713
- 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}
1715
- }, "Xiaomi Token Plan", 8 /* PROPS */, ["onClick"])
1583
+ _createElementVNode("label", { class: "settings-toggle-row tool-config-write-toggle" }, [
1584
+ _createElementVNode("input", {
1585
+ type: "checkbox",
1586
+ checked: _ctx.isToolConfigWriteAllowed('claude'),
1587
+ disabled: _ctx.toolConfigPermissionSaving.claude,
1588
+ onChange: $event => (_ctx.setToolConfigPermission('claude', $event.target.checked))
1589
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["checked", "disabled", "onChange"]),
1590
+ _createElementVNode("span", { class: "toggle-track" }, [
1591
+ _createElementVNode("span", { class: "toggle-thumb" })
1592
+ ]),
1593
+ _createElementVNode("span", null, _toDisplayString(_ctx.toolConfigPermissionStatusLabel('claude')), 1 /* TEXT */)
1716
1594
  ])
1717
- ]),
1718
- _createElementVNode("div", { class: "selector-section" }, [
1719
- _createElementVNode("div", { class: "selector-header" }, [
1720
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('claude.model')), 1 /* TEXT */)
1595
+ ], 8 /* PROPS */, ["aria-label"]),
1596
+ _createElementVNode("div", {
1597
+ class: _normalizeClass(["tool-config-write-scope", { locked: !_ctx.isToolConfigWriteAllowed('claude') }])
1598
+ }, [
1599
+ _createElementVNode("div", { class: "tool-config-write-body" }, [
1600
+ (!_ctx.loading && !_ctx.initError)
1601
+ ? (_openBlock(), _createElementBlock("button", {
1602
+ key: 0,
1603
+ class: "btn-add",
1604
+ onClick: _ctx.openClaudeConfigModal,
1605
+ disabled: !_ctx.isToolConfigWriteAllowed('claude')
1606
+ }, [
1607
+ (_openBlock(), _createElementBlock("svg", {
1608
+ class: "icon",
1609
+ viewBox: "0 0 20 20",
1610
+ fill: "none",
1611
+ stroke: "currentColor",
1612
+ "stroke-width": "2"
1613
+ }, [
1614
+ _createElementVNode("path", { d: "M10 4v12M4 10h12" })
1615
+ ])),
1616
+ _createTextVNode(" " + _toDisplayString(_ctx.t('claude.addProvider')), 1 /* TEXT */)
1617
+ ], 8 /* PROPS */, ["onClick", "disabled"]))
1618
+ : _createCommentVNode("v-if", true),
1619
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('claude.applyDefault')), 1 /* TEXT */),
1620
+ _createElementVNode("div", { class: "selector-section" }, [
1621
+ _createElementVNode("div", { class: "selector-header" }, [
1622
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('claude.presetProviders')), 1 /* TEXT */)
1623
+ ]),
1624
+ _createElementVNode("div", {
1625
+ class: "btn-group",
1626
+ style: {"flex-wrap":"wrap","gap":"8px","margin-top":"0"}
1627
+ }, [
1628
+ _createElementVNode("button", {
1629
+ type: "button",
1630
+ class: "btn-mini",
1631
+ 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}
1632
+ }, "Claude Official", 8 /* PROPS */, ["onClick"]),
1633
+ _createElementVNode("button", {
1634
+ type: "button",
1635
+ class: "btn-mini",
1636
+ 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}
1637
+ }, "DeepSeek", 8 /* PROPS */, ["onClick"]),
1638
+ _createElementVNode("button", {
1639
+ type: "button",
1640
+ class: "btn-mini",
1641
+ 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}
1642
+ }, "Zhipu GLM", 8 /* PROPS */, ["onClick"]),
1643
+ _createElementVNode("button", {
1644
+ type: "button",
1645
+ class: "btn-mini",
1646
+ 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}
1647
+ }, "Z.ai GLM", 8 /* PROPS */, ["onClick"]),
1648
+ _createElementVNode("button", {
1649
+ type: "button",
1650
+ class: "btn-mini",
1651
+ 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}
1652
+ }, "Qwen Coder", 8 /* PROPS */, ["onClick"]),
1653
+ _createElementVNode("button", {
1654
+ type: "button",
1655
+ class: "btn-mini",
1656
+ 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}
1657
+ }, "Kimi k2", 8 /* PROPS */, ["onClick"]),
1658
+ _createElementVNode("button", {
1659
+ type: "button",
1660
+ class: "btn-mini",
1661
+ 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}
1662
+ }, "Kimi For Coding", 8 /* PROPS */, ["onClick"]),
1663
+ _createElementVNode("button", {
1664
+ type: "button",
1665
+ class: "btn-mini",
1666
+ 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}
1667
+ }, "KAT-Coder", 8 /* PROPS */, ["onClick"]),
1668
+ _createElementVNode("button", {
1669
+ type: "button",
1670
+ class: "btn-mini",
1671
+ 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}
1672
+ }, "Longcat", 8 /* PROPS */, ["onClick"]),
1673
+ _createElementVNode("button", {
1674
+ type: "button",
1675
+ class: "btn-mini",
1676
+ 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}
1677
+ }, "MiniMax", 8 /* PROPS */, ["onClick"]),
1678
+ _createElementVNode("button", {
1679
+ type: "button",
1680
+ class: "btn-mini",
1681
+ 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}
1682
+ }, "MiniMax en", 8 /* PROPS */, ["onClick"]),
1683
+ _createElementVNode("button", {
1684
+ type: "button",
1685
+ class: "btn-mini",
1686
+ 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}
1687
+ }, "DouBaoSeed", 8 /* PROPS */, ["onClick"]),
1688
+ _createElementVNode("button", {
1689
+ type: "button",
1690
+ class: "btn-mini",
1691
+ 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}
1692
+ }, "BaiLing", 8 /* PROPS */, ["onClick"]),
1693
+ _createElementVNode("button", {
1694
+ type: "button",
1695
+ class: "btn-mini",
1696
+ 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}
1697
+ }, "ModelScope", 8 /* PROPS */, ["onClick"]),
1698
+ _createElementVNode("button", {
1699
+ type: "button",
1700
+ class: "btn-mini",
1701
+ 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}
1702
+ }, "AiHubMix", 8 /* PROPS */, ["onClick"]),
1703
+ _createElementVNode("button", {
1704
+ type: "button",
1705
+ class: "btn-mini",
1706
+ 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}
1707
+ }, "DMXAPI", 8 /* PROPS */, ["onClick"]),
1708
+ _createElementVNode("button", {
1709
+ type: "button",
1710
+ class: "btn-mini",
1711
+ 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}
1712
+ }, "PackyCode", 8 /* PROPS */, ["onClick"]),
1713
+ _createElementVNode("button", {
1714
+ type: "button",
1715
+ class: "btn-mini",
1716
+ 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}
1717
+ }, "AnyRouter", 8 /* PROPS */, ["onClick"]),
1718
+ _createElementVNode("button", {
1719
+ type: "button",
1720
+ class: "btn-mini",
1721
+ 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}
1722
+ }, "Xiaomi MiMo", 8 /* PROPS */, ["onClick"]),
1723
+ _createElementVNode("button", {
1724
+ type: "button",
1725
+ class: "btn-mini",
1726
+ 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}
1727
+ }, "Xiaomi Token Plan", 8 /* PROPS */, ["onClick"])
1728
+ ])
1729
+ ]),
1730
+ _createElementVNode("div", { class: "selector-section" }, [
1731
+ _createElementVNode("div", { class: "selector-header" }, [
1732
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('claude.model')), 1 /* TEXT */)
1733
+ ]),
1734
+ (_ctx.claudeModelHasList)
1735
+ ? _withDirectives((_openBlock(), _createElementBlock("input", {
1736
+ key: 0,
1737
+ class: "model-input",
1738
+ "onUpdate:modelValue": $event => ((_ctx.currentClaudeModel) = $event),
1739
+ onChange: _ctx.onClaudeModelChange,
1740
+ onBlur: _ctx.onClaudeModelChange,
1741
+ onKeyup: _withKeys(_ctx.onClaudeModelChange, ["enter"]),
1742
+ placeholder: _ctx.t('claude.model.placeholder'),
1743
+ readonly: _ctx.currentClaudeConfig === 'claude-local',
1744
+ list: "claude-model-options"
1745
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange", "onBlur", "onKeyup", "placeholder", "readonly"])), [
1746
+ [_vModelText, _ctx.currentClaudeModel]
1747
+ ])
1748
+ : _createCommentVNode("v-if", true),
1749
+ (_ctx.claudeModelHasList)
1750
+ ? (_openBlock(), _createElementBlock("datalist", {
1751
+ key: 1,
1752
+ id: "claude-model-options"
1753
+ }, [
1754
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.claudeModelOptions, (model) => {
1755
+ return (_openBlock(), _createElementBlock("option", {
1756
+ key: model,
1757
+ value: model
1758
+ }, null, 8 /* PROPS */, ["value"]))
1759
+ }), 128 /* KEYED_FRAGMENT */))
1760
+ ]))
1761
+ : _withDirectives((_openBlock(), _createElementBlock("input", {
1762
+ key: 2,
1763
+ class: "model-input",
1764
+ "onUpdate:modelValue": $event => ((_ctx.currentClaudeModel) = $event),
1765
+ onBlur: _ctx.onClaudeModelChange,
1766
+ onKeyup: _withKeys(_ctx.onClaudeModelChange, ["enter"]),
1767
+ placeholder: _ctx.t('claude.model.placeholder'),
1768
+ readonly: _ctx.currentClaudeConfig === 'claude-local'
1769
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onBlur", "onKeyup", "placeholder", "readonly"])), [
1770
+ [_vModelText, _ctx.currentClaudeModel]
1771
+ ]),
1772
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('claude.model.hint')), 1 /* TEXT */),
1773
+ _createElementVNode("button", {
1774
+ class: "btn-tool btn-template-editor",
1775
+ onClick: _ctx.openClaudeConfigTemplateEditor,
1776
+ disabled: _ctx.loading || !!_ctx.initError
1777
+ }, _toDisplayString(_ctx.t('config.template.openEditor')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1778
+ ]),
1779
+ _createElementVNode("div", { class: "selector-section" }, [
1780
+ _createElementVNode("div", { class: "selector-header" }, [
1781
+ _createElementVNode("span", { class: "selector-title" }, "CLAUDE.md")
1782
+ ]),
1783
+ _createElementVNode("button", {
1784
+ class: "btn-tool",
1785
+ onClick: _ctx.openClaudeMdEditor,
1786
+ disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
1787
+ }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('claude.md.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1788
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('claude.md.hint')), 1 /* TEXT */)
1789
+ ]),
1790
+ _createElementVNode("div", { class: "selector-section" }, [
1791
+ _createElementVNode("div", { class: "selector-header" }, [
1792
+ _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.health.title')), 1 /* TEXT */)
1793
+ ]),
1794
+ _createElementVNode("button", {
1795
+ class: "btn-tool",
1796
+ onClick: _ctx.runHealthCheck,
1797
+ disabled: _ctx.healthCheckLoading || _ctx.loading || !!_ctx.initError
1798
+ }, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('config.health.running') : _ctx.t('config.health.run')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1799
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.health.hint')), 1 /* TEXT */)
1800
+ ]),
1801
+ _createElementVNode("div", { class: "card-list" }, [
1802
+ _createElementVNode("div", {
1803
+ class: _normalizeClass(['card', { active: _ctx.currentClaudeConfig === 'claude-local', disabled: _ctx.isClaudeLocalBridgeDisabled() }]),
1804
+ onClick: $event => (_ctx.isClaudeLocalBridgeDisabled() ? null : _ctx.applyClaudeLocalBridge()),
1805
+ onKeydown: [
1806
+ _withKeys(_withModifiers($event => (_ctx.isClaudeLocalBridgeDisabled() ? null : _ctx.applyClaudeLocalBridge()), ["self","prevent"]), ["enter"]),
1807
+ _withKeys(_withModifiers($event => (_ctx.isClaudeLocalBridgeDisabled() ? null : _ctx.applyClaudeLocalBridge()), ["self","prevent"]), ["space"])
1808
+ ],
1809
+ tabindex: _ctx.isClaudeLocalBridgeDisabled() ? -1 : 0,
1810
+ role: "button",
1811
+ "aria-current": _ctx.currentClaudeConfig === 'claude-local' ? 'true' : null
1812
+ }, [
1813
+ _createElementVNode("div", { class: "card-leading" }, [
1814
+ _createElementVNode("div", { class: "card-icon" }, "L"),
1815
+ _createElementVNode("div", { class: "card-content" }, [
1816
+ _createElementVNode("div", { class: "bridge-pool-summary" }, [
1817
+ (_openBlock(), _createElementBlock("svg", {
1818
+ class: "bridge-pool-summary-icon",
1819
+ viewBox: "0 0 24 24",
1820
+ fill: "none",
1821
+ stroke: "currentColor",
1822
+ "stroke-width": "2",
1823
+ width: "12",
1824
+ height: "12"
1825
+ }, [
1826
+ _createElementVNode("circle", {
1827
+ cx: "6",
1828
+ cy: "6",
1829
+ r: "2"
1830
+ }),
1831
+ _createElementVNode("circle", {
1832
+ cx: "18",
1833
+ cy: "6",
1834
+ r: "2"
1835
+ }),
1836
+ _createElementVNode("circle", {
1837
+ cx: "12",
1838
+ cy: "18",
1839
+ r: "2"
1840
+ }),
1841
+ _createElementVNode("path", { d: "M6 8v4h6v4" }),
1842
+ _createElementVNode("path", { d: "M18 8v4h-6v4" })
1843
+ ])),
1844
+ _createElementVNode("span", { class: "bridge-pool-summary-text" }, _toDisplayString(_ctx.t('claude.localBridge.enabled')) + " " + _toDisplayString(_ctx.claudeLocalBridgeCandidateProviders().filter(cp => !_ctx.isClaudeLocalBridgeExcluded(cp.name)).length) + " / " + _toDisplayString(_ctx.claudeLocalBridgeCandidateProviders().length), 1 /* TEXT */)
1845
+ ]),
1846
+ _createElementVNode("div", { class: "card-title" }, [
1847
+ _createElementVNode("span", null, "local"),
1848
+ _createElementVNode("span", { class: "provider-readonly-badge" }, _toDisplayString(_ctx.t('config.badge.system')), 1 /* TEXT */)
1849
+ ])
1850
+ ])
1851
+ ]),
1852
+ _createElementVNode("div", { class: "card-trailing" }, [
1853
+ _createElementVNode("span", {
1854
+ class: _normalizeClass(['pill', _ctx.claudeLocalBridgeConfigured() ? 'configured' : 'empty'])
1855
+ }, _toDisplayString(_ctx.claudeLocalBridgeConfigured() ? _ctx.t('claude.configured') : _ctx.t('claude.notConfigured')), 3 /* TEXT, CLASS */),
1856
+ _createElementVNode("div", {
1857
+ class: "card-actions",
1858
+ onClick: _withModifiers(() => {}, ["stop"])
1859
+ }, [
1860
+ _createElementVNode("button", {
1861
+ class: "card-action-btn bridge-pool-trigger",
1862
+ onClick: $event => (_ctx.showClaudeBridgePoolModal = true),
1863
+ "aria-label": _ctx.t('claude.localBridge.poolTitle'),
1864
+ title: _ctx.t('claude.localBridge.poolTitle')
1865
+ }, [
1866
+ (_openBlock(), _createElementBlock("svg", {
1867
+ viewBox: "0 0 24 24",
1868
+ fill: "none",
1869
+ stroke: "currentColor",
1870
+ "stroke-width": "2"
1871
+ }, [
1872
+ _createElementVNode("circle", {
1873
+ cx: "6",
1874
+ cy: "6",
1875
+ r: "2"
1876
+ }),
1877
+ _createElementVNode("circle", {
1878
+ cx: "18",
1879
+ cy: "6",
1880
+ r: "2"
1881
+ }),
1882
+ _createElementVNode("circle", {
1883
+ cx: "12",
1884
+ cy: "18",
1885
+ r: "2"
1886
+ }),
1887
+ _createElementVNode("path", { d: "M6 8v4h6v4" }),
1888
+ _createElementVNode("path", { d: "M18 8v4h-6v4" })
1889
+ ]))
1890
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"])
1891
+ ], 8 /* PROPS */, ["onClick"])
1892
+ ])
1893
+ ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "tabindex", "aria-current"]),
1894
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.claudeConfigs, (config, name) => {
1895
+ return (_openBlock(), _createElementBlock("div", {
1896
+ key: name,
1897
+ class: _normalizeClass(['card', { active: _ctx.currentClaudeConfig === name }]),
1898
+ onClick: $event => (_ctx.applyClaudeConfig(name)),
1899
+ onKeydown: [
1900
+ _withKeys(_withModifiers($event => (_ctx.applyClaudeConfig(name)), ["self","prevent"]), ["enter"]),
1901
+ _withKeys(_withModifiers($event => (_ctx.applyClaudeConfig(name)), ["self","prevent"]), ["space"])
1902
+ ],
1903
+ tabindex: "0",
1904
+ role: "button",
1905
+ "aria-current": _ctx.currentClaudeConfig === name ? 'true' : null
1906
+ }, [
1907
+ _createElementVNode("div", { class: "card-leading" }, [
1908
+ _createElementVNode("div", { class: "card-icon" }, _toDisplayString(name.charAt(0).toUpperCase()), 1 /* TEXT */),
1909
+ _createElementVNode("div", { class: "card-content" }, [
1910
+ _createElementVNode("div", { class: "card-title" }, _toDisplayString(name), 1 /* TEXT */),
1911
+ _createElementVNode("div", { class: "card-subtitle card-subtitle-model" }, _toDisplayString(config.model || _ctx.t('claude.model.unset')), 1 /* TEXT */),
1912
+ (config.baseUrl)
1913
+ ? (_openBlock(), _createElementBlock("div", {
1914
+ key: 0,
1915
+ class: "card-subtitle card-subtitle-url"
1916
+ }, _toDisplayString(config.baseUrl), 1 /* TEXT */))
1917
+ : _createCommentVNode("v-if", true)
1918
+ ])
1919
+ ]),
1920
+ _createElementVNode("div", { class: "card-trailing" }, [
1921
+ (_ctx.claudeSpeedResults[name])
1922
+ ? (_openBlock(), _createElementBlock("span", {
1923
+ key: 0,
1924
+ class: _normalizeClass(['latency', _ctx.claudeSpeedResults[name].ok ? 'ok' : 'error'])
1925
+ }, _toDisplayString(_ctx.formatLatency(_ctx.claudeSpeedResults[name])), 3 /* TEXT, CLASS */))
1926
+ : _createCommentVNode("v-if", true),
1927
+ _createElementVNode("span", {
1928
+ class: _normalizeClass(['pill', config.hasKey ? 'configured' : 'empty'])
1929
+ }, _toDisplayString(config.hasKey ? _ctx.t('claude.configured') : _ctx.t('claude.notConfigured')), 3 /* TEXT, CLASS */),
1930
+ _createElementVNode("div", {
1931
+ class: "card-actions",
1932
+ onClick: _withModifiers(() => {}, ["stop"])
1933
+ }, [
1934
+ _createElementVNode("button", {
1935
+ class: "card-action-btn",
1936
+ onClick: $event => (_ctx.openEditConfigModal(name)),
1937
+ "aria-label": _ctx.t('claude.action.editAria', { name }),
1938
+ title: _ctx.t('claude.action.edit')
1939
+ }, [
1940
+ (_openBlock(), _createElementBlock("svg", {
1941
+ viewBox: "0 0 24 24",
1942
+ fill: "none",
1943
+ stroke: "currentColor",
1944
+ "stroke-width": "2"
1945
+ }, [
1946
+ _createElementVNode("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
1947
+ _createElementVNode("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
1948
+ ]))
1949
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]),
1950
+ _createElementVNode("button", {
1951
+ class: "card-action-btn",
1952
+ onClick: $event => (_ctx.openCloneClaudeConfigModal(name, config)),
1953
+ "aria-label": _ctx.t('claude.action.cloneAria', { name }),
1954
+ title: _ctx.t('claude.action.clone')
1955
+ }, [
1956
+ (_openBlock(), _createElementBlock("svg", {
1957
+ viewBox: "0 0 24 24",
1958
+ fill: "none",
1959
+ stroke: "currentColor",
1960
+ "stroke-width": "2"
1961
+ }, [
1962
+ _createElementVNode("rect", {
1963
+ x: "9",
1964
+ y: "9",
1965
+ width: "13",
1966
+ height: "13",
1967
+ rx: "2"
1968
+ }),
1969
+ _createElementVNode("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
1970
+ ]))
1971
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]),
1972
+ _createElementVNode("button", {
1973
+ class: _normalizeClass(["card-action-btn", { loading: _ctx.claudeShareLoading[name] }]),
1974
+ onClick: $event => (_ctx.copyClaudeShareCommand(name)),
1975
+ title: _ctx.t('config.shareCommand'),
1976
+ "aria-label": _ctx.t('config.shareCommand.aria')
1977
+ }, [
1978
+ (_openBlock(), _createElementBlock("svg", {
1979
+ viewBox: "0 0 24 24",
1980
+ fill: "none",
1981
+ stroke: "currentColor",
1982
+ "stroke-width": "2"
1983
+ }, [
1984
+ _createElementVNode("path", { d: "M4 12v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7" }),
1985
+ _createElementVNode("path", { d: "M16 6l-4-4-4 4" }),
1986
+ _createElementVNode("path", { d: "M12 2v14" })
1987
+ ]))
1988
+ ], 10 /* CLASS, PROPS */, ["onClick", "title", "aria-label"]),
1989
+ _createElementVNode("button", {
1990
+ class: "card-action-btn delete",
1991
+ onClick: $event => (_ctx.deleteClaudeConfig(name)),
1992
+ "aria-label": _ctx.t('claude.action.deleteAria', { name }),
1993
+ title: _ctx.t('claude.action.delete')
1994
+ }, [
1995
+ (_openBlock(), _createElementBlock("svg", {
1996
+ viewBox: "0 0 24 24",
1997
+ fill: "none",
1998
+ stroke: "currentColor",
1999
+ "stroke-width": "2"
2000
+ }, [
2001
+ _createElementVNode("path", { d: "M3 6h18" }),
2002
+ _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" })
2003
+ ]))
2004
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"])
2005
+ ], 8 /* PROPS */, ["onClick"])
2006
+ ])
2007
+ ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "aria-current"]))
2008
+ }), 128 /* KEYED_FRAGMENT */))
2009
+ ])
1721
2010
  ]),
1722
- (_ctx.claudeModelHasList)
1723
- ? _withDirectives((_openBlock(), _createElementBlock("input", {
2011
+ (!_ctx.isToolConfigWriteAllowed('claude'))
2012
+ ? (_openBlock(), _createElementBlock("div", {
1724
2013
  key: 0,
1725
- class: "model-input",
1726
- "onUpdate:modelValue": $event => ((_ctx.currentClaudeModel) = $event),
1727
- onChange: _ctx.onClaudeModelChange,
1728
- onBlur: _ctx.onClaudeModelChange,
1729
- onKeyup: _withKeys(_ctx.onClaudeModelChange, ["enter"]),
1730
- placeholder: _ctx.t('claude.model.placeholder'),
1731
- readonly: _ctx.currentClaudeConfig === 'claude-local',
1732
- list: "claude-model-options"
1733
- }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onChange", "onBlur", "onKeyup", "placeholder", "readonly"])), [
1734
- [_vModelText, _ctx.currentClaudeModel]
1735
- ])
1736
- : _createCommentVNode("v-if", true),
1737
- (_ctx.claudeModelHasList)
1738
- ? (_openBlock(), _createElementBlock("datalist", {
1739
- key: 1,
1740
- id: "claude-model-options"
2014
+ class: "tool-config-write-overlay"
1741
2015
  }, [
1742
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.claudeModelOptions, (model) => {
1743
- return (_openBlock(), _createElementBlock("option", {
1744
- key: model,
1745
- value: model
1746
- }, null, 8 /* PROPS */, ["value"]))
1747
- }), 128 /* KEYED_FRAGMENT */))
2016
+ _createElementVNode("div", { class: "tool-config-write-overlay-card" }, [
2017
+ _createElementVNode("div", { class: "tool-config-write-overlay-title" }, _toDisplayString(_ctx.t('toolConfig.claude.lockedTitle')), 1 /* TEXT */),
2018
+ _createElementVNode("p", null, _toDisplayString(_ctx.t('toolConfig.claude.lockedDesc')), 1 /* TEXT */),
2019
+ _createElementVNode("button", {
2020
+ type: "button",
2021
+ class: "btn-tool",
2022
+ onClick: $event => (_ctx.setToolConfigPermission('claude', true)),
2023
+ disabled: _ctx.toolConfigPermissionSaving.claude
2024
+ }, _toDisplayString(_ctx.t('toolConfig.enableWrite')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
2025
+ ])
1748
2026
  ]))
1749
- : _withDirectives((_openBlock(), _createElementBlock("input", {
1750
- key: 2,
1751
- class: "model-input",
1752
- "onUpdate:modelValue": $event => ((_ctx.currentClaudeModel) = $event),
1753
- onBlur: _ctx.onClaudeModelChange,
1754
- onKeyup: _withKeys(_ctx.onClaudeModelChange, ["enter"]),
1755
- placeholder: _ctx.t('claude.model.placeholder'),
1756
- readonly: _ctx.currentClaudeConfig === 'claude-local'
1757
- }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onBlur", "onKeyup", "placeholder", "readonly"])), [
1758
- [_vModelText, _ctx.currentClaudeModel]
1759
- ]),
1760
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('claude.model.hint')), 1 /* TEXT */),
1761
- _createElementVNode("button", {
1762
- class: "btn-tool btn-template-editor",
1763
- onClick: _ctx.openClaudeConfigTemplateEditor,
1764
- disabled: _ctx.loading || !!_ctx.initError
1765
- }, _toDisplayString(_ctx.t('config.template.openEditor')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
1766
- ]),
1767
- _createElementVNode("div", { class: "selector-section" }, [
1768
- _createElementVNode("div", { class: "selector-header" }, [
1769
- _createElementVNode("span", { class: "selector-title" }, "CLAUDE.md")
1770
- ]),
2027
+ : _createCommentVNode("v-if", true)
2028
+ ], 2 /* CLASS */)
2029
+ ], 64 /* STABLE_FRAGMENT */))
2030
+ ], 8 /* PROPS */, ["aria-labelledby"]), [
2031
+ [_vShow, _ctx.mainTab === 'config' && _ctx.configMode === 'claude']
2032
+ ]),
2033
+ _createCommentVNode(" OpenClaw 配置模式 "),
2034
+ _withDirectives(_createElementVNode("div", {
2035
+ class: "mode-content mode-cards",
2036
+ id: "panel-config-openclaw",
2037
+ role: "tabpanel",
2038
+ "aria-labelledby": _ctx.forceCompactLayout ? 'tab-config' : 'side-tab-config-openclaw'
2039
+ }, [
2040
+ (_ctx.forceCompactLayout && !_ctx.sessionStandalone)
2041
+ ? (_openBlock(), _createElementBlock("div", {
2042
+ key: 0,
2043
+ class: "segmented-control"
2044
+ }, [
2045
+ _createElementVNode("button", {
2046
+ type: "button",
2047
+ class: _normalizeClass(['segment', { active: _ctx.configMode === 'codex' }]),
2048
+ onClick: $event => (_ctx.switchConfigMode('codex'))
2049
+ }, _toDisplayString(_ctx.t('tab.config.codex')), 11 /* TEXT, CLASS, PROPS */, ["onClick"]),
2050
+ _createElementVNode("button", {
2051
+ type: "button",
2052
+ class: _normalizeClass(['segment', { active: _ctx.configMode === 'claude' }]),
2053
+ onClick: $event => (_ctx.switchConfigMode('claude'))
2054
+ }, _toDisplayString(_ctx.t('tab.config.claude')), 11 /* TEXT, CLASS, PROPS */, ["onClick"]),
2055
+ _createElementVNode("button", {
2056
+ type: "button",
2057
+ class: _normalizeClass(['segment', { active: _ctx.configMode === 'openclaw' }]),
2058
+ onClick: $event => (_ctx.switchConfigMode('openclaw'))
2059
+ }, _toDisplayString(_ctx.t('tab.config.openclaw')), 11 /* TEXT, CLASS, PROPS */, ["onClick"])
2060
+ ]))
2061
+ : _createCommentVNode("v-if", true),
2062
+ _createElementVNode("div", { class: "openclaw-layout" }, [
2063
+ _createElementVNode("section", { class: "settings-card settings-card--wide openclaw-workspace-card" }, [
2064
+ _createElementVNode("div", { class: "settings-card-body" }, [
2065
+ _createElementVNode("div", { class: "openclaw-tools-grid" }, [
1771
2066
  _createElementVNode("button", {
1772
- class: "btn-tool",
1773
- onClick: _ctx.openClaudeMdEditor,
2067
+ class: "openclaw-tool-btn",
2068
+ onClick: _ctx.openOpenclawAgentsEditor,
1774
2069
  disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
1775
- }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('claude.md.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1776
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('claude.md.hint')), 1 /* TEXT */)
1777
- ]),
1778
- _createElementVNode("div", { class: "selector-section" }, [
1779
- _createElementVNode("div", { class: "selector-header" }, [
1780
- _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('config.health.title')), 1 /* TEXT */)
1781
- ]),
1782
- _createElementVNode("button", {
1783
- class: "btn-tool",
1784
- onClick: _ctx.runHealthCheck,
1785
- disabled: _ctx.healthCheckLoading || _ctx.loading || !!_ctx.initError
1786
- }, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('config.health.running') : _ctx.t('config.health.run')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1787
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.health.hint')), 1 /* TEXT */)
1788
- ]),
1789
- _createElementVNode("div", { class: "card-list" }, [
1790
- _createElementVNode("div", {
1791
- class: _normalizeClass(['card', { active: _ctx.currentClaudeConfig === 'claude-local', disabled: _ctx.isClaudeLocalBridgeDisabled() }]),
1792
- onClick: $event => (_ctx.isClaudeLocalBridgeDisabled() ? null : _ctx.applyClaudeLocalBridge()),
1793
- onKeydown: [
1794
- _withKeys(_withModifiers($event => (_ctx.isClaudeLocalBridgeDisabled() ? null : _ctx.applyClaudeLocalBridge()), ["self","prevent"]), ["enter"]),
1795
- _withKeys(_withModifiers($event => (_ctx.isClaudeLocalBridgeDisabled() ? null : _ctx.applyClaudeLocalBridge()), ["self","prevent"]), ["space"])
1796
- ],
1797
- tabindex: _ctx.isClaudeLocalBridgeDisabled() ? -1 : 0,
1798
- role: "button",
1799
- "aria-current": _ctx.currentClaudeConfig === 'claude-local' ? 'true' : null
1800
2070
  }, [
1801
- _createElementVNode("div", { class: "card-leading" }, [
1802
- _createElementVNode("div", { class: "card-icon" }, "L"),
1803
- _createElementVNode("div", { class: "card-content" }, [
1804
- _createElementVNode("div", { class: "bridge-pool-summary" }, [
1805
- (_openBlock(), _createElementBlock("svg", {
1806
- class: "bridge-pool-summary-icon",
1807
- viewBox: "0 0 24 24",
1808
- fill: "none",
1809
- stroke: "currentColor",
1810
- "stroke-width": "2",
1811
- width: "12",
1812
- height: "12"
1813
- }, [
1814
- _createElementVNode("circle", {
1815
- cx: "6",
1816
- cy: "6",
1817
- r: "2"
1818
- }),
1819
- _createElementVNode("circle", {
1820
- cx: "18",
1821
- cy: "6",
1822
- r: "2"
1823
- }),
1824
- _createElementVNode("circle", {
1825
- cx: "12",
1826
- cy: "18",
1827
- r: "2"
1828
- }),
1829
- _createElementVNode("path", { d: "M6 8v4h6v4" }),
1830
- _createElementVNode("path", { d: "M18 8v4h-6v4" })
1831
- ])),
1832
- _createElementVNode("span", { class: "bridge-pool-summary-text" }, _toDisplayString(_ctx.t('claude.localBridge.enabled')) + " " + _toDisplayString(_ctx.claudeLocalBridgeCandidateProviders().filter(cp => !_ctx.isClaudeLocalBridgeExcluded(cp.name)).length) + " / " + _toDisplayString(_ctx.claudeLocalBridgeCandidateProviders().length), 1 /* TEXT */)
1833
- ]),
1834
- _createElementVNode("div", { class: "card-title" }, [
1835
- _createElementVNode("span", null, "local"),
1836
- _createElementVNode("span", { class: "provider-readonly-badge" }, _toDisplayString(_ctx.t('config.badge.system')), 1 /* TEXT */)
1837
- ])
1838
- ])
2071
+ _createElementVNode("div", { class: "tool-icon" }, "📄"),
2072
+ _createElementVNode("div", { class: "tool-content" }, [
2073
+ _createElementVNode("div", { class: "tool-title" }, "AGENTS.md"),
2074
+ _createElementVNode("div", { class: "tool-meta" }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('openclaw.agents.hint')), 1 /* TEXT */)
1839
2075
  ]),
1840
- _createElementVNode("div", { class: "card-trailing" }, [
1841
- _createElementVNode("span", {
1842
- class: _normalizeClass(['pill', _ctx.claudeLocalBridgeConfigured() ? 'configured' : 'empty'])
1843
- }, _toDisplayString(_ctx.claudeLocalBridgeConfigured() ? _ctx.t('claude.configured') : _ctx.t('claude.notConfigured')), 3 /* TEXT, CLASS */),
1844
- _createElementVNode("div", {
1845
- class: "card-actions",
1846
- onClick: _withModifiers(() => {}, ["stop"])
1847
- }, [
1848
- _createElementVNode("button", {
1849
- class: "card-action-btn bridge-pool-trigger",
1850
- onClick: $event => (_ctx.showClaudeBridgePoolModal = true),
1851
- "aria-label": _ctx.t('claude.localBridge.poolTitle'),
1852
- title: _ctx.t('claude.localBridge.poolTitle')
1853
- }, [
1854
- (_openBlock(), _createElementBlock("svg", {
1855
- viewBox: "0 0 24 24",
1856
- fill: "none",
1857
- stroke: "currentColor",
1858
- "stroke-width": "2"
1859
- }, [
1860
- _createElementVNode("circle", {
1861
- cx: "6",
1862
- cy: "6",
1863
- r: "2"
1864
- }),
1865
- _createElementVNode("circle", {
1866
- cx: "18",
1867
- cy: "6",
1868
- r: "2"
1869
- }),
1870
- _createElementVNode("circle", {
1871
- cx: "12",
1872
- cy: "18",
1873
- r: "2"
1874
- }),
1875
- _createElementVNode("path", { d: "M6 8v4h6v4" }),
1876
- _createElementVNode("path", { d: "M18 8v4h-6v4" })
1877
- ]))
1878
- ], 8 /* PROPS */, ["onClick", "aria-label", "title"])
1879
- ], 8 /* PROPS */, ["onClick"])
1880
- ])
1881
- ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "tabindex", "aria-current"]),
1882
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.claudeConfigs, (config, name) => {
2076
+ (_openBlock(), _createElementBlock("svg", {
2077
+ class: "tool-chevron",
2078
+ viewBox: "0 0 24 24",
2079
+ fill: "none",
2080
+ stroke: "currentColor",
2081
+ "stroke-width": "2"
2082
+ }, [
2083
+ _createElementVNode("path", { d: "M9 18l6-6-6-6" })
2084
+ ]))
2085
+ ], 8 /* PROPS */, ["onClick", "disabled"]),
2086
+ _createElementVNode("div", { class: "openclaw-workspace-card" }, [
2087
+ _createElementVNode("label", {
2088
+ class: "workspace-label",
2089
+ for: "openclaw-workspace-file"
2090
+ }, _toDisplayString(_ctx.t('openclaw.workspaceFile')), 1 /* TEXT */),
2091
+ _createElementVNode("div", { class: "workspace-input-group" }, [
2092
+ _withDirectives(_createElementVNode("input", {
2093
+ id: "openclaw-workspace-file",
2094
+ class: "form-input",
2095
+ "onUpdate:modelValue": $event => ((_ctx.openclawWorkspaceFileName) = $event),
2096
+ placeholder: _ctx.t('openclaw.workspace.placeholder')
2097
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
2098
+ [_vModelText, _ctx.openclawWorkspaceFileName]
2099
+ ]),
2100
+ _createElementVNode("button", {
2101
+ class: "btn-tool",
2102
+ onClick: _ctx.openOpenclawWorkspaceEditor,
2103
+ disabled: _ctx.loading || !!_ctx.initError || _ctx.agentsLoading
2104
+ }, _toDisplayString(_ctx.agentsLoading ? _ctx.t('config.modelLoading') : _ctx.t('openclaw.workspace.open')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
2105
+ ]),
2106
+ _createElementVNode("div", { class: "workspace-meta" }, _toDisplayString(_ctx.t('openclaw.workspace.hint')), 1 /* TEXT */)
2107
+ ])
2108
+ ])
2109
+ ])
2110
+ ]),
2111
+ _createElementVNode("section", {
2112
+ class: "settings-card settings-card--wide openclaw-configs-card",
2113
+ "aria-labelledby": "openclaw-configs-title"
2114
+ }, [
2115
+ _createElementVNode("div", { class: "settings-card-body" }, [
2116
+ _createElementVNode("div", { class: "card-list openclaw-card-list" }, [
2117
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.openclawConfigs, (config, name) => {
1883
2118
  return (_openBlock(), _createElementBlock("div", {
1884
2119
  key: name,
1885
- class: _normalizeClass(['card', { active: _ctx.currentClaudeConfig === name }]),
1886
- onClick: $event => (_ctx.applyClaudeConfig(name)),
2120
+ class: _normalizeClass(['card', { active: _ctx.currentOpenclawConfig === name }]),
2121
+ onClick: $event => (_ctx.applyOpenclawConfig(name)),
1887
2122
  onKeydown: [
1888
- _withKeys(_withModifiers($event => (_ctx.applyClaudeConfig(name)), ["self","prevent"]), ["enter"]),
1889
- _withKeys(_withModifiers($event => (_ctx.applyClaudeConfig(name)), ["self","prevent"]), ["space"])
2123
+ _withKeys(_withModifiers($event => (_ctx.applyOpenclawConfig(name)), ["self","prevent"]), ["enter"]),
2124
+ _withKeys(_withModifiers($event => (_ctx.applyOpenclawConfig(name)), ["self","prevent"]), ["space"])
1890
2125
  ],
1891
2126
  tabindex: "0",
1892
2127
  role: "button",
1893
- "aria-current": _ctx.currentClaudeConfig === name ? 'true' : null
2128
+ "aria-label": _ctx.t('openclaw.action.applyAria', { name }),
2129
+ "aria-current": _ctx.currentOpenclawConfig === name ? 'true' : null
1894
2130
  }, [
1895
2131
  _createElementVNode("div", { class: "card-leading" }, [
1896
2132
  _createElementVNode("div", { class: "card-icon" }, _toDisplayString(name.charAt(0).toUpperCase()), 1 /* TEXT */),
1897
2133
  _createElementVNode("div", { class: "card-content" }, [
1898
2134
  _createElementVNode("div", { class: "card-title" }, _toDisplayString(name), 1 /* TEXT */),
1899
- _createElementVNode("div", { class: "card-subtitle card-subtitle-model" }, _toDisplayString(config.model || _ctx.t('claude.model.unset')), 1 /* TEXT */),
1900
- (config.baseUrl)
1901
- ? (_openBlock(), _createElementBlock("div", {
1902
- key: 0,
1903
- class: "card-subtitle card-subtitle-url"
1904
- }, _toDisplayString(config.baseUrl), 1 /* TEXT */))
1905
- : _createCommentVNode("v-if", true)
2135
+ _createElementVNode("div", { class: "card-subtitle" }, _toDisplayString(_ctx.openclawSubtitle(config)), 1 /* TEXT */)
1906
2136
  ])
1907
2137
  ]),
1908
2138
  _createElementVNode("div", { class: "card-trailing" }, [
1909
- (_ctx.claudeSpeedResults[name])
1910
- ? (_openBlock(), _createElementBlock("span", {
1911
- key: 0,
1912
- class: _normalizeClass(['latency', _ctx.claudeSpeedResults[name].ok ? 'ok' : 'error'])
1913
- }, _toDisplayString(_ctx.formatLatency(_ctx.claudeSpeedResults[name])), 3 /* TEXT, CLASS */))
1914
- : _createCommentVNode("v-if", true),
1915
2139
  _createElementVNode("span", {
1916
- class: _normalizeClass(['pill', config.hasKey ? 'configured' : 'empty'])
1917
- }, _toDisplayString(config.hasKey ? _ctx.t('claude.configured') : _ctx.t('claude.notConfigured')), 3 /* TEXT, CLASS */),
2140
+ class: _normalizeClass(['pill', _ctx.openclawHasContent(config) ? 'configured' : 'empty'])
2141
+ }, _toDisplayString(_ctx.openclawHasContent(config) ? _ctx.t('openclaw.configured') : _ctx.t('openclaw.notConfigured')), 3 /* TEXT, CLASS */),
1918
2142
  _createElementVNode("div", {
1919
2143
  class: "card-actions",
1920
2144
  onClick: _withModifiers(() => {}, ["stop"])
1921
2145
  }, [
1922
2146
  _createElementVNode("button", {
1923
2147
  class: "card-action-btn",
1924
- onClick: $event => (_ctx.openEditConfigModal(name)),
1925
- "aria-label": _ctx.t('claude.action.editAria', { name }),
1926
- title: _ctx.t('claude.action.edit')
2148
+ onClick: $event => (_ctx.openOpenclawEditModal(name)),
2149
+ "aria-label": _ctx.t('openclaw.action.editAria', { name }),
2150
+ title: _ctx.t('openclaw.action.edit')
1927
2151
  }, [
1928
2152
  (_openBlock(), _createElementBlock("svg", {
1929
2153
  viewBox: "0 0 24 24",
@@ -1935,201 +2159,32 @@ return function render(_ctx, _cache) {
1935
2159
  _createElementVNode("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
1936
2160
  ]))
1937
2161
  ], 8 /* PROPS */, ["onClick", "aria-label", "title"]),
1938
- _createElementVNode("button", {
1939
- class: "card-action-btn",
1940
- onClick: $event => (_ctx.openCloneClaudeConfigModal(name, config)),
1941
- "aria-label": _ctx.t('claude.action.cloneAria', { name }),
1942
- title: _ctx.t('claude.action.clone')
1943
- }, [
1944
- (_openBlock(), _createElementBlock("svg", {
1945
- viewBox: "0 0 24 24",
1946
- fill: "none",
1947
- stroke: "currentColor",
1948
- "stroke-width": "2"
1949
- }, [
1950
- _createElementVNode("rect", {
1951
- x: "9",
1952
- y: "9",
1953
- width: "13",
1954
- height: "13",
1955
- rx: "2"
1956
- }),
1957
- _createElementVNode("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
1958
- ]))
1959
- ], 8 /* PROPS */, ["onClick", "aria-label", "title"]),
1960
- _createElementVNode("button", {
1961
- class: _normalizeClass(["card-action-btn", { loading: _ctx.claudeShareLoading[name] }]),
1962
- onClick: $event => (_ctx.copyClaudeShareCommand(name)),
1963
- title: _ctx.t('config.shareCommand'),
1964
- "aria-label": _ctx.t('config.shareCommand.aria')
1965
- }, [
1966
- (_openBlock(), _createElementBlock("svg", {
1967
- viewBox: "0 0 24 24",
1968
- fill: "none",
1969
- stroke: "currentColor",
1970
- "stroke-width": "2"
1971
- }, [
1972
- _createElementVNode("path", { d: "M4 12v7a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-7" }),
1973
- _createElementVNode("path", { d: "M16 6l-4-4-4 4" }),
1974
- _createElementVNode("path", { d: "M12 2v14" })
1975
- ]))
1976
- ], 10 /* CLASS, PROPS */, ["onClick", "title", "aria-label"]),
1977
- _createElementVNode("button", {
1978
- class: "card-action-btn delete",
1979
- onClick: $event => (_ctx.deleteClaudeConfig(name)),
1980
- "aria-label": _ctx.t('claude.action.deleteAria', { name }),
1981
- title: _ctx.t('claude.action.delete')
1982
- }, [
1983
- (_openBlock(), _createElementBlock("svg", {
1984
- viewBox: "0 0 24 24",
1985
- fill: "none",
1986
- stroke: "currentColor",
1987
- "stroke-width": "2"
1988
- }, [
1989
- _createElementVNode("path", { d: "M3 6h18" }),
1990
- _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" })
1991
- ]))
1992
- ], 8 /* PROPS */, ["onClick", "aria-label", "title"])
2162
+ (!_ctx.isDefaultOpenclawConfig(name, config))
2163
+ ? (_openBlock(), _createElementBlock("button", {
2164
+ key: 0,
2165
+ class: "card-action-btn delete",
2166
+ onClick: $event => (_ctx.deleteOpenclawConfig(name)),
2167
+ "aria-label": _ctx.t('openclaw.action.deleteAria', { name }),
2168
+ title: _ctx.t('openclaw.action.delete')
2169
+ }, [
2170
+ (_openBlock(), _createElementBlock("svg", {
2171
+ viewBox: "0 0 24 24",
2172
+ fill: "none",
2173
+ stroke: "currentColor",
2174
+ "stroke-width": "2"
2175
+ }, [
2176
+ _createElementVNode("path", { d: "M3 6h18" }),
2177
+ _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" })
2178
+ ]))
2179
+ ], 8 /* PROPS */, ["onClick", "aria-label", "title"]))
2180
+ : _createCommentVNode("v-if", true)
1993
2181
  ], 8 /* PROPS */, ["onClick"])
1994
2182
  ])
1995
- ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "aria-current"]))
2183
+ ], 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onClick", "onKeydown", "aria-label", "aria-current"]))
1996
2184
  }), 128 /* KEYED_FRAGMENT */))
1997
2185
  ])
1998
- ], 64 /* STABLE_FRAGMENT */))
1999
- ], 8 /* PROPS */, ["aria-labelledby"]), [
2000
- [_vShow, _ctx.mainTab === 'config' && _ctx.configMode === 'claude']
2001
- ]),
2002
- _createCommentVNode(" OpenClaw 配置模式 "),
2003
- _withDirectives(_createElementVNode("div", {
2004
- class: "mode-content mode-cards",
2005
- id: "panel-config-openclaw",
2006
- role: "tabpanel",
2007
- "aria-labelledby": _ctx.forceCompactLayout ? 'tab-config' : 'side-tab-config-openclaw'
2008
- }, [
2009
- (_ctx.forceCompactLayout && !_ctx.sessionStandalone)
2010
- ? (_openBlock(), _createElementBlock("div", {
2011
- key: 0,
2012
- class: "segmented-control"
2013
- }, [
2014
- _createElementVNode("button", {
2015
- type: "button",
2016
- class: _normalizeClass(['segment', { active: _ctx.configMode === 'codex' }]),
2017
- onClick: $event => (_ctx.switchConfigMode('codex'))
2018
- }, _toDisplayString(_ctx.t('tab.config.codex')), 11 /* TEXT, CLASS, PROPS */, ["onClick"]),
2019
- _createElementVNode("button", {
2020
- type: "button",
2021
- class: _normalizeClass(['segment', { active: _ctx.configMode === 'claude' }]),
2022
- onClick: $event => (_ctx.switchConfigMode('claude'))
2023
- }, _toDisplayString(_ctx.t('tab.config.claude')), 11 /* TEXT, CLASS, PROPS */, ["onClick"]),
2024
- _createElementVNode("button", {
2025
- type: "button",
2026
- class: _normalizeClass(['segment', { active: _ctx.configMode === 'openclaw' }]),
2027
- onClick: $event => (_ctx.switchConfigMode('openclaw'))
2028
- }, _toDisplayString(_ctx.t('tab.config.openclaw')), 11 /* TEXT, CLASS, PROPS */, ["onClick"])
2029
- ]))
2030
- : _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"])
2093
- }, [
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')
2099
- }, [
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')
2117
- }, [
2118
- (_openBlock(), _createElementBlock("svg", {
2119
- viewBox: "0 0 24 24",
2120
- fill: "none",
2121
- stroke: "currentColor",
2122
- "stroke-width": "2"
2123
- }, [
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 */))
2186
+ ])
2187
+ ])
2133
2188
  ])
2134
2189
  ], 8 /* PROPS */, ["aria-labelledby"]), [
2135
2190
  [_vShow, _ctx.mainTab === 'config' && _ctx.configMode === 'openclaw']
@@ -4014,6 +4069,36 @@ return function render(_ctx, _cache) {
4014
4069
  "aria-labelledby": "settings-tab-general"
4015
4070
  }, [
4016
4071
  _createElementVNode("div", { class: "settings-grid" }, [
4072
+ _createElementVNode("section", {
4073
+ id: "settings-language",
4074
+ class: "settings-card",
4075
+ "aria-label": _ctx.t('settings.language.title')
4076
+ }, [
4077
+ _createElementVNode("div", { class: "settings-card-main" }, [
4078
+ _createElementVNode("div", { class: "settings-card-content" }, [
4079
+ _createElementVNode("div", { class: "settings-card-title" }, _toDisplayString(_ctx.t('settings.language.title')), 1 /* TEXT */),
4080
+ _createElementVNode("p", { class: "settings-card-desc" }, _toDisplayString(_ctx.t('settings.language.meta')), 1 /* TEXT */),
4081
+ _createElementVNode("label", {
4082
+ class: "selector-label",
4083
+ for: "settings-language-select"
4084
+ }, _toDisplayString(_ctx.t('settings.language.label')), 1 /* TEXT */),
4085
+ _createElementVNode("select", {
4086
+ id: "settings-language-select",
4087
+ class: "model-select settings-language-select",
4088
+ value: _ctx.lang,
4089
+ onChange: $event => (_ctx.setLang($event.target.value))
4090
+ }, [
4091
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.languageOptions(), (option) => {
4092
+ return (_openBlock(), _createElementBlock("option", {
4093
+ key: option.code,
4094
+ value: option.code
4095
+ }, _toDisplayString(option.nativeName) + " · " + _toDisplayString(option.englishName), 9 /* TEXT, PROPS */, ["value"]))
4096
+ }), 128 /* KEYED_FRAGMENT */))
4097
+ ], 40 /* PROPS, NEED_HYDRATION */, ["value", "onChange"]),
4098
+ _createElementVNode("p", { class: "settings-card-hint" }, _toDisplayString(_ctx.t('settings.language.hint')), 1 /* TEXT */)
4099
+ ])
4100
+ ])
4101
+ ], 8 /* PROPS */, ["aria-label"]),
4017
4102
  _createElementVNode("section", {
4018
4103
  class: "settings-card",
4019
4104
  "aria-label": _ctx.t('settings.sharePrefix.title')
@@ -4064,17 +4149,17 @@ return function render(_ctx, _cache) {
4064
4149
  ], 8 /* PROPS */, ["aria-label"]),
4065
4150
  _createElementVNode("section", {
4066
4151
  class: "settings-card",
4067
- "aria-label": 'Webhook'
4152
+ "aria-label": _ctx.t('settings.webhook.title')
4068
4153
  }, [
4069
4154
  _createElementVNode("div", { class: "settings-card-main" }, [
4070
4155
  _createElementVNode("div", { class: "settings-card-content" }, [
4071
- _createElementVNode("div", { class: "settings-card-title" }, "Webhook"),
4072
- _createElementVNode("p", { class: "settings-card-desc" }, "配置变更时外发通知"),
4156
+ _createElementVNode("div", { class: "settings-card-title" }, _toDisplayString(_ctx.t('settings.webhook.title')), 1 /* TEXT */),
4157
+ _createElementVNode("p", { class: "settings-card-desc" }, _toDisplayString(_ctx.t('settings.webhook.meta')), 1 /* TEXT */),
4073
4158
  _createElementVNode("div", { class: "webhook-status" }, [
4074
4159
  _createElementVNode("span", {
4075
4160
  class: _normalizeClass(["webhook-status-dot", { active: _ctx.webhookConfig.enabled }])
4076
4161
  }, null, 2 /* CLASS */),
4077
- _createElementVNode("span", { class: "webhook-status-label" }, _toDisplayString(_ctx.webhookConfig.enabled ? '已启用' : '已禁用'), 1 /* TEXT */),
4162
+ _createElementVNode("span", { class: "webhook-status-label" }, _toDisplayString(_ctx.webhookConfig.enabled ? _ctx.t('settings.webhook.enabled') : _ctx.t('settings.webhook.disabled')), 1 /* TEXT */),
4078
4163
  (_ctx.webhookConfig.url)
4079
4164
  ? (_openBlock(), _createElementBlock("code", {
4080
4165
  key: 0,
@@ -4089,10 +4174,10 @@ return function render(_ctx, _cache) {
4089
4174
  onClick: _ctx.openWebhookModal
4090
4175
  }, [
4091
4176
  (_ctx.webhookConfig.enabled)
4092
- ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.webhookConfig.url ? '编辑' : '配置'), 1 /* TEXT */))
4093
- : (_openBlock(), _createElementBlock("span", { key: 1 }, "启用"))
4177
+ ? (_openBlock(), _createElementBlock("span", { key: 0 }, _toDisplayString(_ctx.webhookConfig.url ? _ctx.t('settings.webhook.edit') : _ctx.t('settings.webhook.configure')), 1 /* TEXT */))
4178
+ : (_openBlock(), _createElementBlock("span", { key: 1 }, _toDisplayString(_ctx.t('settings.webhook.enable')), 1 /* TEXT */))
4094
4179
  ], 10 /* CLASS, PROPS */, ["onClick"])
4095
- ])
4180
+ ], 8 /* PROPS */, ["aria-label"])
4096
4181
  ])
4097
4182
  ], 512 /* NEED_PATCH */), [
4098
4183
  [_vShow, _ctx.settingsTab === 'general']
@@ -4174,7 +4259,7 @@ return function render(_ctx, _cache) {
4174
4259
  onChange: $event => (_ctx.setSessionTrashRetentionDays(Number($event.target.value))),
4175
4260
  class: "settings-retention-input"
4176
4261
  }, null, 40 /* PROPS, NEED_HYDRATION */, ["value", "onChange"]),
4177
- _createElementVNode("span", null, "天")
4262
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('settings.trash.retentionUnit')), 1 /* TEXT */)
4178
4263
  ]),
4179
4264
  _createElementVNode("p", { class: "settings-card-hint" }, _toDisplayString(_ctx.t('settings.trash.retentionHint')), 1 /* TEXT */)
4180
4265
  ])
@@ -4204,7 +4289,7 @@ return function render(_ctx, _cache) {
4204
4289
  ], 512 /* NEED_PATCH */), [
4205
4290
  [_vShow, _ctx.mainTab === 'settings']
4206
4291
  ]),
4207
- _createCommentVNode(" 回收站面板 "),
4292
+ _createCommentVNode(" Trash panel "),
4208
4293
  _withDirectives(_createElementVNode("div", {
4209
4294
  class: "mode-content",
4210
4295
  id: "panel-trash",
@@ -4216,7 +4301,7 @@ return function render(_ctx, _cache) {
4216
4301
  key: 0,
4217
4302
  class: "trash-panel-shell"
4218
4303
  }, [
4219
- _createCommentVNode(" 空态 "),
4304
+ _createCommentVNode(" Empty state "),
4220
4305
  (_ctx.getSessionTrashViewState() === 'empty')
4221
4306
  ? (_openBlock(), _createElementBlock("div", {
4222
4307
  key: 0,
@@ -4239,11 +4324,11 @@ return function render(_ctx, _cache) {
4239
4324
  })
4240
4325
  ])),
4241
4326
  _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 */)
4327
+ _createElementVNode("div", { class: "trash-empty-hint" }, _toDisplayString(_ctx.t('settings.trash.emptyHint', { days: _ctx.sessionTrashRetentionDays })), 1 /* TEXT */)
4243
4328
  ]))
4244
4329
  : (_ctx.getSessionTrashViewState() === 'loading')
4245
4330
  ? (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
4246
- _createCommentVNode(" 加载态 "),
4331
+ _createCommentVNode(" Loading state "),
4247
4332
  _createElementVNode("div", { class: "trash-empty-state" }, [
4248
4333
  _createElementVNode("div", { class: "trash-spinner" }),
4249
4334
  _createElementVNode("div", { class: "trash-empty-title" }, _toDisplayString(_ctx.t('settings.trash.loading')), 1 /* TEXT */)
@@ -4251,7 +4336,7 @@ return function render(_ctx, _cache) {
4251
4336
  ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
4252
4337
  : (_ctx.getSessionTrashViewState() === 'retry')
4253
4338
  ? (_openBlock(), _createElementBlock(_Fragment, { key: 2 }, [
4254
- _createCommentVNode(" 错误态 "),
4339
+ _createCommentVNode(" Error state "),
4255
4340
  _createElementVNode("div", { class: "trash-empty-state" }, [
4256
4341
  (_openBlock(), _createElementBlock("svg", {
4257
4342
  class: "trash-empty-svg",
@@ -4275,21 +4360,22 @@ return function render(_ctx, _cache) {
4275
4360
  _createElementVNode("button", {
4276
4361
  class: "btn-tool",
4277
4362
  onClick: $event => (_ctx.loadSessionTrash({ forceRefresh: true }))
4278
- }, "重试", 8 /* PROPS */, ["onClick"])
4363
+ }, _toDisplayString(_ctx.t('common.retry')), 9 /* TEXT, PROPS */, ["onClick"])
4279
4364
  ])
4280
4365
  ], 2112 /* STABLE_FRAGMENT, DEV_ROOT_FRAGMENT */))
4281
4366
  : (_openBlock(), _createElementBlock(_Fragment, { key: 3 }, [
4282
- _createCommentVNode(" 列表态 "),
4367
+ _createCommentVNode(" List state "),
4283
4368
  _createElementVNode("div", { class: "trash-toolbar" }, [
4284
4369
  _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 */)
4370
+ _createElementVNode("span", { class: "trash-toolbar-count" }, _toDisplayString(_ctx.t('settings.trash.count', { count: _ctx.sessionTrashCount })), 1 /* TEXT */),
4371
+ _createElementVNode("span", { class: "trash-toolbar-retention" }, _toDisplayString(_ctx.t('settings.trash.retentionShort', { days: _ctx.sessionTrashRetentionDays })), 1 /* TEXT */)
4287
4372
  ]),
4288
4373
  _createElementVNode("div", { class: "trash-toolbar-right" }, [
4289
4374
  _createElementVNode("button", {
4290
4375
  class: "btn-mini",
4291
4376
  onClick: $event => (_ctx.loadSessionTrash({ forceRefresh: true })),
4292
4377
  disabled: _ctx.sessionTrashLoading,
4378
+ "aria-label": _ctx.t('sessions.refresh'),
4293
4379
  title: _ctx.t('sessions.refresh')
4294
4380
  }, [
4295
4381
  (_openBlock(), _createElementBlock("svg", {
@@ -4301,12 +4387,12 @@ return function render(_ctx, _cache) {
4301
4387
  }, [
4302
4388
  _createElementVNode("path", { d: "M21 2v6h-6M3 12a9 9 0 0115-6.7L21 8M3 22v-6h6M21 12a9 9 0 01-15 6.7L3 16" })
4303
4389
  ]))
4304
- ], 8 /* PROPS */, ["onClick", "disabled", "title"]),
4390
+ ], 8 /* PROPS */, ["onClick", "disabled", "aria-label", "title"]),
4305
4391
  _createElementVNode("button", {
4306
4392
  class: "btn-mini delete",
4307
4393
  onClick: _ctx.clearSessionTrash,
4308
4394
  disabled: _ctx.sessionTrashClearing || _ctx.sessionTrashLoading || !(Number(_ctx.sessionTrashCount) > 0)
4309
- }, _toDisplayString(_ctx.sessionTrashClearing ? '清空中…' : '清空'), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4395
+ }, _toDisplayString(_ctx.sessionTrashClearing ? _ctx.t('settings.trash.clearing') : _ctx.t('settings.trash.clearShort')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4310
4396
  ])
4311
4397
  ]),
4312
4398
  _createElementVNode("div", { class: "trash-list" }, [
@@ -4337,7 +4423,8 @@ return function render(_ctx, _cache) {
4337
4423
  class: "trash-action-btn restore",
4338
4424
  onClick: $event => (_ctx.restoreSessionTrash(item)),
4339
4425
  disabled: _ctx.sessionTrashLoading || _ctx.sessionTrashClearing || _ctx.isSessionTrashActionBusy(item),
4340
- title: _ctx.sessionTrashRestoring[_ctx.getSessionTrashActionKey(item)] ? '恢复中…' : '恢复'
4426
+ "aria-label": _ctx.sessionTrashRestoring[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.restoring') : _ctx.t('settings.trash.restore'),
4427
+ title: _ctx.sessionTrashRestoring[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.restoring') : _ctx.t('settings.trash.restore')
4341
4428
  }, [
4342
4429
  (_openBlock(), _createElementBlock("svg", {
4343
4430
  viewBox: "0 0 24 24",
@@ -4348,12 +4435,13 @@ return function render(_ctx, _cache) {
4348
4435
  _createElementVNode("path", { d: "M3 12a9 9 0 119 9" }),
4349
4436
  _createElementVNode("path", { d: "M3 4v6h6" })
4350
4437
  ]))
4351
- ], 8 /* PROPS */, ["onClick", "disabled", "title"]),
4438
+ ], 8 /* PROPS */, ["onClick", "disabled", "aria-label", "title"]),
4352
4439
  _createElementVNode("button", {
4353
4440
  class: "trash-action-btn delete",
4354
4441
  onClick: $event => (_ctx.purgeSessionTrash(item)),
4355
4442
  disabled: _ctx.sessionTrashLoading || _ctx.sessionTrashClearing || _ctx.isSessionTrashActionBusy(item),
4356
- title: _ctx.sessionTrashPurging[_ctx.getSessionTrashActionKey(item)] ? '删除中…' : '彻底删除'
4443
+ "aria-label": _ctx.sessionTrashPurging[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.purging') : _ctx.t('settings.trash.purge'),
4444
+ title: _ctx.sessionTrashPurging[_ctx.getSessionTrashActionKey(item)] ? _ctx.t('settings.trash.purging') : _ctx.t('settings.trash.purge')
4357
4445
  }, [
4358
4446
  (_openBlock(), _createElementBlock("svg", {
4359
4447
  viewBox: "0 0 24 24",
@@ -4363,7 +4451,7 @@ return function render(_ctx, _cache) {
4363
4451
  }, [
4364
4452
  _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
4453
  ]))
4366
- ], 8 /* PROPS */, ["onClick", "disabled", "title"])
4454
+ ], 8 /* PROPS */, ["onClick", "disabled", "aria-label", "title"])
4367
4455
  ])
4368
4456
  ])
4369
4457
  ]))
@@ -4377,7 +4465,7 @@ return function render(_ctx, _cache) {
4377
4465
  class: "btn-tool btn-tool-compact",
4378
4466
  onClick: _ctx.loadMoreSessionTrashItems,
4379
4467
  disabled: _ctx.sessionTrashLoading || _ctx.sessionTrashClearing
4380
- }, " 加载更多(" + _toDisplayString(_ctx.sessionTrashHiddenCount) + " 条) ", 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4468
+ }, _toDisplayString(_ctx.t('settings.trash.loadMoreItems', { count: _ctx.sessionTrashHiddenCount })), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
4381
4469
  ]))
4382
4470
  : _createCommentVNode("v-if", true)
4383
4471
  ])
@@ -5280,15 +5368,81 @@ return function render(_ctx, _cache) {
5280
5368
  : _createCommentVNode("v-if", true)
5281
5369
  ]),
5282
5370
  _createElementVNode("div", { class: "form-group" }, [
5283
- _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiKey')), 1 /* TEXT */),
5371
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelName')), 1 /* TEXT */),
5284
5372
  _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
- ])
5373
+ "onUpdate:modelValue": $event => ((_ctx.newProvider.model) = $event),
5374
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.providerFieldError('add', 'model') }]),
5375
+ placeholder: _ctx.t('placeholder.modelExample'),
5376
+ autocomplete: "off",
5377
+ spellcheck: "false",
5378
+ onBlur: $event => (_ctx.normalizeProviderDraft('add'))
5379
+ }, null, 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onBlur"]), [
5380
+ [_vModelText, _ctx.newProvider.model]
5381
+ ]),
5382
+ (_ctx.providerFieldError('add', 'model'))
5383
+ ? (_openBlock(), _createElementBlock("div", {
5384
+ key: 0,
5385
+ class: "form-hint form-error"
5386
+ }, _toDisplayString(_ctx.providerFieldError('add', 'model')), 1 /* TEXT */))
5387
+ : _createCommentVNode("v-if", true)
5388
+ ]),
5389
+ _createElementVNode("div", { class: "form-group" }, [
5390
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiKey')), 1 /* TEXT */),
5391
+ _createElementVNode("div", { class: "input-with-toggle" }, [
5392
+ _withDirectives(_createElementVNode("input", {
5393
+ "onUpdate:modelValue": $event => ((_ctx.newProvider.key) = $event),
5394
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.providerFieldError('add', 'key') }]),
5395
+ type: _ctx.showAddProviderKey ? 'text' : 'password',
5396
+ placeholder: "sk-...",
5397
+ autocomplete: "off",
5398
+ spellcheck: "false",
5399
+ onBlur: $event => (_ctx.normalizeProviderDraft('add'))
5400
+ }, null, 42 /* CLASS, PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "type", "onBlur"]), [
5401
+ [_vModelDynamic, _ctx.newProvider.key]
5402
+ ]),
5403
+ _createElementVNode("button", {
5404
+ type: "button",
5405
+ class: "input-toggle-btn",
5406
+ onClick: _ctx.toggleAddProviderKey,
5407
+ title: _ctx.showAddProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5408
+ "aria-label": _ctx.showAddProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5409
+ }, [
5410
+ (!_ctx.showAddProviderKey)
5411
+ ? (_openBlock(), _createElementBlock("svg", {
5412
+ key: 0,
5413
+ viewBox: "0 0 20 20",
5414
+ fill: "none",
5415
+ stroke: "currentColor",
5416
+ "stroke-width": "1.5",
5417
+ width: "16",
5418
+ height: "16"
5419
+ }, [
5420
+ _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" }),
5421
+ _createElementVNode("circle", {
5422
+ cx: "10",
5423
+ cy: "10",
5424
+ r: "3"
5425
+ })
5426
+ ]))
5427
+ : (_openBlock(), _createElementBlock("svg", {
5428
+ key: 1,
5429
+ viewBox: "0 0 20 20",
5430
+ fill: "none",
5431
+ stroke: "currentColor",
5432
+ "stroke-width": "1.5",
5433
+ width: "16",
5434
+ height: "16"
5435
+ }, [
5436
+ _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" })
5437
+ ]))
5438
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5439
+ ]),
5440
+ (_ctx.providerFieldError('add', 'key'))
5441
+ ? (_openBlock(), _createElementBlock("div", {
5442
+ key: 0,
5443
+ class: "form-hint form-error"
5444
+ }, _toDisplayString(_ctx.providerFieldError('add', 'key')), 1 /* TEXT */))
5445
+ : _createCommentVNode("v-if", true)
5292
5446
  ]),
5293
5447
  _createElementVNode("div", { class: "form-group" }, [
5294
5448
  _createElementVNode("label", { class: "form-label" }, [
@@ -5379,7 +5533,8 @@ return function render(_ctx, _cache) {
5379
5533
  type: "button",
5380
5534
  class: "input-toggle-btn",
5381
5535
  onClick: _ctx.toggleEditProviderKey,
5382
- title: _ctx.showEditProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5536
+ title: _ctx.showEditProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5537
+ "aria-label": _ctx.showEditProviderKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5383
5538
  }, [
5384
5539
  (!_ctx.showEditProviderKey)
5385
5540
  ? (_openBlock(), _createElementBlock("svg", {
@@ -5409,7 +5564,7 @@ return function render(_ctx, _cache) {
5409
5564
  }, [
5410
5565
  _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
5566
  ]))
5412
- ], 8 /* PROPS */, ["onClick", "title"])
5567
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5413
5568
  ])
5414
5569
  ]),
5415
5570
  _createElementVNode("div", { class: "btn-group" }, [
@@ -5528,34 +5683,108 @@ return function render(_ctx, _cache) {
5528
5683
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.configName')), 1 /* TEXT */),
5529
5684
  _withDirectives(_createElementVNode("input", {
5530
5685
  "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.name) = $event),
5531
- class: "form-input",
5686
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'name') }]),
5532
5687
  placeholder: _ctx.t('placeholder.configNameExample')
5533
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5688
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5534
5689
  [_vModelText, _ctx.newClaudeConfig.name]
5535
- ])
5690
+ ]),
5691
+ (_ctx.claudeConfigFieldError('add', 'name'))
5692
+ ? (_openBlock(), _createElementBlock("div", {
5693
+ key: 0,
5694
+ class: "form-hint form-error"
5695
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'name')), 1 /* TEXT */))
5696
+ : _createCommentVNode("v-if", true)
5536
5697
  ]),
5537
- _createElementVNode("div", { class: "form-group" }, [
5538
- _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
- ])
5698
+ _createElementVNode("div", { class: "form-group" }, [
5699
+ _createElementVNode("label", { class: "form-label" }, "API Key"),
5700
+ _createElementVNode("div", { class: "input-with-toggle" }, [
5701
+ _withDirectives(_createElementVNode("input", {
5702
+ "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.apiKey) = $event),
5703
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'apiKey') }]),
5704
+ type: _ctx.showAddClaudeConfigKey ? 'text' : 'password',
5705
+ autocomplete: "off",
5706
+ spellcheck: "false",
5707
+ placeholder: _ctx.t('placeholder.apiKeyExampleClaude')
5708
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "type", "placeholder"]), [
5709
+ [_vModelDynamic, _ctx.newClaudeConfig.apiKey]
5710
+ ]),
5711
+ _createElementVNode("button", {
5712
+ type: "button",
5713
+ class: "input-toggle-btn",
5714
+ onClick: _ctx.toggleAddClaudeConfigKey,
5715
+ title: _ctx.showAddClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5716
+ "aria-label": _ctx.showAddClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5717
+ }, [
5718
+ (!_ctx.showAddClaudeConfigKey)
5719
+ ? (_openBlock(), _createElementBlock("svg", {
5720
+ key: 0,
5721
+ viewBox: "0 0 20 20",
5722
+ fill: "none",
5723
+ stroke: "currentColor",
5724
+ "stroke-width": "1.5",
5725
+ width: "16",
5726
+ height: "16"
5727
+ }, [
5728
+ _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" }),
5729
+ _createElementVNode("circle", {
5730
+ cx: "10",
5731
+ cy: "10",
5732
+ r: "3"
5733
+ })
5734
+ ]))
5735
+ : (_openBlock(), _createElementBlock("svg", {
5736
+ key: 1,
5737
+ viewBox: "0 0 20 20",
5738
+ fill: "none",
5739
+ stroke: "currentColor",
5740
+ "stroke-width": "1.5",
5741
+ width: "16",
5742
+ height: "16"
5743
+ }, [
5744
+ _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" })
5745
+ ]))
5746
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5747
+ ]),
5748
+ (_ctx.claudeConfigFieldError('add', 'apiKey'))
5749
+ ? (_openBlock(), _createElementBlock("div", {
5750
+ key: 0,
5751
+ class: "form-hint form-error"
5752
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'apiKey')), 1 /* TEXT */))
5753
+ : _createCommentVNode("v-if", true)
5549
5754
  ]),
5550
5755
  _createElementVNode("div", { class: "form-group" }, [
5551
5756
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
5552
5757
  _withDirectives(_createElementVNode("input", {
5553
5758
  "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.baseUrl) = $event),
5554
- class: "form-input",
5759
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'baseUrl') }]),
5555
5760
  placeholder: _ctx.t('placeholder.baseUrlExampleClaude')
5556
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5761
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5557
5762
  [_vModelText, _ctx.newClaudeConfig.baseUrl]
5558
- ])
5763
+ ]),
5764
+ (_ctx.claudeConfigFieldError('add', 'baseUrl'))
5765
+ ? (_openBlock(), _createElementBlock("div", {
5766
+ key: 0,
5767
+ class: "form-hint form-error"
5768
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'baseUrl')), 1 /* TEXT */))
5769
+ : _createCommentVNode("v-if", true)
5770
+ ]),
5771
+ _createElementVNode("div", { class: "form-group" }, [
5772
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelName')), 1 /* TEXT */),
5773
+ _withDirectives(_createElementVNode("input", {
5774
+ "onUpdate:modelValue": $event => ((_ctx.newClaudeConfig.model) = $event),
5775
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('add', 'model') }]),
5776
+ placeholder: _ctx.t('placeholder.modelExample'),
5777
+ autocomplete: "off",
5778
+ spellcheck: "false"
5779
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5780
+ [_vModelText, _ctx.newClaudeConfig.model]
5781
+ ]),
5782
+ (_ctx.claudeConfigFieldError('add', 'model'))
5783
+ ? (_openBlock(), _createElementBlock("div", {
5784
+ key: 0,
5785
+ class: "form-hint form-error"
5786
+ }, _toDisplayString(_ctx.claudeConfigFieldError('add', 'model')), 1 /* TEXT */))
5787
+ : _createCommentVNode("v-if", true)
5559
5788
  ]),
5560
5789
  _createElementVNode("div", { class: "btn-group" }, [
5561
5790
  _createElementVNode("button", {
@@ -5564,8 +5793,9 @@ return function render(_ctx, _cache) {
5564
5793
  }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"]),
5565
5794
  _createElementVNode("button", {
5566
5795
  class: "btn btn-confirm",
5567
- onClick: _ctx.addClaudeConfig
5568
- }, _toDisplayString(_ctx.t('common.add')), 9 /* TEXT, PROPS */, ["onClick"])
5796
+ onClick: _ctx.addClaudeConfig,
5797
+ disabled: !_ctx.canSubmitClaudeConfig('add')
5798
+ }, _toDisplayString(_ctx.t('common.add')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
5569
5799
  ])
5570
5800
  ])
5571
5801
  ], 8 /* PROPS */, ["onClick"]))
@@ -5591,31 +5821,38 @@ return function render(_ctx, _cache) {
5591
5821
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.configName')), 1 /* TEXT */),
5592
5822
  _withDirectives(_createElementVNode("input", {
5593
5823
  "onUpdate:modelValue": $event => ((_ctx.editingConfig.name) = $event),
5594
- class: "form-input",
5824
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'name') }]),
5595
5825
  placeholder: _ctx.t('field.configName'),
5596
5826
  readonly: ""
5597
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5827
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5598
5828
  [_vModelText, _ctx.editingConfig.name]
5599
- ])
5829
+ ]),
5830
+ (_ctx.claudeConfigFieldError('edit', 'name'))
5831
+ ? (_openBlock(), _createElementBlock("div", {
5832
+ key: 0,
5833
+ class: "form-hint form-error"
5834
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'name')), 1 /* TEXT */))
5835
+ : _createCommentVNode("v-if", true)
5600
5836
  ]),
5601
5837
  _createElementVNode("div", { class: "form-group" }, [
5602
5838
  _createElementVNode("label", { class: "form-label" }, "API Key"),
5603
5839
  _createElementVNode("div", { class: "input-with-toggle" }, [
5604
5840
  _withDirectives(_createElementVNode("input", {
5605
5841
  "onUpdate:modelValue": $event => ((_ctx.editingConfig.apiKey) = $event),
5606
- class: "form-input",
5842
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'apiKey') }]),
5607
5843
  type: _ctx.showEditClaudeConfigKey ? 'text' : 'password',
5608
5844
  autocomplete: "off",
5609
5845
  spellcheck: "false",
5610
5846
  placeholder: _ctx.t('placeholder.apiKeyExampleClaude')
5611
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "type", "placeholder"]), [
5847
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "type", "placeholder"]), [
5612
5848
  [_vModelDynamic, _ctx.editingConfig.apiKey]
5613
5849
  ]),
5614
5850
  _createElementVNode("button", {
5615
5851
  type: "button",
5616
5852
  class: "input-toggle-btn",
5617
5853
  onClick: _ctx.toggleEditClaudeConfigKey,
5618
- title: _ctx.showEditClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5854
+ title: _ctx.showEditClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show'),
5855
+ "aria-label": _ctx.showEditClaudeConfigKey ? _ctx.t('common.hide') : _ctx.t('common.show')
5619
5856
  }, [
5620
5857
  (!_ctx.showEditClaudeConfigKey)
5621
5858
  ? (_openBlock(), _createElementBlock("svg", {
@@ -5645,18 +5882,48 @@ return function render(_ctx, _cache) {
5645
5882
  }, [
5646
5883
  _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
5884
  ]))
5648
- ], 8 /* PROPS */, ["onClick", "title"])
5649
- ])
5885
+ ], 8 /* PROPS */, ["onClick", "title", "aria-label"])
5886
+ ]),
5887
+ (_ctx.claudeConfigFieldError('edit', 'apiKey'))
5888
+ ? (_openBlock(), _createElementBlock("div", {
5889
+ key: 0,
5890
+ class: "form-hint form-error"
5891
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'apiKey')), 1 /* TEXT */))
5892
+ : _createCommentVNode("v-if", true)
5650
5893
  ]),
5651
5894
  _createElementVNode("div", { class: "form-group" }, [
5652
5895
  _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
5653
5896
  _withDirectives(_createElementVNode("input", {
5654
5897
  "onUpdate:modelValue": $event => ((_ctx.editingConfig.baseUrl) = $event),
5655
- class: "form-input",
5898
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'baseUrl') }]),
5656
5899
  placeholder: _ctx.t('placeholder.baseUrlExampleClaude')
5657
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5900
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5658
5901
  [_vModelText, _ctx.editingConfig.baseUrl]
5659
- ])
5902
+ ]),
5903
+ (_ctx.claudeConfigFieldError('edit', 'baseUrl'))
5904
+ ? (_openBlock(), _createElementBlock("div", {
5905
+ key: 0,
5906
+ class: "form-hint form-error"
5907
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'baseUrl')), 1 /* TEXT */))
5908
+ : _createCommentVNode("v-if", true)
5909
+ ]),
5910
+ _createElementVNode("div", { class: "form-group" }, [
5911
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelName')), 1 /* TEXT */),
5912
+ _withDirectives(_createElementVNode("input", {
5913
+ "onUpdate:modelValue": $event => ((_ctx.editingConfig.model) = $event),
5914
+ class: _normalizeClass(['form-input', { invalid: !!_ctx.claudeConfigFieldError('edit', 'model') }]),
5915
+ placeholder: _ctx.t('placeholder.modelExample'),
5916
+ autocomplete: "off",
5917
+ spellcheck: "false"
5918
+ }, null, 10 /* CLASS, PROPS */, ["onUpdate:modelValue", "placeholder"]), [
5919
+ [_vModelText, _ctx.editingConfig.model]
5920
+ ]),
5921
+ (_ctx.claudeConfigFieldError('edit', 'model'))
5922
+ ? (_openBlock(), _createElementBlock("div", {
5923
+ key: 0,
5924
+ class: "form-hint form-error"
5925
+ }, _toDisplayString(_ctx.claudeConfigFieldError('edit', 'model')), 1 /* TEXT */))
5926
+ : _createCommentVNode("v-if", true)
5660
5927
  ]),
5661
5928
  _createElementVNode("div", { class: "btn-group" }, [
5662
5929
  _createElementVNode("button", {
@@ -5665,13 +5932,14 @@ return function render(_ctx, _cache) {
5665
5932
  }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"]),
5666
5933
  _createElementVNode("button", {
5667
5934
  class: "btn btn-confirm",
5668
- onClick: _ctx.saveAndApplyConfig
5669
- }, _toDisplayString(_ctx.t('common.saveApply')), 9 /* TEXT, PROPS */, ["onClick"])
5935
+ onClick: _ctx.saveAndApplyConfig,
5936
+ disabled: !_ctx.canSubmitClaudeConfig('edit')
5937
+ }, _toDisplayString(_ctx.t('common.saveApply')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
5670
5938
  ])
5671
5939
  ])
5672
5940
  ], 8 /* PROPS */, ["onClick"]))
5673
5941
  : _createCommentVNode("v-if", true),
5674
- _createCommentVNode(" Codex 轮询池控制模态框 "),
5942
+ _createCommentVNode(" Codex bridge pool modal "),
5675
5943
  (_ctx.showCodexBridgePoolModal)
5676
5944
  ? (_openBlock(), _createElementBlock("div", {
5677
5945
  key: 8,
@@ -5715,9 +5983,9 @@ return function render(_ctx, _cache) {
5715
5983
  _createElementVNode("path", { d: "M6 8v4h6v4" }),
5716
5984
  _createElementVNode("path", { d: "M18 8v4h-6v4" })
5717
5985
  ])),
5718
- _createTextVNode(" 轮询池设置 ")
5986
+ _createTextVNode(" " + _toDisplayString(_ctx.t('config.localBridge.poolSettings')), 1 /* TEXT */)
5719
5987
  ]),
5720
- _createElementVNode("div", { class: "bridge-pool-modal-hint" }, "勾选参与负载均衡的提供商"),
5988
+ _createElementVNode("div", { class: "bridge-pool-modal-hint" }, _toDisplayString(_ctx.t('config.localBridge.poolHint')), 1 /* TEXT */),
5721
5989
  (_ctx.localBridgeCandidateProviders().length === 0)
5722
5990
  ? (_openBlock(), _createElementBlock("div", {
5723
5991
  key: 0,
@@ -5733,7 +6001,7 @@ return function render(_ctx, _cache) {
5733
6001
  }, [
5734
6002
  _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
6003
  ])),
5736
- _createElementVNode("span", null, "暂无可用上游 provider,请先添加直连 provider")
6004
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('config.localBridge.noProviders')), 1 /* TEXT */)
5737
6005
  ]))
5738
6006
  : (_openBlock(), _createElementBlock("div", {
5739
6007
  key: 1,
@@ -5747,7 +6015,7 @@ return function render(_ctx, _cache) {
5747
6015
  _createElementVNode("span", { class: "bridge-pool-item-name" }, _toDisplayString(cp.name), 1 /* TEXT */),
5748
6016
  _createElementVNode("span", {
5749
6017
  class: _normalizeClass(["bridge-pool-item-status", { active: !_ctx.isLocalBridgeExcluded(cp.name) }])
5750
- }, _toDisplayString(_ctx.isLocalBridgeExcluded(cp.name) ? '未启用' : '已启用'), 3 /* TEXT, CLASS */),
6018
+ }, _toDisplayString(_ctx.isLocalBridgeExcluded(cp.name) ? _ctx.t('common.disabled') : _ctx.t('common.enabled')), 3 /* TEXT, CLASS */),
5751
6019
  _createElementVNode("input", {
5752
6020
  type: "checkbox",
5753
6021
  checked: !_ctx.isLocalBridgeExcluded(cp.name),
@@ -5858,7 +6126,7 @@ return function render(_ctx, _cache) {
5858
6126
  ])
5859
6127
  ], 8 /* PROPS */, ["onClick"]))
5860
6128
  : _createCommentVNode("v-if", true),
5861
- _createCommentVNode(" Webhook 配置模态框 "),
6129
+ _createCommentVNode(" Webhook settings modal "),
5862
6130
  (_ctx.showWebhookModal)
5863
6131
  ? (_openBlock(), _createElementBlock("div", {
5864
6132
  key: 10,
@@ -5874,9 +6142,9 @@ return function render(_ctx, _cache) {
5874
6142
  _createElementVNode("div", {
5875
6143
  class: "modal-title",
5876
6144
  id: "webhook-modal-title"
5877
- }, "Webhook 配置"),
6145
+ }, _toDisplayString(_ctx.t('settings.webhook.modalTitle')), 1 /* TEXT */),
5878
6146
  _createElementVNode("div", { class: "form-group" }, [
5879
- _createElementVNode("label", { class: "form-label" }, "启用状态"),
6147
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('settings.webhook.enabledLabel')), 1 /* TEXT */),
5880
6148
  _createElementVNode("label", { class: "settings-toggle" }, [
5881
6149
  _withDirectives(_createElementVNode("input", {
5882
6150
  type: "checkbox",
@@ -5884,11 +6152,11 @@ return function render(_ctx, _cache) {
5884
6152
  }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
5885
6153
  [_vModelCheckbox, _ctx.webhookConfig.enabled]
5886
6154
  ]),
5887
- _createElementVNode("span", null, "启用 Webhook")
6155
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('settings.webhook.enableToggle')), 1 /* TEXT */)
5888
6156
  ])
5889
6157
  ]),
5890
6158
  _createElementVNode("div", { class: "form-group" }, [
5891
- _createElementVNode("label", { class: "form-label" }, "URL"),
6159
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('settings.webhook.urlLabel')), 1 /* TEXT */),
5892
6160
  _withDirectives(_createElementVNode("input", {
5893
6161
  "onUpdate:modelValue": $event => ((_ctx.webhookConfig.url) = $event),
5894
6162
  class: "form-input",
@@ -5901,7 +6169,7 @@ return function render(_ctx, _cache) {
5901
6169
  ])
5902
6170
  ]),
5903
6171
  _createElementVNode("div", { class: "form-group" }, [
5904
- _createElementVNode("label", { class: "form-label" }, "事件"),
6172
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('settings.webhook.eventsLabel')), 1 /* TEXT */),
5905
6173
  _createElementVNode("div", { class: "webhook-events-checkbox-list" }, [
5906
6174
  (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.webhookEventOptions, (ev) => {
5907
6175
  return (_openBlock(), _createElementBlock("label", {
@@ -5922,12 +6190,12 @@ return function render(_ctx, _cache) {
5922
6190
  _createElementVNode("button", {
5923
6191
  class: "btn btn-cancel",
5924
6192
  onClick: _ctx.closeWebhookModal
5925
- }, "取消", 8 /* PROPS */, ["onClick"]),
6193
+ }, _toDisplayString(_ctx.t('common.cancel')), 9 /* TEXT, PROPS */, ["onClick"]),
5926
6194
  _createElementVNode("button", {
5927
6195
  class: "btn btn-confirm",
5928
6196
  onClick: _ctx.saveWebhookSettings,
5929
6197
  disabled: _ctx.webhookSaving
5930
- }, _toDisplayString(_ctx.webhookSaving ? '保存中...' : '保存'), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
6198
+ }, _toDisplayString(_ctx.webhookSaving ? _ctx.t('common.saving') : _ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
5931
6199
  ])
5932
6200
  ])
5933
6201
  ], 8 /* PROPS */, ["onClick"]))
@@ -5995,183 +6263,312 @@ return function render(_ctx, _cache) {
5995
6263
  }, _toDisplayString(_ctx.t('common.clear')), 9 /* TEXT, PROPS */, ["onClick"])
5996
6264
  ])
5997
6265
  ]),
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]
6266
+ _createCommentVNode(" Accordion Stepper "),
6267
+ _createElementVNode("div", { class: "quick-accordion" }, [
6268
+ _createCommentVNode(" Step 1: Provider "),
6269
+ _createElementVNode("div", {
6270
+ class: _normalizeClass(['accordion-panel', { active: _ctx.openclawAccordionStep === 1, completed: _ctx.openclawAccordionStep > 1 }])
6271
+ }, [
6272
+ _createElementVNode("button", {
6273
+ class: "accordion-trigger",
6274
+ onClick: $event => (_ctx.toggleAccordionStep(1)),
6275
+ type: "button"
6276
+ }, [
6277
+ _createElementVNode("span", { class: "accordion-step-badge" }, [
6278
+ (_ctx.openclawAccordionStep > 1)
6279
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
6280
+ _createTextVNode("")
6281
+ ], 64 /* STABLE_FRAGMENT */))
6282
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
6283
+ _createTextVNode("1")
6284
+ ], 64 /* STABLE_FRAGMENT */))
6035
6285
  ]),
6036
- (_ctx.openclawQuick.baseUrlDisplayKind === 'builtin-default')
6037
- ? (_openBlock(), _createElementBlock("div", {
6286
+ _createElementVNode("span", { class: "accordion-title" }, "Provider"),
6287
+ (_ctx.openclawQuick.providerName)
6288
+ ? (_openBlock(), _createElementBlock("span", {
6038
6289
  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" }, [
6290
+ class: "accordion-status"
6291
+ }, _toDisplayString(_ctx.openclawQuick.providerName), 1 /* TEXT */))
6292
+ : _createCommentVNode("v-if", true),
6293
+ (_openBlock(), _createElementBlock("svg", {
6294
+ class: "accordion-chevron",
6295
+ viewBox: "0 0 24 24",
6296
+ fill: "none",
6297
+ stroke: "currentColor",
6298
+ "stroke-width": "2"
6299
+ }, [
6300
+ _createElementVNode("path", { d: "M6 9l6 6 6-6" })
6301
+ ]))
6302
+ ], 8 /* PROPS */, ["onClick"]),
6303
+ _withDirectives(_createElementVNode("div", { class: "accordion-content" }, [
6304
+ _createElementVNode("div", { class: "form-group" }, [
6305
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.providerName')), 1 /* TEXT */),
6051
6306
  _withDirectives(_createElementVNode("input", {
6052
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiKey) = $event),
6307
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.providerName) = $event),
6053
6308
  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]
6309
+ placeholder: "例如: custom-myapi",
6310
+ onInput: _ctx.validateProviderName
6311
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "onInput"]), [
6312
+ [_vModelText, _ctx.openclawQuick.providerName]
6059
6313
  ]),
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)
6314
+ _createElementVNode("div", {
6315
+ class: _normalizeClass(["form-hint", { 'hint-error': !_ctx.openclawValidation.providerName.valid }])
6316
+ }, _toDisplayString(_ctx.openclawValidation.providerName.message || _ctx.t('modal.openclaw.quick.providerHint')), 3 /* TEXT, CLASS */)
6067
6317
  ]),
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)
6318
+ _createElementVNode("div", { class: "form-group" }, [
6319
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.baseUrl')), 1 /* TEXT */),
6320
+ _withDirectives(_createElementVNode("input", {
6321
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.baseUrl) = $event),
6322
+ class: "form-input",
6323
+ placeholder: "https://api.example.com/v1",
6324
+ readonly: _ctx.openclawQuick.baseUrlReadOnly
6325
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "readonly"]), [
6326
+ [_vModelText, _ctx.openclawQuick.baseUrl]
6327
+ ]),
6328
+ (_ctx.openclawQuick.baseUrlDisplayKind === 'builtin-default')
6074
6329
  ? (_openBlock(), _createElementBlock("div", {
6075
- key: 1,
6330
+ key: 0,
6076
6331
  class: "form-hint"
6077
- }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintReadonly')), 1 /* TEXT */))
6078
- : (_openBlock(), _createElementBlock("div", {
6079
- key: 2,
6332
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.baseUrlHintDefault')), 1 /* TEXT */))
6333
+ : (_ctx.openclawQuick.baseUrlReadOnly)
6334
+ ? (_openBlock(), _createElementBlock("div", {
6335
+ key: 1,
6336
+ class: "form-hint"
6337
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.baseUrlHintReadonly')), 1 /* TEXT */))
6338
+ : _createCommentVNode("v-if", true)
6339
+ ]),
6340
+ _createElementVNode("div", { class: "form-group" }, [
6341
+ _createElementVNode("label", { class: "form-label" }, "API Key"),
6342
+ _createElementVNode("div", { class: "list-row" }, [
6343
+ _withDirectives(_createElementVNode("input", {
6344
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiKey) = $event),
6345
+ class: "form-input",
6346
+ readonly: _ctx.openclawQuick.apiKeyReadOnly,
6347
+ type: (_ctx.openclawQuick.apiKeyReadOnly || _ctx.openclawQuick.showKey) ? 'text' : 'password',
6348
+ placeholder: "sk-..."
6349
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "readonly", "type"]), [
6350
+ [_vModelDynamic, _ctx.openclawQuick.apiKey]
6351
+ ]),
6352
+ (!_ctx.openclawQuick.apiKeyReadOnly)
6353
+ ? (_openBlock(), _createElementBlock("button", {
6354
+ key: 0,
6355
+ class: "btn-mini",
6356
+ onClick: _ctx.toggleOpenclawQuickKey
6357
+ }, _toDisplayString(_ctx.openclawQuick.showKey ? _ctx.t('common.hide') : _ctx.t('common.show')), 9 /* TEXT, PROPS */, ["onClick"]))
6358
+ : _createCommentVNode("v-if", true)
6359
+ ]),
6360
+ (_ctx.openclawQuick.apiKeyDisplayKind === 'auth-profile-value')
6361
+ ? (_openBlock(), _createElementBlock("div", {
6362
+ key: 0,
6080
6363
  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]
6364
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintFromAuth')), 1 /* TEXT */))
6365
+ : (_ctx.openclawQuick.apiKeyReadOnly)
6366
+ ? (_openBlock(), _createElementBlock("div", {
6367
+ key: 1,
6368
+ class: "form-hint"
6369
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintReadonly')), 1 /* TEXT */))
6370
+ : (_openBlock(), _createElementBlock("div", {
6371
+ key: 2,
6372
+ class: "form-hint"
6373
+ }, _toDisplayString(_ctx.t('modal.openclaw.quick.apiKeyHintKeep')), 1 /* TEXT */))
6374
+ ]),
6375
+ _createElementVNode("div", { class: "form-group" }, [
6376
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.apiType')), 1 /* TEXT */),
6377
+ _withDirectives(_createElementVNode("input", {
6378
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.apiType) = $event),
6379
+ class: "form-input",
6380
+ list: "openclawApiTypeList",
6381
+ placeholder: _ctx.t('placeholder.apiTypeExample')
6382
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6383
+ [_vModelText, _ctx.openclawQuick.apiType]
6384
+ ]),
6385
+ _createElementVNode("datalist", { id: "openclawApiTypeList" }, [
6386
+ _createElementVNode("option", { value: "openai-responses" }),
6387
+ _createElementVNode("option", { value: "openai-chat" }),
6388
+ _createElementVNode("option", { value: "anthropic" }),
6389
+ _createElementVNode("option", { value: "custom" })
6390
+ ])
6092
6391
  ]),
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" })
6392
+ _createElementVNode("div", { class: "accordion-actions" }, [
6393
+ _createElementVNode("button", {
6394
+ class: "btn btn-confirm btn-sm",
6395
+ onClick: _ctx.nextAccordionStep,
6396
+ disabled: !_ctx.openclawQuick.providerName
6397
+ }, " 下一步 → ", 8 /* PROPS */, ["onClick", "disabled"])
6098
6398
  ])
6399
+ ], 512 /* NEED_PATCH */), [
6400
+ [_vShow, _ctx.openclawAccordionStep === 1]
6099
6401
  ])
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" }, [
6402
+ ], 2 /* CLASS */),
6403
+ _createCommentVNode(" Step 2: Model "),
6404
+ _createElementVNode("div", {
6405
+ class: _normalizeClass(['accordion-panel', { active: _ctx.openclawAccordionStep === 2, completed: _ctx.openclawAccordionStep > 2 }])
6406
+ }, [
6407
+ _createElementVNode("button", {
6408
+ class: "accordion-trigger",
6409
+ onClick: $event => (_ctx.toggleAccordionStep(2)),
6410
+ type: "button"
6411
+ }, [
6412
+ _createElementVNode("span", { class: "accordion-step-badge" }, [
6413
+ (_ctx.openclawAccordionStep > 2)
6414
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
6415
+ _createTextVNode("")
6416
+ ], 64 /* STABLE_FRAGMENT */))
6417
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
6418
+ _createTextVNode("2")
6419
+ ], 64 /* STABLE_FRAGMENT */))
6420
+ ]),
6421
+ _createElementVNode("span", { class: "accordion-title" }, _toDisplayString(_ctx.t('modal.openclaw.quick.modelTitle')), 1 /* TEXT */),
6422
+ (_ctx.openclawQuick.modelId)
6423
+ ? (_openBlock(), _createElementBlock("span", {
6424
+ key: 0,
6425
+ class: "accordion-status"
6426
+ }, _toDisplayString(_ctx.openclawQuick.modelName || _ctx.openclawQuick.modelId), 1 /* TEXT */))
6427
+ : _createCommentVNode("v-if", true),
6428
+ (_openBlock(), _createElementBlock("svg", {
6429
+ class: "accordion-chevron",
6430
+ viewBox: "0 0 24 24",
6431
+ fill: "none",
6432
+ stroke: "currentColor",
6433
+ "stroke-width": "2"
6434
+ }, [
6435
+ _createElementVNode("path", { d: "M6 9l6 6 6-6" })
6436
+ ]))
6437
+ ], 8 /* PROPS */, ["onClick"]),
6438
+ _withDirectives(_createElementVNode("div", { class: "accordion-content" }, [
6439
+ _createElementVNode("div", { class: "form-group" }, [
6440
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.modelId')), 1 /* TEXT */),
6126
6441
  _withDirectives(_createElementVNode("input", {
6127
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.contextWindow) = $event),
6442
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.modelId) = $event),
6128
6443
  class: "form-input",
6129
- placeholder: _ctx.t('field.contextWindow')
6130
- }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6131
- [_vModelText, _ctx.openclawQuick.contextWindow]
6444
+ placeholder: _ctx.t('placeholder.modelIdExample'),
6445
+ onInput: _ctx.validateModelId
6446
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["onUpdate:modelValue", "placeholder", "onInput"]), [
6447
+ [_vModelText, _ctx.openclawQuick.modelId]
6132
6448
  ]),
6449
+ _createElementVNode("div", {
6450
+ class: _normalizeClass(["form-hint", { 'hint-error': !_ctx.openclawValidation.modelId.valid }])
6451
+ }, _toDisplayString(_ctx.openclawValidation.modelId.message || '必填,例如: gpt-4'), 3 /* TEXT, CLASS */)
6452
+ ]),
6453
+ _createElementVNode("div", { class: "form-group" }, [
6454
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.displayName')), 1 /* TEXT */),
6133
6455
  _withDirectives(_createElementVNode("input", {
6134
- "onUpdate:modelValue": $event => ((_ctx.openclawQuick.maxTokens) = $event),
6456
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.modelName) = $event),
6135
6457
  class: "form-input",
6136
- placeholder: _ctx.t('field.maxOutput')
6458
+ placeholder: _ctx.t('placeholder.modelNameOptional')
6137
6459
  }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6138
- [_vModelText, _ctx.openclawQuick.maxTokens]
6139
- ])
6460
+ [_vModelText, _ctx.openclawQuick.modelName]
6461
+ ]),
6462
+ _createElementVNode("div", { class: "form-hint" }, "可选,用于显示")
6463
+ ]),
6464
+ _createElementVNode("div", { class: "form-group" }, [
6465
+ _createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('field.contextAndMaxOutput')), 1 /* TEXT */),
6466
+ _createElementVNode("div", { class: "list-row" }, [
6467
+ _withDirectives(_createElementVNode("input", {
6468
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.contextWindow) = $event),
6469
+ class: "form-input",
6470
+ placeholder: _ctx.t('field.contextWindow')
6471
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6472
+ [_vModelText, _ctx.openclawQuick.contextWindow]
6473
+ ]),
6474
+ _withDirectives(_createElementVNode("input", {
6475
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.maxTokens) = $event),
6476
+ class: "form-input",
6477
+ placeholder: _ctx.t('field.maxOutput')
6478
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue", "placeholder"]), [
6479
+ [_vModelText, _ctx.openclawQuick.maxTokens]
6480
+ ])
6481
+ ]),
6482
+ _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('hint.emptyNoChange')), 1 /* TEXT */)
6140
6483
  ]),
6141
- _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('hint.emptyNoChange')), 1 /* TEXT */)
6484
+ _createElementVNode("div", { class: "accordion-actions" }, [
6485
+ _createElementVNode("button", {
6486
+ class: "btn btn-cancel btn-sm",
6487
+ onClick: _ctx.prevAccordionStep
6488
+ }, " ← 上一步 ", 8 /* PROPS */, ["onClick"]),
6489
+ _createElementVNode("button", {
6490
+ class: "btn btn-confirm btn-sm",
6491
+ onClick: _ctx.nextAccordionStep,
6492
+ disabled: !_ctx.openclawQuick.modelId
6493
+ }, " 下一步 → ", 8 /* PROPS */, ["onClick", "disabled"])
6494
+ ])
6495
+ ], 512 /* NEED_PATCH */), [
6496
+ [_vShow, _ctx.openclawAccordionStep === 2]
6142
6497
  ])
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]
6498
+ ], 2 /* CLASS */),
6499
+ _createCommentVNode(" Step 3: Options "),
6500
+ _createElementVNode("div", {
6501
+ class: _normalizeClass(['accordion-panel', { active: _ctx.openclawAccordionStep === 3, completed: _ctx.openclawAccordionStep > 3 }])
6502
+ }, [
6503
+ _createElementVNode("button", {
6504
+ class: "accordion-trigger",
6505
+ onClick: $event => (_ctx.toggleAccordionStep(3)),
6506
+ type: "button"
6507
+ }, [
6508
+ _createElementVNode("span", { class: "accordion-step-badge" }, [
6509
+ (_ctx.openclawAccordionStep > 3)
6510
+ ? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
6511
+ _createTextVNode("✓")
6512
+ ], 64 /* STABLE_FRAGMENT */))
6513
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
6514
+ _createTextVNode("3")
6515
+ ], 64 /* STABLE_FRAGMENT */))
6152
6516
  ]),
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]
6517
+ _createElementVNode("span", { class: "accordion-title" }, _toDisplayString(_ctx.t('modal.openclaw.quick.optionsTitle')), 1 /* TEXT */),
6518
+ _createElementVNode("span", { class: "accordion-status" }, "高级选项"),
6519
+ (_openBlock(), _createElementBlock("svg", {
6520
+ class: "accordion-chevron",
6521
+ viewBox: "0 0 24 24",
6522
+ fill: "none",
6523
+ stroke: "currentColor",
6524
+ "stroke-width": "2"
6525
+ }, [
6526
+ _createElementVNode("path", { d: "M6 9l6 6 6-6" })
6527
+ ]))
6528
+ ], 8 /* PROPS */, ["onClick"]),
6529
+ _withDirectives(_createElementVNode("div", { class: "accordion-content" }, [
6530
+ _createElementVNode("label", { class: "quick-option" }, [
6531
+ _withDirectives(_createElementVNode("input", {
6532
+ type: "checkbox",
6533
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.setPrimary) = $event)
6534
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6535
+ [_vModelCheckbox, _ctx.openclawQuick.setPrimary]
6536
+ ]),
6537
+ _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.setPrimary')), 1 /* TEXT */)
6161
6538
  ]),
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]
6539
+ _createElementVNode("label", { class: "quick-option" }, [
6540
+ _withDirectives(_createElementVNode("input", {
6541
+ type: "checkbox",
6542
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.overrideProvider) = $event)
6543
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6544
+ [_vModelCheckbox, _ctx.openclawQuick.overrideProvider]
6545
+ ]),
6546
+ _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.overrideProvider')), 1 /* TEXT */)
6170
6547
  ]),
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
- ])
6548
+ _createElementVNode("label", { class: "quick-option" }, [
6549
+ _withDirectives(_createElementVNode("input", {
6550
+ type: "checkbox",
6551
+ "onUpdate:modelValue": $event => ((_ctx.openclawQuick.overrideModels) = $event)
6552
+ }, null, 8 /* PROPS */, ["onUpdate:modelValue"]), [
6553
+ [_vModelCheckbox, _ctx.openclawQuick.overrideModels]
6554
+ ]),
6555
+ _createTextVNode(" " + _toDisplayString(_ctx.t('modal.openclaw.quick.overrideModels')), 1 /* TEXT */)
6556
+ ]),
6557
+ _createElementVNode("div", { class: "form-hint" }, _toDisplayString(_ctx.t('modal.openclaw.quick.optionsHint')), 1 /* TEXT */),
6558
+ _createElementVNode("div", { class: "accordion-actions" }, [
6559
+ _createElementVNode("button", {
6560
+ class: "btn btn-cancel btn-sm",
6561
+ onClick: _ctx.prevAccordionStep
6562
+ }, " ← 上一步 ", 8 /* PROPS */, ["onClick"]),
6563
+ _createElementVNode("button", {
6564
+ class: "btn btn-confirm btn-sm",
6565
+ onClick: _ctx.finishAccordionStep
6566
+ }, " 完成 ✓ ", 8 /* PROPS */, ["onClick"])
6567
+ ])
6568
+ ], 512 /* NEED_PATCH */), [
6569
+ [_vShow, _ctx.openclawAccordionStep === 3]
6570
+ ])
6571
+ ], 2 /* CLASS */)
6175
6572
  ]),
6176
6573
  _createElementVNode("div", { class: "btn-group" }, [
6177
6574
  _createElementVNode("button", {
@@ -6490,7 +6887,7 @@ return function render(_ctx, _cache) {
6490
6887
  [_vModelText, _ctx.openclawEditing.content]
6491
6888
  ]),
6492
6889
  _createElementVNode("div", { class: "template-editor-warning" }, [
6493
- (_ctx.openclawEditing.lockName && _ctx.openclawEditing.name === '默认配置')
6890
+ (_ctx.openclawEditing.lockName && _ctx.isDefaultOpenclawConfig(_ctx.openclawEditing.name))
6494
6891
  ? (_openBlock(), _createElementBlock("span", { key: 0 }, "默认配置始终映射当前 openclaw.json,请直接使用“保存并应用”。"))
6495
6892
  : (_openBlock(), _createElementBlock("span", { key: 1 }, "保存仅写入本地配置库。点击“保存并应用”后会写入 openclaw.json。"))
6496
6893
  ])
@@ -6504,7 +6901,7 @@ return function render(_ctx, _cache) {
6504
6901
  _createElementVNode("button", {
6505
6902
  class: "btn btn-confirm",
6506
6903
  onClick: _ctx.saveOpenclawConfig,
6507
- disabled: _ctx.openclawSaving || _ctx.openclawApplying || (_ctx.openclawEditing.lockName && _ctx.openclawEditing.name === '默认配置')
6904
+ disabled: _ctx.openclawSaving || _ctx.openclawApplying || (_ctx.openclawEditing.lockName && _ctx.isDefaultOpenclawConfig(_ctx.openclawEditing.name))
6508
6905
  }, _toDisplayString(_ctx.openclawSaving ? '保存中...' : '保存'), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
6509
6906
  _createElementVNode("button", {
6510
6907
  class: "btn btn-confirm secondary",