codexmate 0.0.55 → 0.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +2 -0
  2. package/README.vi.md +2 -0
  3. package/README.zh.md +2 -0
  4. package/cli/local-bridge.js +221 -22
  5. package/cli.js +117 -5
  6. package/package.json +1 -1
  7. package/web-ui/app.js +2 -0
  8. package/web-ui/modules/app.computed.session.mjs +210 -0
  9. package/web-ui/modules/app.methods.claude-config.mjs +128 -12
  10. package/web-ui/modules/app.methods.codex-config.mjs +294 -65
  11. package/web-ui/modules/app.methods.navigation.mjs +4 -1
  12. package/web-ui/modules/app.methods.providers.mjs +15 -1
  13. package/web-ui/modules/app.methods.runtime.mjs +7 -2
  14. package/web-ui/modules/app.methods.session-actions.mjs +24 -0
  15. package/web-ui/modules/app.methods.startup-claude.mjs +34 -1
  16. package/web-ui/modules/i18n/locales/en.mjs +41 -2
  17. package/web-ui/modules/i18n/locales/ja.mjs +41 -2
  18. package/web-ui/modules/i18n/locales/vi.mjs +41 -8
  19. package/web-ui/modules/i18n/locales/zh-tw.mjs +41 -2
  20. package/web-ui/modules/i18n/locales/zh.mjs +41 -2
  21. package/web-ui/modules/provider-default-names.mjs +25 -0
  22. package/web-ui/partials/index/modal-health-check.html +69 -5
  23. package/web-ui/partials/index/panel-config-codex.html +2 -2
  24. package/web-ui/partials/index/panel-sessions.html +97 -17
  25. package/web-ui/res/web-ui-render.precompiled.js +345 -93
  26. package/web-ui/session-helpers.mjs +4 -1
  27. package/web-ui/styles/responsive.css +98 -0
  28. package/web-ui/styles/sessions-preview.css +212 -2
  29. package/web-ui/styles/sessions-toolbar-trash.css +61 -18
  30. package/web-ui/styles/skills-list.css +122 -0
  31. package/web-ui/styles/titles-cards.css +52 -0
@@ -1115,7 +1115,7 @@ return function render(_ctx, _cache) {
1115
1115
  ? (_openBlock(), _createElementBlock("button", {
1116
1116
  key: 0,
1117
1117
  class: "btn-add",
1118
- onClick: $event => {_ctx.showAddProviderKey = false; _ctx.showAddModal = true},
1118
+ onClick: _ctx.openAddProviderModal,
1119
1119
  disabled: !_ctx.isToolConfigWriteAllowed('codex')
1120
1120
  }, [
1121
1121
  (_openBlock(), _createElementBlock("svg", {
@@ -1373,7 +1373,7 @@ return function render(_ctx, _cache) {
1373
1373
  onClick: _ctx.runHealthCheck,
1374
1374
  disabled: _ctx.healthCheckLoading || _ctx.loading || !!_ctx.initError
1375
1375
  }, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('config.health.running') : _ctx.t('config.health.run')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
1376
- _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.health.hint')), 1 /* TEXT */)
1376
+ _createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('config.health.codexHint')), 1 /* TEXT */)
1377
1377
  ])
1378
1378
  ], 64 /* STABLE_FRAGMENT */))
1379
1379
  : _createCommentVNode("v-if", true),
@@ -2749,7 +2749,7 @@ return function render(_ctx, _cache) {
2749
2749
  ]))
2750
2750
  ]))
2751
2751
  : (_openBlock(), _createElementBlock("div", { key: 1 }, [
2752
- _createElementVNode("div", { class: "selector-section" }, [
2752
+ _createElementVNode("div", { class: "selector-section session-selector-section" }, [
2753
2753
  _createElementVNode("div", {
2754
2754
  class: "selector-header",
2755
2755
  style: {"display":"none"}
@@ -2757,29 +2757,30 @@ return function render(_ctx, _cache) {
2757
2757
  _createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('sessions.sourceTitle')), 1 /* TEXT */),
2758
2758
  _createElementVNode("div", { class: "selector-actions sessions-header-actions" })
2759
2759
  ]),
2760
+ _createElementVNode("div", { class: "session-source-tabs-row" }, [
2761
+ _createElementVNode("div", {
2762
+ class: "session-source-pills",
2763
+ role: "group",
2764
+ "aria-label": _ctx.t('sessions.sourceTitle')
2765
+ }, [
2766
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.sessionSourceOptions, (src) => {
2767
+ return (_openBlock(), _createElementBlock("button", {
2768
+ key: src.value,
2769
+ class: _normalizeClass(['session-source-pill', { active: _ctx.sessionFilterSource === src.value }]),
2770
+ "data-source": src.value,
2771
+ onClick: $event => (_ctx.setSessionSource(src.value)),
2772
+ disabled: _ctx.sessionsLoading,
2773
+ "aria-pressed": _ctx.sessionFilterSource === src.value,
2774
+ type: "button"
2775
+ }, [
2776
+ _createElementVNode("span", { class: "session-source-pill-dot" }),
2777
+ _createElementVNode("span", { class: "session-source-pill-label" }, _toDisplayString(src.label), 1 /* TEXT */)
2778
+ ], 10 /* CLASS, PROPS */, ["data-source", "onClick", "disabled", "aria-pressed"]))
2779
+ }), 128 /* KEYED_FRAGMENT */))
2780
+ ], 8 /* PROPS */, ["aria-label"])
2781
+ ]),
2760
2782
  _createElementVNode("div", { class: "session-toolbar" }, [
2761
2783
  _createElementVNode("div", { class: "session-toolbar-group session-toolbar-primary" }, [
2762
- _createElementVNode("div", {
2763
- class: "session-source-pills",
2764
- role: "radiogroup",
2765
- "aria-label": "Session source"
2766
- }, [
2767
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.sessionSourceOptions, (src) => {
2768
- return (_openBlock(), _createElementBlock("button", {
2769
- key: src.value,
2770
- class: _normalizeClass(['session-source-pill', { active: _ctx.sessionFilterSource === src.value }]),
2771
- "data-source": src.value,
2772
- onClick: $event => (_ctx.setSessionSource(src.value)),
2773
- disabled: _ctx.sessionsLoading,
2774
- "aria-pressed": _ctx.sessionFilterSource === src.value,
2775
- role: "radio",
2776
- type: "button"
2777
- }, [
2778
- _createElementVNode("span", { class: "session-source-pill-dot" }),
2779
- _createElementVNode("span", { class: "session-source-pill-label" }, _toDisplayString(src.label), 1 /* TEXT */)
2780
- ], 10 /* CLASS, PROPS */, ["data-source", "onClick", "disabled", "aria-pressed"]))
2781
- }), 128 /* KEYED_FRAGMENT */))
2782
- ]),
2783
2784
  _withDirectives(_createElementVNode("select", {
2784
2785
  class: "session-path-select",
2785
2786
  "onUpdate:modelValue": $event => ((_ctx.sessionPathFilter) = $event),
@@ -3173,6 +3174,27 @@ return function render(_ctx, _cache) {
3173
3174
  _createElementVNode("path", { d: "M2.5 12v1.5a1 1 0 0 0 1 1h9a1 1 0 0 0 1-1V12" })
3174
3175
  ]))
3175
3176
  ], 8 /* PROPS */, ["onClick", "disabled", "title", "aria-label"]),
3177
+ _createElementVNode("button", {
3178
+ class: "btn-session-open session-brief-copy",
3179
+ onClick: _ctx.copySessionWorkspaceBrief,
3180
+ disabled: !_ctx.activeSessionWorkspaceSummary.available,
3181
+ title: _ctx.t('sessions.workspace.copy'),
3182
+ "aria-label": _ctx.t('sessions.workspace.copy')
3183
+ }, [
3184
+ (_openBlock(), _createElementBlock("svg", {
3185
+ viewBox: "0 0 16 16",
3186
+ fill: "none",
3187
+ stroke: "currentColor",
3188
+ "stroke-width": "1.8",
3189
+ "stroke-linecap": "round",
3190
+ "stroke-linejoin": "round"
3191
+ }, [
3192
+ _createElementVNode("path", { d: "M4 2.5h6.5L13 5v8.5H4z" }),
3193
+ _createElementVNode("path", { d: "M10.5 2.5V5H13" }),
3194
+ _createElementVNode("path", { d: "M6 8h5" }),
3195
+ _createElementVNode("path", { d: "M6 10.5h5" })
3196
+ ]))
3197
+ ], 8 /* PROPS */, ["onClick", "disabled", "title", "aria-label"]),
3176
3198
  _createElementVNode("div", { class: "session-link-group" }, [
3177
3199
  _createElementVNode("button", {
3178
3200
  class: "btn-session-open",
@@ -3270,6 +3292,140 @@ return function render(_ctx, _cache) {
3270
3292
  key: 5,
3271
3293
  class: "session-preview-body"
3272
3294
  }, [
3295
+ (_ctx.activeSessionWorkspaceSummary.available)
3296
+ ? (_openBlock(), _createElementBlock("section", {
3297
+ key: 0,
3298
+ class: "session-workspace",
3299
+ "aria-label": _ctx.t('sessions.workspace.title')
3300
+ }, [
3301
+ _createElementVNode("div", { class: "session-workspace-header" }, [
3302
+ _createElementVNode("div", null, [
3303
+ _createElementVNode("div", { class: "session-workspace-kicker" }, _toDisplayString(_ctx.t('sessions.workspace.kicker')), 1 /* TEXT */),
3304
+ _createElementVNode("h3", { class: "session-workspace-title" }, _toDisplayString(_ctx.t('sessions.workspace.title')), 1 /* TEXT */),
3305
+ _createElementVNode("p", { class: "session-workspace-subtitle" }, _toDisplayString(_ctx.t('sessions.workspace.subtitle', { count: _ctx.activeSessionWorkspaceSummary.messageCount })), 1 /* TEXT */)
3306
+ ]),
3307
+ _createElementVNode("button", {
3308
+ class: "btn-mini",
3309
+ type: "button",
3310
+ onClick: _ctx.copySessionWorkspaceBrief
3311
+ }, _toDisplayString(_ctx.t('sessions.workspace.copy')), 9 /* TEXT, PROPS */, ["onClick"])
3312
+ ]),
3313
+ _createElementVNode("div", { class: "session-workspace-metrics" }, [
3314
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.metrics, (metric) => {
3315
+ return (_openBlock(), _createElementBlock("div", {
3316
+ key: metric.key,
3317
+ class: "session-workspace-metric"
3318
+ }, [
3319
+ _createElementVNode("span", { class: "session-workspace-metric-value" }, _toDisplayString(metric.value), 1 /* TEXT */),
3320
+ _createElementVNode("span", { class: "session-workspace-metric-label" }, _toDisplayString(metric.label), 1 /* TEXT */)
3321
+ ]))
3322
+ }), 128 /* KEYED_FRAGMENT */))
3323
+ ]),
3324
+ _createElementVNode("div", { class: "session-workspace-grid" }, [
3325
+ _createElementVNode("div", { class: "session-workspace-card session-workspace-card-wide" }, [
3326
+ _createElementVNode("div", { class: "session-workspace-card-title" }, _toDisplayString(_ctx.t('sessions.workspace.signals')), 1 /* TEXT */),
3327
+ (_ctx.activeSessionWorkspaceSummary.signals.length)
3328
+ ? (_openBlock(), _createElementBlock("ul", {
3329
+ key: 0,
3330
+ class: "session-workspace-list"
3331
+ }, [
3332
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.signals, (item, index) => {
3333
+ return (_openBlock(), _createElementBlock("li", {
3334
+ key: 'signal-' + index
3335
+ }, _toDisplayString(item), 1 /* TEXT */))
3336
+ }), 128 /* KEYED_FRAGMENT */))
3337
+ ]))
3338
+ : (_openBlock(), _createElementBlock("div", {
3339
+ key: 1,
3340
+ class: "session-workspace-empty"
3341
+ }, _toDisplayString(_ctx.t('sessions.workspace.empty')), 1 /* TEXT */))
3342
+ ]),
3343
+ _createElementVNode("div", { class: "session-workspace-card" }, [
3344
+ _createElementVNode("div", { class: "session-workspace-card-title" }, _toDisplayString(_ctx.t('sessions.workspace.commands')), 1 /* TEXT */),
3345
+ (_ctx.activeSessionWorkspaceSummary.commands.length)
3346
+ ? (_openBlock(), _createElementBlock("ul", {
3347
+ key: 0,
3348
+ class: "session-workspace-list session-workspace-code-list"
3349
+ }, [
3350
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.commands, (item, index) => {
3351
+ return (_openBlock(), _createElementBlock("li", {
3352
+ key: 'command-' + index
3353
+ }, [
3354
+ _createElementVNode("code", null, _toDisplayString(item), 1 /* TEXT */)
3355
+ ]))
3356
+ }), 128 /* KEYED_FRAGMENT */))
3357
+ ]))
3358
+ : (_openBlock(), _createElementBlock("div", {
3359
+ key: 1,
3360
+ class: "session-workspace-empty"
3361
+ }, _toDisplayString(_ctx.t('sessions.workspace.noneCommands')), 1 /* TEXT */))
3362
+ ]),
3363
+ _createElementVNode("div", { class: "session-workspace-card" }, [
3364
+ _createElementVNode("div", { class: "session-workspace-card-title" }, _toDisplayString(_ctx.t('sessions.workspace.files')), 1 /* TEXT */),
3365
+ (_ctx.activeSessionWorkspaceSummary.files.length)
3366
+ ? (_openBlock(), _createElementBlock("ul", {
3367
+ key: 0,
3368
+ class: "session-workspace-list session-workspace-code-list"
3369
+ }, [
3370
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.files, (item, index) => {
3371
+ return (_openBlock(), _createElementBlock("li", {
3372
+ key: 'file-' + index
3373
+ }, [
3374
+ _createElementVNode("code", null, _toDisplayString(item), 1 /* TEXT */)
3375
+ ]))
3376
+ }), 128 /* KEYED_FRAGMENT */))
3377
+ ]))
3378
+ : (_openBlock(), _createElementBlock("div", {
3379
+ key: 1,
3380
+ class: "session-workspace-empty"
3381
+ }, _toDisplayString(_ctx.t('sessions.workspace.noneFiles')), 1 /* TEXT */))
3382
+ ]),
3383
+ _createElementVNode("div", { class: "session-workspace-card" }, [
3384
+ _createElementVNode("div", { class: "session-workspace-card-title" }, _toDisplayString(_ctx.t('sessions.workspace.links')), 1 /* TEXT */),
3385
+ (_ctx.activeSessionWorkspaceSummary.links.length)
3386
+ ? (_openBlock(), _createElementBlock("ul", {
3387
+ key: 0,
3388
+ class: "session-workspace-list"
3389
+ }, [
3390
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.links, (item, index) => {
3391
+ return (_openBlock(), _createElementBlock("li", {
3392
+ key: 'link-' + index
3393
+ }, _toDisplayString(item), 1 /* TEXT */))
3394
+ }), 128 /* KEYED_FRAGMENT */))
3395
+ ]))
3396
+ : (_openBlock(), _createElementBlock("div", {
3397
+ key: 1,
3398
+ class: "session-workspace-empty"
3399
+ }, _toDisplayString(_ctx.t('sessions.workspace.noneLinks')), 1 /* TEXT */))
3400
+ ]),
3401
+ _createElementVNode("div", {
3402
+ class: _normalizeClass(["session-workspace-card", { 'session-workspace-card-alert': _ctx.activeSessionWorkspaceSummary.risks.length || _ctx.activeSessionWorkspaceSummary.nextSteps.length }])
3403
+ }, [
3404
+ _createElementVNode("div", { class: "session-workspace-card-title" }, _toDisplayString(_ctx.t('sessions.workspace.risks')), 1 /* TEXT */),
3405
+ (_ctx.activeSessionWorkspaceSummary.risks.length || _ctx.activeSessionWorkspaceSummary.nextSteps.length)
3406
+ ? (_openBlock(), _createElementBlock("ul", {
3407
+ key: 0,
3408
+ class: "session-workspace-list"
3409
+ }, [
3410
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.risks, (item, index) => {
3411
+ return (_openBlock(), _createElementBlock("li", {
3412
+ key: 'risk-' + index
3413
+ }, _toDisplayString(item), 1 /* TEXT */))
3414
+ }), 128 /* KEYED_FRAGMENT */)),
3415
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionWorkspaceSummary.nextSteps, (item, index) => {
3416
+ return (_openBlock(), _createElementBlock("li", {
3417
+ key: 'next-' + index
3418
+ }, _toDisplayString(item), 1 /* TEXT */))
3419
+ }), 128 /* KEYED_FRAGMENT */))
3420
+ ]))
3421
+ : (_openBlock(), _createElementBlock("div", {
3422
+ key: 1,
3423
+ class: "session-workspace-empty"
3424
+ }, _toDisplayString(_ctx.t('sessions.workspace.noneRisks')), 1 /* TEXT */))
3425
+ ], 2 /* CLASS */)
3426
+ ])
3427
+ ], 8 /* PROPS */, ["aria-label"]))
3428
+ : _createCommentVNode("v-if", true),
3273
3429
  _createElementVNode("div", { class: "session-preview-messages" }, [
3274
3430
  (_ctx.activeSessionDetailClipped)
3275
3431
  ? (_openBlock(), _createElementBlock("div", {
@@ -3277,7 +3433,7 @@ return function render(_ctx, _cache) {
3277
3433
  class: "session-item-sub session-item-wrap"
3278
3434
  }, _toDisplayString(_ctx.t('sessions.preview.clipped', { count: _ctx.activeSessionMessages.length })), 1 /* TEXT */))
3279
3435
  : _createCommentVNode("v-if", true),
3280
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionMessages, (msg, idx, ___, _cached) => {
3436
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.activeSessionVisibleMessages, (msg, idx, ___, _cached) => {
3281
3437
  const _memo = ([msg.text, msg.timestamp, msg.roleLabel, msg.normalizedRole])
3282
3438
  if (_cached && _cached.key === _ctx.getRecordRenderKey(msg, idx) && _isMemoSame(_cached, _memo)) return _cached
3283
3439
  const _item = (_openBlock(), _createElementBlock("div", {
@@ -3300,7 +3456,21 @@ return function render(_ctx, _cache) {
3300
3456
  ], 10 /* CLASS, PROPS */, ["data-message-key"]))
3301
3457
  _item.memo = _memo
3302
3458
  return _item
3303
- }, _cache, 2), 128 /* KEYED_FRAGMENT */))
3459
+ }, _cache, 2), 128 /* KEYED_FRAGMENT */)),
3460
+ (_ctx.canLoadMoreSessionMessages)
3461
+ ? (_openBlock(), _createElementBlock("div", {
3462
+ key: 1,
3463
+ class: "session-preview-load-more"
3464
+ }, [
3465
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('sessions.preview.shownCount', { shown: _ctx.activeSessionVisibleMessages.length, total: _ctx.activeSessionMessages.length })), 1 /* TEXT */),
3466
+ _createElementVNode("button", {
3467
+ class: "btn-mini",
3468
+ type: "button",
3469
+ onClick: _ctx.loadMoreSessionMessages,
3470
+ disabled: _ctx.sessionPreviewLoadingMore
3471
+ }, _toDisplayString(_ctx.sessionPreviewLoadingMore ? _ctx.t('sessions.preview.loadingMore') : _ctx.t('sessions.preview.loadMore', { remain: _ctx.sessionPreviewRemainingCount })), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
3472
+ ]))
3473
+ : _createCommentVNode("v-if", true)
3304
3474
  ])
3305
3475
  ]))
3306
3476
  ], 40 /* PROPS, NEED_HYDRATION */, ["onScroll"]),
@@ -8905,7 +9075,7 @@ return function render(_ctx, _cache) {
8905
9075
  onClick: _withModifiers($event => (_ctx.showHealthCheckModal = false), ["self"])
8906
9076
  }, [
8907
9077
  _createElementVNode("div", {
8908
- class: "modal",
9078
+ class: "modal modal-health-check",
8909
9079
  role: "dialog",
8910
9080
  "aria-modal": "true",
8911
9081
  "aria-labelledby": "health-check-modal-title"
@@ -8914,73 +9084,155 @@ return function render(_ctx, _cache) {
8914
9084
  class: "modal-title",
8915
9085
  id: "health-check-modal-title"
8916
9086
  }, _toDisplayString(_ctx.t('config.health.title')), 1 /* TEXT */),
8917
- (!_ctx.healthCheckResult)
8918
- ? (_openBlock(), _createElementBlock("div", {
8919
- key: 0,
8920
- class: "state-message"
8921
- }, _toDisplayString(_ctx.t('common.notLoaded')), 1 /* TEXT */))
8922
- : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
8923
- _createElementVNode("div", { class: "form-hint" }, [
8924
- _createTextVNode(_toDisplayString(_ctx.healthCheckResult.ok ? _ctx.t('config.health.ok') : _ctx.t('config.health.fail')) + " ", 1 /* TEXT */),
8925
- (_ctx.healthCheckResult.issues)
8926
- ? (_openBlock(), _createElementBlock("span", { key: 0 }, "(" + _toDisplayString(_ctx.t('config.health.issues', { count: _ctx.healthCheckResult.issues.length })) + ")", 1 /* TEXT */))
9087
+ _createElementVNode("div", { class: "health-check-modal-body" }, [
9088
+ (!_ctx.healthCheckResult)
9089
+ ? (_openBlock(), _createElementBlock("div", {
9090
+ key: 0,
9091
+ class: "state-message"
9092
+ }, _toDisplayString(_ctx.t('common.notLoaded')), 1 /* TEXT */))
9093
+ : (_openBlock(), _createElementBlock(_Fragment, { key: 1 }, [
9094
+ _createElementVNode("div", { class: "form-hint" }, [
9095
+ _createTextVNode(_toDisplayString(_ctx.healthCheckResult.ok ? _ctx.t('config.health.ok') : _ctx.t('config.health.fail')) + " ", 1 /* TEXT */),
9096
+ (_ctx.healthCheckResult.issues)
9097
+ ? (_openBlock(), _createElementBlock("span", { key: 0 }, "(" + _toDisplayString(_ctx.t('config.health.issues', { count: _ctx.healthCheckResult.issues.length })) + ")", 1 /* TEXT */))
9098
+ : _createCommentVNode("v-if", true)
9099
+ ]),
9100
+ (_ctx.healthCheckResult.remote && _ctx.healthCheckResult.remote.type === 'remote-health-check')
9101
+ ? (_openBlock(), _createElementBlock("div", {
9102
+ key: 0,
9103
+ class: "form-hint"
9104
+ }, [
9105
+ _createTextVNode(_toDisplayString(_ctx.healthCheckResult.remote.endpoint || '') + " ", 1 /* TEXT */),
9106
+ (_ctx.healthCheckResult.remote.statusCode)
9107
+ ? (_openBlock(), _createElementBlock("span", { key: 0 }, " · " + _toDisplayString(_ctx.healthCheckResult.remote.statusCode), 1 /* TEXT */))
9108
+ : _createCommentVNode("v-if", true),
9109
+ (_ctx.healthCheckResult.remote.message)
9110
+ ? (_openBlock(), _createElementBlock("span", { key: 1 }, " · " + _toDisplayString(_ctx.healthCheckResult.remote.message), 1 /* TEXT */))
9111
+ : _createCommentVNode("v-if", true)
9112
+ ]))
9113
+ : _createCommentVNode("v-if", true),
9114
+ (_ctx.healthCheckResult.remote && _ctx.healthCheckResult.remote.type === 'providers-health')
9115
+ ? (_openBlock(), _createElementBlock("div", {
9116
+ key: 1,
9117
+ class: "form-hint"
9118
+ }, _toDisplayString(_ctx.t('config.health.providersSummary', _ctx.healthCheckResult.remote.summary || { total: 0, green: 0, yellow: 0, red: 0 })), 1 /* TEXT */))
9119
+ : _createCommentVNode("v-if", true),
9120
+ (_ctx.getHealthCheckFailedProviderItems().length)
9121
+ ? (_openBlock(), _createElementBlock("div", {
9122
+ key: 2,
9123
+ class: "model-list health-failed-provider-list"
9124
+ }, [
9125
+ _createElementVNode("div", { class: "model-item health-failed-provider-header" }, [
9126
+ _createElementVNode("span", { class: "health-failed-provider-main" }, [
9127
+ _createElementVNode("input", {
9128
+ type: "checkbox",
9129
+ checked: _ctx.areAllHealthCheckFailedProvidersSelected(),
9130
+ disabled: !_ctx.getSelectableHealthCheckFailedProviderItems().length || _ctx.healthCheckFailedProviderDeleting,
9131
+ onChange: $event => (_ctx.setAllHealthCheckFailedProviderSelections($event.target.checked)),
9132
+ "aria-label": _ctx.t('config.health.failedProviders.selectAllAria')
9133
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["checked", "disabled", "onChange", "aria-label"]),
9134
+ _createElementVNode("span", null, _toDisplayString(_ctx.t('config.health.failedProviders.title')), 1 /* TEXT */)
9135
+ ]),
9136
+ _createElementVNode("span", { class: "health-failed-provider-actions" }, [
9137
+ _createElementVNode("button", {
9138
+ type: "button",
9139
+ class: "btn-link",
9140
+ disabled: !_ctx.getSelectableHealthCheckFailedProviderItems().length || _ctx.healthCheckFailedProviderDeleting,
9141
+ onClick: $event => (_ctx.setAllHealthCheckFailedProviderSelections(true))
9142
+ }, _toDisplayString(_ctx.t('config.health.failedProviders.selectAll')), 9 /* TEXT, PROPS */, ["disabled", "onClick"]),
9143
+ _createElementVNode("button", {
9144
+ type: "button",
9145
+ class: "btn-link",
9146
+ disabled: !_ctx.hasHealthCheckFailedProviderSelection() || _ctx.healthCheckFailedProviderDeleting,
9147
+ onClick: $event => (_ctx.setAllHealthCheckFailedProviderSelections(false))
9148
+ }, _toDisplayString(_ctx.t('config.health.failedProviders.clearSelection')), 9 /* TEXT, PROPS */, ["disabled", "onClick"]),
9149
+ _createElementVNode("span", { class: "latency error" }, _toDisplayString(_ctx.getHealthCheckFailedProviderItems().length), 1 /* TEXT */)
9150
+ ])
9151
+ ]),
9152
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.getHealthCheckFailedProviderItems(), (item) => {
9153
+ return (_openBlock(), _createElementBlock("label", {
9154
+ key: item.key,
9155
+ class: _normalizeClass(["model-item health-failed-provider-item", { disabled: !item.deletable }])
9156
+ }, [
9157
+ _createElementVNode("span", { class: "health-failed-provider-main" }, [
9158
+ _createElementVNode("input", {
9159
+ type: "checkbox",
9160
+ checked: item.selected,
9161
+ disabled: !item.deletable || _ctx.healthCheckFailedProviderDeleting,
9162
+ onChange: $event => (_ctx.toggleHealthCheckFailedProviderSelection(item, $event.target.checked)),
9163
+ "aria-label": _ctx.t('config.health.failedProviders.selectAria', { name: item.name })
9164
+ }, null, 40 /* PROPS, NEED_HYDRATION */, ["checked", "disabled", "onChange", "aria-label"]),
9165
+ _createElementVNode("span", null, [
9166
+ _createElementVNode("strong", null, _toDisplayString(item.name), 1 /* TEXT */),
9167
+ (item.detail)
9168
+ ? (_openBlock(), _createElementBlock("span", {
9169
+ key: 0,
9170
+ class: "form-hint"
9171
+ }, _toDisplayString(item.detail), 1 /* TEXT */))
9172
+ : _createCommentVNode("v-if", true),
9173
+ (!item.deletable)
9174
+ ? (_openBlock(), _createElementBlock("span", {
9175
+ key: 1,
9176
+ class: "form-hint"
9177
+ }, _toDisplayString(item.blockedReason === 'readonly' ? _ctx.t('config.health.failedProviders.writeRequired') : _ctx.t('config.health.failedProviders.notDeletable')), 1 /* TEXT */))
9178
+ : _createCommentVNode("v-if", true)
9179
+ ])
9180
+ ]),
9181
+ _createElementVNode("span", { class: "latency error" }, _toDisplayString(item.status), 1 /* TEXT */)
9182
+ ], 2 /* CLASS */))
9183
+ }), 128 /* KEYED_FRAGMENT */))
9184
+ ]))
9185
+ : _createCommentVNode("v-if", true),
9186
+ (_ctx.healthCheckResult.remote && _ctx.healthCheckResult.remote.speedTests)
9187
+ ? (_openBlock(), _createElementBlock("div", {
9188
+ key: 3,
9189
+ class: "model-list"
9190
+ }, [
9191
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.healthCheckResult.remote.speedTests, (result, name) => {
9192
+ return (_openBlock(), _createElementBlock("div", {
9193
+ key: 'health-speed-' + name,
9194
+ class: "model-item"
9195
+ }, [
9196
+ _createElementVNode("span", null, _toDisplayString(name), 1 /* TEXT */),
9197
+ (result && result.ok)
9198
+ ? (_openBlock(), _createElementBlock("span", {
9199
+ key: 0,
9200
+ class: "latency ok"
9201
+ }, _toDisplayString(_ctx.formatLatency(result)), 1 /* TEXT */))
9202
+ : (_openBlock(), _createElementBlock("span", {
9203
+ key: 1,
9204
+ class: "latency error"
9205
+ }, _toDisplayString((result && result.error) ? result.error : _ctx.t('config.health.fail')), 1 /* TEXT */))
9206
+ ]))
9207
+ }), 128 /* KEYED_FRAGMENT */))
9208
+ ]))
9209
+ : _createCommentVNode("v-if", true),
9210
+ (_ctx.healthCheckResult.issues && _ctx.healthCheckResult.issues.length)
9211
+ ? (_openBlock(), _createElementBlock("div", {
9212
+ key: 4,
9213
+ class: "model-list"
9214
+ }, [
9215
+ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.healthCheckResult.issues, (issue, index) => {
9216
+ return (_openBlock(), _createElementBlock("div", {
9217
+ key: issue.code || ('health-issue-' + index),
9218
+ class: "model-item"
9219
+ }, [
9220
+ _createElementVNode("span", null, _toDisplayString(issue.message || issue.code || ''), 1 /* TEXT */)
9221
+ ]))
9222
+ }), 128 /* KEYED_FRAGMENT */))
9223
+ ]))
8927
9224
  : _createCommentVNode("v-if", true)
8928
- ]),
8929
- (_ctx.healthCheckResult.remote && _ctx.healthCheckResult.remote.type === 'remote-health-check')
8930
- ? (_openBlock(), _createElementBlock("div", {
8931
- key: 0,
8932
- class: "form-hint"
8933
- }, [
8934
- _createTextVNode(_toDisplayString(_ctx.healthCheckResult.remote.endpoint || '') + " ", 1 /* TEXT */),
8935
- (_ctx.healthCheckResult.remote.statusCode)
8936
- ? (_openBlock(), _createElementBlock("span", { key: 0 }, " · " + _toDisplayString(_ctx.healthCheckResult.remote.statusCode), 1 /* TEXT */))
8937
- : _createCommentVNode("v-if", true),
8938
- (_ctx.healthCheckResult.remote.message)
8939
- ? (_openBlock(), _createElementBlock("span", { key: 1 }, " · " + _toDisplayString(_ctx.healthCheckResult.remote.message), 1 /* TEXT */))
8940
- : _createCommentVNode("v-if", true)
8941
- ]))
8942
- : _createCommentVNode("v-if", true),
8943
- (_ctx.healthCheckResult.remote && _ctx.healthCheckResult.remote.speedTests)
8944
- ? (_openBlock(), _createElementBlock("div", {
8945
- key: 1,
8946
- class: "model-list"
8947
- }, [
8948
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.healthCheckResult.remote.speedTests, (result, name) => {
8949
- return (_openBlock(), _createElementBlock("div", {
8950
- key: 'health-speed-' + name,
8951
- class: "model-item"
8952
- }, [
8953
- _createElementVNode("span", null, _toDisplayString(name), 1 /* TEXT */),
8954
- (result && result.ok)
8955
- ? (_openBlock(), _createElementBlock("span", {
8956
- key: 0,
8957
- class: "latency ok"
8958
- }, _toDisplayString(_ctx.formatLatency(result)), 1 /* TEXT */))
8959
- : (_openBlock(), _createElementBlock("span", {
8960
- key: 1,
8961
- class: "latency error"
8962
- }, _toDisplayString((result && result.error) ? result.error : _ctx.t('config.health.fail')), 1 /* TEXT */))
8963
- ]))
8964
- }), 128 /* KEYED_FRAGMENT */))
8965
- ]))
8966
- : _createCommentVNode("v-if", true),
8967
- (_ctx.healthCheckResult.issues && _ctx.healthCheckResult.issues.length)
8968
- ? (_openBlock(), _createElementBlock("div", {
8969
- key: 2,
8970
- class: "model-list"
8971
- }, [
8972
- (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.healthCheckResult.issues, (issue, index) => {
8973
- return (_openBlock(), _createElementBlock("div", {
8974
- key: issue.code || ('health-issue-' + index),
8975
- class: "model-item"
8976
- }, [
8977
- _createElementVNode("span", null, _toDisplayString(issue.message || issue.code || ''), 1 /* TEXT */)
8978
- ]))
8979
- }), 128 /* KEYED_FRAGMENT */))
8980
- ]))
8981
- : _createCommentVNode("v-if", true)
8982
- ], 64 /* STABLE_FRAGMENT */)),
8983
- _createElementVNode("div", { class: "btn-group" }, [
9225
+ ], 64 /* STABLE_FRAGMENT */))
9226
+ ]),
9227
+ _createElementVNode("div", { class: "btn-group health-check-modal-actions" }, [
9228
+ (_ctx.getHealthCheckFailedProviderItems().length)
9229
+ ? (_openBlock(), _createElementBlock("button", {
9230
+ key: 0,
9231
+ class: "btn btn-confirm btn-danger",
9232
+ disabled: _ctx.healthCheckFailedProviderDeleting || !_ctx.hasHealthCheckFailedProviderSelection(),
9233
+ onClick: $event => (_ctx.deleteSelectedHealthCheckFailedProviders())
9234
+ }, _toDisplayString(_ctx.healthCheckFailedProviderDeleting ? _ctx.t('config.health.failedProviders.deleting') : _ctx.t('config.health.failedProviders.deleteSelected')), 9 /* TEXT, PROPS */, ["disabled", "onClick"]))
9235
+ : _createCommentVNode("v-if", true),
8984
9236
  _createElementVNode("button", {
8985
9237
  class: "btn btn-confirm",
8986
9238
  onClick: $event => (_ctx.showHealthCheckModal = false)
@@ -478,7 +478,10 @@ export async function loadActiveSessionDetail(api, options = {}) {
478
478
  const nextLimit = Math.min(currentLimit + fetchStep, limitCap);
479
479
  if (nextLimit <= currentLimit) return;
480
480
  this.sessionDetailMessageLimit = nextLimit;
481
- this.sessionPreviewPendingVisibleCount = nextLimit;
481
+ const currentVisible = Number(this.sessionPreviewVisibleCount);
482
+ this.sessionPreviewPendingVisibleCount = Number.isFinite(currentVisible)
483
+ ? Math.max(0, Math.floor(currentVisible))
484
+ : 0;
482
485
  void this.loadActiveSessionDetail({ preserveVisibleCount: true });
483
486
  });
484
487
  }