Skip to content

Commit 296e49e

Browse files
MomiJiSanHongzhi Wenclaude
authored
galgame_plugin: prompt 英文化 + install 路由解耦 + choice_advisor fast loop 修复 (Project-N-E-K-O#1133)
* Add galgame plugin implementation * Wire galgame plugin into host runtime * Add galgame plugin regression coverage * Fix diagnose push lint entrypoint * PluginUIFrame 通过 iframe 加载插件 UI 页面,原 frame-ancestors 'none' 会指示浏览器拒绝任何 iframe 嵌入,导致 UI 空白。 改为 'self' 允许同源嵌入。 * _resolve_install_task_payload (line 220) 现在先校验 task_id,非法值直接 400,不会再进 load_install_task_state()。 _install_stream_response (line 355) 在返回 StreamingResponse 前先调用 _resolve_install_task_payload(),不存在的 task 会干净地返回 404,不会启动后才炸 SSE * 实现哀鸿选项 OCR 空间区域过滤 - 新增 AIHONG_CHOICES_REGION_PRESET,定义哀鸿选项检测区域为画面高度 20%-60% - 新增 OCR box 空间过滤逻辑,仅将中间区域文本送入 menu_stage 选项识别 - 为 source_height 增加降级推导:source_size、window_rect、boxes 最大 bottom、1080 - 调整 choices_shown bounds 匹配,使用过滤后的 choice boxes,减少标题栏、HUD、对白污染 - 补充哀鸿选项区域过滤与全屏 OCR 污染回归测试 验证: - py_compile passed - test_galgame_ocr_reader.py -k "aihong_choice_region or aihong_menu_stage_filters": 2 passed - test_galgame_ocr_reader.py -k "aihong_menu": 9 passed * 新增 AIHONG_CHOICES_REGION_PRESET,把哀鸿选项识别区域设为画面高度 20% - 60%。 - 新增 OCR boxes 空间过滤函数,只保留中间区域文本参与选项识别。 - 改造哀鸿 menu_stage 识别入口,避免标题栏、HUD、底部对白混入纯文字选项判断。 - 选项 bounds 匹配改用过滤后的 boxes。 - 补充 2 个针对性单测,并确认 aihong_menu 相关测试通过。 * Delete CODE/md/galgame-memory-reader-restart-loop-ocr-fallback-2026-05-04.md 清理文档 * Delete docs/plugins/galgame_agent_context_push_chain_review.md 清理文档 * Delete ocr_debug_capture.png * 清理 galgame 插件对 core/task_executor 的专用代码污染 - 将 galgame scene_summary 的上下文提示模板下沉到 galgame 插件侧预组装 - 删除 brain/task_executor.py 中 galgame 专用关键词命令路由 - 删除 main_logic/core.py 中 galgame 专用 callback 判断、prefix strip 和 instruction builder - galgame 控制命令改为走现有通用 UserPlugin LLM 评估路径 - 更新回归测试,断言 galgame 命令通过通用插件评估而不是硬编码路由 验证: - py_compile passed - test_agent_rewrite_regression.py 相关用例:3 passed - test_proactive_sm_integration.py:10 passed - test_galgame_bridge.py scene_summary 相关用例:2 passed main_routers/agent_router.py - openclaw availability timeout: 4.5s -> 4.0s * plugin desc enum 截断格式化:把 "..." 移进 [] 内并附剩余数量 原渲染对超过 12 个 enum 值的字段是 `enum=[a|b|c]...`,孤零零的 "..." 贴在 ] 外面,LLM 容易把可见 12 个值误读为完整白名单,把用户实际想要 的(被截断掉的)合法值替换成最相近的可见值,或直接拒绝执行。 改成 `enum=[a|b|c|... +N more]`,把省略号放进 [] 内并明确告诉 LLM "还有 N 个未列出的合法值"。N 来自 len(enum_values) - 12。 ≤12 的渲染保持原样不动,原有 test_task_executor_plugin_desc_includes_enum_values 不受影响;新增 test_task_executor_plugin_desc_truncates_long_enum_with_remainder_hint 覆盖截断分支,断言新格式 + 旧的 "]..." 形态不再出现。 验证: - pytest tests/test_agent_rewrite_regression.py 95 passed Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * 解决 codex P1(共享路由聚合层 galgame 污染)+ P2(Open UI 忽略 list_action target/open_in) P1 — plugin/server/routes/__init__.py:18 + plugin/server/http_app.py:30,172 共享路由聚合层(plugin/server/routes/__init__.py)原本 hardcode `from plugin.plugins.galgame_plugin.install_routes import ...`,是 commit 0ddcd26 "OCR 区域过滤" 夹带进去的 stealth import,d8e82c00 "清理 galgame 污染" 漏扫这一层。symptom:galgame plugin 任何 import-time 副作用炸(缺 dxcam / tesseract / textractor 可选依赖、非 Windows 环境 等)→ 整个 plugin server 启动 fail,而不是只让 install 端点 404。 修法: - 共享聚合层 plugin/server/routes/__init__.py 完全不再认识 galgame, 和 mcp_adapter / sts2_autoplay 看齐 - galgame import 移到 plugin/server/http_app.py 的 build_plugin_server_app() 内部,try/except ImportError 兜住;失败时 logger.warning + 跳过 include - 顶层 builder 仍 hardcode 知道 galgame 是个特殊 case,但已经从"hard 依赖"降级为"optional 依赖"语义;彻底去 hardcode 的方案 B(plugin SDK 自己注册 router)改动跨 plugin loader,留给 follow-up 验证: - python -c 'build_plugin_server_app()' 正常:86 routes(含 16 galgame) - 模拟 plugin.plugins.galgame_plugin.install_routes ImportError: app 仍能 build,70 routes(无 galgame),WARNING 落日志 - pytest plugin/tests/unit/server/ → 135 passed P2 — frontend/plugin-manager/src/components/plugin/PluginActions.vue:103 backend ui_query_service.py 的 _normalize_list_action 已经在 L460-487 显式 normalize `target` 和 `open_in` 进 list_action 契约,frontend types/api.ts:51-52 也已经声明这两个字段为可选,但 PR 新加的 handleOpenUi 直接 hardcode `router.push({ path: /plugins/{id}, query: { tab: 'ui' } })`,把契约里两个字段全丢了。symptom:plugin 配置 `kind: "ui"` + 外部 URL target / `open_in: "new_tab"` → 按钮静默跳错 地方。 修法:handleOpenUi 按 4 个组合分支: - 外部 URL (http/https) target × open_in → window.open / location.href - 内部路由 target × open_in → router.resolve+window.open / router.push - 无 target → 回退到原 ?tab=ui 默认行为,open_in 仍生效 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * plugin list_action label / confirm_message i18n dict 解析(修 P3 + 老 bug) CodeRabbit 在 cd051ce 上指出 PluginActions.vue:11 的 `{{ uiAction.label || t(...) }}` 在 label 是 i18n 字典对象时会渲染成 `[object Object]`。 backend `_normalize_plugin_list_action`(plugin/server/application/plugins/ ui_query_service.py L454-487)显式接受 `label` / `confirm_message` 为 string 或 locale-keyed dict(e.g. `{"en-US": "Open UI", "zh-CN": "打开界面"}`), 而 `resolve_i18n_refs`(plugin/sdk/shared/i18n.py L155)只解析 `$i18n` ref, 不会把 locale-keyed 字典拍平,所以 dict 会原样发到 frontend。模板里直接 `{{ value }}` 在 dict 时会渲染成 "[object Object]"。 audit 全 frontend 后发现这是 systemic 老 bug(不只是 PR 引入): - PluginActions.vue:11 ← PR 引入 - usePluginListContextActions.ts:107 resolveActionLabel ← 老 bug - usePluginListContextActions.ts:230 confirmIfNeeded ← 老 bug - PluginList.vue:332 dangerDialog message ← 老 bug 修法: - 新增 utils/i18nLabel.ts 提供 `resolveLocalizedText(value, locale, fallback)` helper,按 locale 完整匹配 → 主语言降级 → en-US/en 兜底 → 字典首项 → fallback 五级解析 - types/api.ts: PluginListAction.label / confirm_message 改为 `LocalizedText = string | Record<string, string>`,contract 与 backend 对齐 - 4 处消费点改用 helper: - PluginActions.vue: 用 computed `uiActionLabel` - usePluginListContextActions.ts: resolveActionLabel + confirmIfNeeded 都走 helper,前者 helper 解析空时仍 fallback 到内置 i18n key - PluginList.vue: dangerDialog 的 :message 用 computed `dangerDialogMessage` - ResolvedPluginListAction 已在 `& { label: string }` 把 label resolve 为 string,下游 PluginContextMenu / Resolved 消费点不受影响 验证: - `npm run type-check` (vue-tsc --build) 通过 - 我修改的文件 lint 0 引入新 error(pre-existing `any` 类型 error 全在 未修改区域) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Open UI 按钮 open_in 缺省与 list-action executor convention 对齐 codex 在 08732c1 上指出 handleOpenUi 把缺省 open_in 视为 same-tab (`action.open_in === 'new_tab'`),但 usePluginListContextActions.ts:366 的 list-action executor 缺省视为 new-tab (`action.open_in === 'same_tab' ? '_self' : '_blank'`)。 后果:在同一个 plugin manager 里,"Open UI" 按钮和右键菜单 action 对同一个 `kind: "ui"` action(plugin 没显式声明 open_in 时)行为分叉 ——一个替换当前页、一个新开 tab,用户体验不一致。 修法:把判断翻成 `action.open_in !== 'same_tab'`,让 undefined → new_tab 与 executor 对齐。plugin 显式设 same_tab 仍然受尊重。 验证:vue-tsc --build 通过。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * handleOpenUi 走 browser navigation + fetchStaticUI 加 stale-response guard P2-A — PluginActions.vue:143 (codex) handleOpenUi 在 same_tab + non-HTTP target 时走 router.push(target),但 SPA router(src/router/index.ts)只定义 manager 内部路由(/plugins/:id 等), plugin server 暴露的 path(如 /plugin/<id>/ui/)会被当 unmatched route, UI 打不开。 修法:和 usePluginListContextActions.ts:366 的 list-action executor 行为 对齐——`kind === 'ui'` 的 action 永远走 browser navigation (window.open with _blank/_self),不再按 http vs 内部 path 分两条路径。 仅"无 target → 默认 plugin 详情页 ?tab=ui"这条 fallback 仍走 router.push (这是真正的 manager 内部路由)。 P2-B — PluginDetail.vue:310 (codex / CodeRabbit 之前 r3183397668 也提过) fetchStaticUI 没有 stale-response guard,用户快速切换 plugin detail 页 时旧 plugin 的 /ui-info 响应可能在新 plugin 加载后才到,覆盖 hasStaticUI 导致 UI tab 显示状态错位。 修法:照搬 fetchSurfaces 的 pattern——加 currentStaticUiLoadId 模块级 counter,fetchStaticUI 入口 ++loadId + snapshot pluginId,响应到来时 任一不匹配就丢弃。 验证:vue-tsc --build 通过。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * handleOpenUi 跳转前尊重 action.confirm_message CodeRabbit 在 2c8a90e 上指出 handleOpenUi 没有调用确认守卫,list-action executor (usePluginListContextActions.ts:executeAction L350) 对 `kind === 'ui'` action 跳转前会先调 confirmIfNeeded 弹确认框,但 Open UI 按钮直接跳过——plugin 给 ui action 配 confirm_message 时两处行为分叉, 按钮绕过了 plugin 自己配的二次确认。 修法:与 confirmIfNeeded (L226-244) 行为对齐——dialog mode 时若解析出 confirm_message 就 ElMessageBox.confirm,用户取消则 return。 hold mode 依赖 host 组件(PluginDangerConfirmDialog)呈现,按钮上下文 不支持,跳过即可(plugin 给 kind: "ui" 配 hold mode 极少见)。 confirm_message 走 resolveLocalizedText(i18nLabel.ts),与之前 P3 一致 处理 string / locale-keyed dict。 验证:vue-tsc --build 通过。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Hongzhi Wen <cartabio.coder1@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b9c0dc9 commit 296e49e

76 files changed

Lines changed: 73166 additions & 21 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

brain/task_executor.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,7 @@ def __init__(self, computer_use: Optional[ComputerUseAdapter] = None, browser_us
235235
def _normalize_correction_tool_name(self, value: Any) -> str:
236236
tool = str(value or "").strip().lower()
237237
return self._correction_tool_canonical.get(tool, "")
238-
239-
238+
240239
def set_plugin_list_provider(self, provider: Callable[[bool], Awaitable[List[Dict[str, Any]]]]):
241240
"""Allow agent_server to inject a custom async provider for plugin discovery."""
242241
self._external_plugin_provider = provider
@@ -1073,7 +1072,22 @@ def _build_plugin_desc_lines(self, plugins: Any) -> list:
10731072
fields = []
10741073
for fname, fdef in list(props.items())[:8]:
10751074
ftype = fdef.get("type", "any") if isinstance(fdef, dict) else "any"
1076-
fields.append(f"{fname}:{ftype}")
1075+
enum_hint = ""
1076+
if isinstance(fdef, dict):
1077+
enum_values = fdef.get("enum")
1078+
if isinstance(enum_values, list) and enum_values:
1079+
shown = [str(v) for v in enum_values[:12]]
1080+
inner = "|".join(shown)
1081+
# 截断时把 "..." 放进 [] 内,并附上剩余数量。
1082+
# 让 LLM 明确知道 "还有 N 个未列出的合法值",
1083+
# 而不是把可见 12 个误当成完整白名单。
1084+
if len(enum_values) > 12:
1085+
enum_hint = (
1086+
f" enum=[{inner}|... +{len(enum_values) - 12} more]"
1087+
)
1088+
else:
1089+
enum_hint = f" enum=[{inner}]"
1090+
fields.append(f"{fname}:{ftype}{enum_hint}")
10771091
required = schema.get("required", [])
10781092
req_str = f" required={required}" if required else ""
10791093
schema_hint = f" args({', '.join(fields)}{req_str})"

frontend/plugin-manager/src/components/plugin/PluginActions.vue

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
<template>
22
<div class="plugin-actions">
3+
<el-button
4+
v-if="uiAction"
5+
type="primary"
6+
plain
7+
:icon="Monitor"
8+
@click="handleOpenUi"
9+
:disabled="uiDisabled"
10+
>
11+
{{ uiActionLabel }}
12+
</el-button>
313
<!-- Extension 操作按钮 -->
414
<el-button-group v-if="isExtension">
515
<el-button
@@ -56,18 +66,21 @@
5666

5767
<script setup lang="ts">
5868
import { ref, computed } from 'vue'
69+
import { useRouter } from 'vue-router'
5970
import { useI18n } from 'vue-i18n'
60-
import { VideoPlay, VideoPause, Refresh, SwitchButton } from '@element-plus/icons-vue'
71+
import { VideoPlay, VideoPause, Refresh, SwitchButton, Monitor } from '@element-plus/icons-vue'
6172
import { ElMessage, ElMessageBox } from 'element-plus'
6273
import { usePluginStore } from '@/stores/plugin'
74+
import { resolveLocalizedText } from '@/utils/i18nLabel'
6375
6476
interface Props {
6577
pluginId: string
6678
}
6779
6880
const props = defineProps<Props>()
6981
const pluginStore = usePluginStore()
70-
const { t } = useI18n()
82+
const router = useRouter()
83+
const { t, locale } = useI18n()
7184
7285
const loading = ref(false)
7386
@@ -78,6 +91,88 @@ const currentPlugin = computed(() => {
7891
const status = computed(() => currentPlugin.value?.status || 'stopped')
7992
const isExtension = computed(() => currentPlugin.value?.type === 'extension')
8093
const isDisabled = computed(() => status.value === 'disabled')
94+
const uiAction = computed(() => {
95+
return currentPlugin.value?.list_actions?.find((action) => action.kind === 'ui') || null
96+
})
97+
const uiDisabled = computed(() => {
98+
if (!uiAction.value) return true
99+
if (uiAction.value.disabled) return true
100+
if (uiAction.value.requires_running && status.value !== 'running') return true
101+
return false
102+
})
103+
// label 可能是 string 或 locale-keyed dict(与 backend list_action contract
104+
// 对齐,见 utils/i18nLabel.ts)。直接 `{{ uiAction.label }}` 在 dict 时会
105+
// 渲染成 "[object Object]",必须先按当前 locale 解析。
106+
const uiActionLabel = computed(() =>
107+
resolveLocalizedText(uiAction.value?.label, locale.value, t('plugins.ui.open')),
108+
)
109+
110+
async function handleOpenUi() {
111+
if (!uiAction.value || uiDisabled.value) {
112+
return
113+
}
114+
115+
// 尊重 backend 的 list_action 契约(plugin/server/application/plugins/ui_query_service.py
116+
// _normalize_list_action 会显式 normalize `target` 和 `open_in`)。
117+
// 若 plugin 声明了外部 URL / 自定义路由 / 新 tab 打开,UI 必须按字段路由,
118+
// 而不是无条件回退到默认的 `/plugins/{id}?tab=ui` 静态详情页。
119+
const action = uiAction.value
120+
121+
// 与 usePluginListContextActions.ts confirmIfNeeded 行为对齐:跳转前若
122+
// plugin 声明了 confirm_message 就弹 dialog 确认,否则按钮会绕过 plugin
123+
// 自己配的二次确认。`confirm_mode === 'hold'` 依赖 PluginDangerConfirmDialog
124+
// 这种 host 组件呈现,按钮上下文不支持,跳过即可(plugin 给 kind: "ui"
125+
// 配 hold mode 极少见)。
126+
if (action.confirm_mode !== 'hold') {
127+
const confirmMsg = resolveLocalizedText(action.confirm_message, locale.value, '')
128+
if (confirmMsg) {
129+
try {
130+
await ElMessageBox.confirm(confirmMsg, t('common.confirm'), {
131+
type: action.danger ? 'warning' : 'info',
132+
})
133+
} catch {
134+
return
135+
}
136+
}
137+
}
138+
139+
const target = action.target?.trim() || ''
140+
// open_in 缺省时统一默认 new_tab,与 usePluginListContextActions.ts:366
141+
// 的 list-action executor convention 对齐(`open_in === 'same_tab' ? '_self'
142+
// : '_blank'`)。否则同一个 plugin manager 里 Open UI 按钮和右键菜单
143+
// action 行为分叉,用户体验不一致。
144+
const openInNewTab = action.open_in !== 'same_tab'
145+
146+
// 显式 target:用 browser navigation(window.open),不走 SPA router——
147+
// 与 list-action executor 的 ui/url 分支行为一致。SPA router(
148+
// src/router/index.ts)只认识 manager 内部路由(/plugins/:id 等),plugin
149+
// server 暴露的 path(如 /plugin/<id>/ui/)和外部 URL 都得走 browser
150+
// navigation 才能正确跳转,否则 same_tab + plugin-server path 会被当
151+
// unmatched SPA route,UI 不打开。
152+
if (target) {
153+
const windowTarget = openInNewTab ? '_blank' : '_self'
154+
window.open(
155+
target,
156+
windowTarget,
157+
openInNewTab ? 'noopener,noreferrer' : undefined,
158+
)
159+
return
160+
}
161+
162+
// 无 target 时退回默认 plugin 详情页 ?tab=ui,这是 manager 内部路由,
163+
// 用 router.push 走 SPA 内导航更平顺;new_tab 时仍 window.open 新窗口。
164+
const fallback = {
165+
path: `/plugins/${encodeURIComponent(props.pluginId)}`,
166+
query: { tab: 'ui' },
167+
}
168+
if (openInNewTab) {
169+
const resolved = router.resolve(fallback)
170+
window.open(resolved.href, '_blank', 'noopener,noreferrer')
171+
} else {
172+
await router.push(fallback)
173+
}
174+
}
175+
81176
async function handleStart() {
82177
if (isDisabled.value) {
83178
ElMessage.warning(t('messages.pluginDisabled'))
@@ -170,5 +265,6 @@ async function handleEnableExt() {
170265
.plugin-actions {
171266
display: flex;
172267
gap: 8px;
268+
flex-wrap: wrap;
173269
}
174270
</style>

frontend/plugin-manager/src/components/plugin/PluginUIFrame.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const { t } = useI18n()
5959
6060
const iframeRef = ref<HTMLIFrameElement | null>(null)
6161
const iframeKey = ref(0)
62+
const uiCacheBust = ref(Date.now())
6263
const loading = ref(true)
6364
const error = ref<string | null>(null)
6465
const hasUI = ref(false)
@@ -71,7 +72,7 @@ const uiUrl = computed(() => {
7172
// This component is the original static UI iframe path. New entry points
7273
// should consume PluginUiSurface and render static panels through the
7374
// surface container, while this remains as compatibility renderer.
74-
return `/plugin/${encodeURIComponent(props.pluginId)}/ui/`
75+
return `/plugin/${encodeURIComponent(props.pluginId)}/ui/?_ui=${uiCacheBust.value}`
7576
})
7677
7778
async function checkUIAvailability() {
@@ -120,10 +121,12 @@ async function reload() {
120121
// UI availability already confirmed (iframe load failed); skip network call
121122
error.value = null
122123
loading.value = true
124+
uiCacheBust.value = Date.now()
123125
iframeKey.value++
124126
} else {
125127
await checkUIAvailability()
126128
if (hasUI.value && !error.value) {
129+
uiCacheBust.value = Date.now()
127130
iframeKey.value++
128131
}
129132
}
@@ -168,6 +171,7 @@ onUnmounted(() => {
168171
})
169172
170173
watch(() => props.pluginId, () => {
174+
uiCacheBust.value = Date.now()
171175
checkUIAvailability()
172176
})
173177
</script>

frontend/plugin-manager/src/composables/usePluginListContextActions.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { deletePlugin } from '@/api/plugins'
55
import { packPluginCli } from '@/api/pluginCli'
66
import { usePluginStore } from '@/stores/plugin'
77
import type { PluginListAction, PluginMeta } from '@/types/api'
8+
import { resolveLocalizedText } from '@/utils/i18nLabel'
89

910
type PluginListContextPlugin = PluginMeta & {
1011
status?: string
@@ -34,7 +35,7 @@ function replacePluginTokens(value: string, pluginId: string): string {
3435
export function usePluginListContextActions() {
3536
const router = useRouter()
3637
const pluginStore = usePluginStore()
37-
const { t } = useI18n()
38+
const { t, locale } = useI18n()
3839

3940
function isRunning(plugin: PluginListContextPlugin): boolean {
4041
return plugin.status === 'running'
@@ -105,8 +106,11 @@ export function usePluginListContextActions() {
105106
}
106107

107108
function resolveActionLabel(action: PluginListAction): string {
108-
if (action.label) {
109-
return action.label
109+
// 后端 label 可能是 string 或 locale-keyed dict,统一走 resolveLocalizedText
110+
// 解析;解析后为空再回退到内置 action id 对应的 i18n key。
111+
const localized = resolveLocalizedText(action.label, locale.value, '')
112+
if (localized) {
113+
return localized
110114
}
111115
switch (action.id) {
112116
case 'open_detail':
@@ -223,11 +227,15 @@ export function usePluginListContextActions() {
223227
if (action.confirm_mode === 'hold') {
224228
return true
225229
}
226-
if (!action.confirm_message) {
230+
// confirm_message 与 label 同样是 LocalizedText(string 或 locale-keyed
231+
// dict),不能直接传给 ElMessageBox.confirm(它会把 dict 渲染成
232+
// "[object Object]")。解析为空时跳过确认。
233+
const message = resolveLocalizedText(action.confirm_message, locale.value, '')
234+
if (!message) {
227235
return true
228236
}
229237
try {
230-
await ElMessageBox.confirm(action.confirm_message, t('common.confirm'), {
238+
await ElMessageBox.confirm(message, t('common.confirm'), {
231239
type: action.danger ? 'warning' : 'info',
232240
})
233241
return true

frontend/plugin-manager/src/i18n/locales/en-US.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export default {
240240
},
241241
ui: {
242242
open: 'Open UI',
243+
title: 'UI',
243244
panel: 'Panel',
244245
guide: 'Guide',
245246
loading: 'Loading plugin UI...',

frontend/plugin-manager/src/i18n/locales/es.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export default {
240240
},
241241
ui: {
242242
open: 'Abrir UI',
243+
title: 'UI',
243244
panel: 'Panel',
244245
guide: 'Tutorial',
245246
loading: 'Cargando UI del plugin...',

frontend/plugin-manager/src/i18n/locales/ja.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export default {
240240
},
241241
ui: {
242242
open: 'UIを開く',
243+
title: 'UI',
243244
panel: 'パネル',
244245
guide: 'チュートリアル',
245246
loading: 'プラグインUIを読み込み中...',

frontend/plugin-manager/src/i18n/locales/ko.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export default {
240240
},
241241
ui: {
242242
open: 'UI 열기',
243+
title: 'UI',
243244
panel: '패널',
244245
guide: '튜토리얼',
245246
loading: '플러그인 UI 로딩 중...',

frontend/plugin-manager/src/i18n/locales/pt.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export default {
240240
},
241241
ui: {
242242
open: 'Abrir UI',
243+
title: 'UI',
243244
panel: 'Painel',
244245
guide: 'Tutorial',
245246
loading: 'Carregando UI do plugin...',

frontend/plugin-manager/src/i18n/locales/ru.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ export default {
240240
},
241241
ui: {
242242
open: 'Открыть UI',
243+
title: 'UI',
243244
panel: 'Панель',
244245
guide: 'Обучение',
245246
loading: 'Загрузка интерфейса плагина...',

0 commit comments

Comments
 (0)