Add a small badge next to the LangBot name in the sidebar header that reflects
systemInfo.edition: a neutral "Community" badge for the community edition and a
blue "Cloud" badge for the cloud edition. Adds sidebar.editionCommunity /
sidebar.editionCloud across all 8 locales.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The installed-extensions grouping is by extension format (plugin / MCP / skill),
so rename the toggle label accordingly across all 8 locales (key unchanged).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
check-i18n surfaced that market.componentName.*, market.filterByComponentHint
and the addExtension.install* keys existed only in en-US/zh-Hans. Backfill
them for es-ES, ja-JP, ru-RU, th-TH, vi-VN and zh-Hant (reusing each locale's
existing component-name translations) and align the filterByComponent label
with the new "Plugin Component" wording. check-i18n now passes for all locales.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When Box is disabled in config (``box.enabled = false``) or unreachable,
saving a new MCP server in stdio mode produced one that could never
start — the user would only learn that from the runtime error on the
detail page. Stop the user before they save instead.
Both MCP forms (the page-level ``MCPForm.tsx`` and the older dialog
``MCPFormDialog.tsx``) now:
- Disable the ``stdio`` option in the mode select when Box is
unavailable, with a small "(requires Box)" suffix so the reason is
obvious. Existing stdio configs still display their current value
- Show ``BoxUnavailableNotice`` inline under the mode select when the
currently-selected mode is stdio and Box is unavailable, so editing
a stale stdio config makes the cause visible
- Disable the Save / Submit button while stdio is selected under that
condition. ``MCPForm`` exposes a new ``onSaveBlockedChange`` prop
so the parent ``MCPDetailContent`` can disable both its Submit and
Save buttons. ``MCPFormDialog`` disables its Save button locally
- Refuse the submit handler too (Enter-key path) with a toast carrying
the same i18n message
i18n: ``mcp.boxRequired`` (short tag in the disabled option) and
``mcp.stdioBlockedByBoxToast`` added to all 8 locales.
Backend runtime gate (``_init_stdio_python_server`` refusal +
``BOX_UNAVAILABLE`` error_phase + retry short-circuit) stays in place
as the last line of defence for API bypass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously the MCP detail dialog dumped the raw RuntimeError text from
``_init_stdio_python_server`` — English-only, prefixed with "Failed
after 4 attempts", and exposing internal config names. The retry
wrapper also kept retrying a refusal that is deterministically going
to fail again, polluting logs.
Replace the raw text with a structured signal:
- New ``MCPSessionErrorPhase.BOX_UNAVAILABLE`` enum value. The stdio
refusal path sets it before raising and uses a short opaque
discriminator (``box_disabled_in_config`` / ``box_unavailable``) as
the message body — never user-facing
- ``_lifecycle_loop_with_retry`` short-circuits on
``BOX_UNAVAILABLE``: surfaces the error immediately, no retries,
no "Failed after N attempts" prefix. Silences the warning storm
seen during smoke-testing
- ``MCPServerRuntimeInfo`` (TS type) now declares ``error_phase``,
``retry_count``, ``box_session_id``, ``box_enabled`` to match what
the backend already returns in get_runtime_info_dict()
- Both MCP detail forms (``mcp/components/mcp-form/MCPForm.tsx`` and
``plugins/mcp-server/mcp-form/MCPFormDialog.tsx``) detect
``error_phase === 'box_unavailable'`` and render a two-line
localized notice: state line ("Box disabled / unreachable") plus
remediation line ("enable Box or switch to http/sse")
- 8 locale files (en/zh-Hans/zh-Hant/ja/ru/vi/th/es) get
``mcp.boxDisabledStdioRefused``, ``mcp.boxUnavailableStdioRefused``,
``mcp.boxStdioRefusedSuggestion``
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When Box is disabled in config (``box.enabled = false``) or fails to
connect, every dependent UI surface now degrades visibly:
- ``useBoxStatus`` hook: shared, polled 30s, exposes ``available``,
``disabled`` (config-off) and a single ``hint`` key so callers don't
have to re-derive the three states
- ``BoxUnavailableNotice`` reusable Alert banner driven by that hint
- Dashboard SystemStatusCards: three-state dot + label
(connected / disabled-gray / disconnected-red); disabled state shows
the ``boxDisabled`` hint, failed state continues to show the connector
error. Plugin block kept untouched
- Skills page (create view) and SkillDetailContent (edit view):
Save button disabled and banner inserted above the form when Box is
unavailable — matches the backend gate added in the previous commit
- PipelineExtension skill section: ``enable_all_skills`` switch, Add
Skill button and Remove buttons all gate on Box availability;
banner inline under the section header
- PipelineFormComponent: banner above the ``local-agent`` stage card
when Box is unavailable, since that stage carries the sandbox-bound
``box-session-id-template`` field
- Box status payload type (``ApiRespBoxStatus.enabled``) and 8 locale
files updated with ``boxDisabled`` / ``boxUnavailable`` /
``boxRequiredHint`` strings
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add engineSettingsInvalid and retrievalSettingsInvalid keys to all
locale files (zh-Hant, ja-JP, vi-VN, es-ES, ru-RU, th-TH) for the
new dynamic form validation feature.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Rename /home/plugins route to /home/extensions and update all sidebar links.
- Add unified GET /api/v1/extensions returning plugins, MCP servers and skills,
sorted by name; replace the three separate frontend fetches with this single call.
- Migrate the extensions page to shadcn primitives (Tabs/Card/Alert/Badge/Skeleton/
Switch/Label) and clean up hardcoded color tokens on the extension card.
- Add a localStorage-persisted "Group by type" switch that, when enabled in the
All Types tab, renders extensions grouped by type with a compact section header.
- Show a spinner while loading and rename the empty-state copy from
"No plugins installed" to "No extensions installed".
- Rename the "格式 / Formats" filter label to "类型 / Types" across all 8 locales.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the dropdown popover with a proper Dialog for runtime status
details. Add a small info button on the System Status card that opens
the dialog. Session details now show in a spacious 2-column grid layout
with full image name, backend, CPU/memory, network, mount path, and
created/last-used timestamps.
Replace the separate two-card row with a single compact 'System Status'
card placed as the 5th column in the metrics grid. Shows green/red dots
for Plugin Runtime and Box Runtime. Click to expand a popover with
connection details (backend, profile, sandbox count).
Add SystemStatusCards component to the monitoring dashboard showing
Plugin Runtime and Box Runtime connection status with details (backend,
profile, sandbox count). Remove all Box/session status from the plugin
page debug popover — it now only shows debug URL and key.
Includes i18n for all 8 supported languages.
Display sandbox count and a detailed list of active sessions including
session ID, image, backend, resources (CPU/memory), network mode, and
last used time. Fetched from GET /api/v1/box/sessions in parallel.
Includes i18n for all 8 supported languages.
The active_sessions count reflects transient sandbox containers that
expire after 5 minutes of inactivity, making it misleading in the UI.
Keep only connection status, backend, profile, and error count.
Add Box status section to the debug info popover on the plugin list page,
displaying connection status, backend info, profile, active sessions,
and recent error count. Fetched from GET /api/v1/box/status in parallel
with plugin debug info. Includes i18n for all 8 supported languages.
Add 'object' as a new value type for model extra parameters so users can
configure nested JSON like {"thinking": {"type": "disabled"}} required by
DeepSeek-v4 non-thinking mode (refs #2157).
UI: add 'Object' option to the type dropdown in ExtraArgsEditor; render a
full-width JSON Textarea (resize-y, monospace) with live JSON validation.
On save, JSON is parsed and rejected if not a plain object.
Also make the model edit and add-model popovers scrollable: cap height at
min(70vh, --radix-popover-content-available-height), stop wheel/touchmove
propagation so the dialog's react-remove-scroll lock doesn't swallow
events, and use overscroll-none to avoid the bottom border seam from
rubber-band overscroll.
i18n updated for all 8 locales.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add sidebar.pluginPages, sidebar.pluginPagesTooltip, pluginPages
section, and plugins.componentName.Page to es-ES, ja-JP, ru-RU,
th-TH, vi-VN, zh-Hant to fix CI i18n key check.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>