diff --git a/astrbot/dashboard/routes/t2i.py b/astrbot/dashboard/routes/t2i.py index 634828e955..66a31e915e 100644 --- a/astrbot/dashboard/routes/t2i.py +++ b/astrbot/dashboard/routes/t2i.py @@ -7,6 +7,9 @@ from astrbot.core import logger from astrbot.core.core_lifecycle import AstrBotCoreLifecycle from astrbot.core.utils.t2i.template_manager import TemplateManager +from astrbot.core.utils.t2i.network_strategy import ( + get_shiki_runtime as _get_shiki_runtime, +) from .route import Response, Route, RouteContext @@ -26,6 +29,7 @@ def __init__( ("/t2i/templates/create", ("POST", self.create_template)), ("/t2i/templates/reset_default", ("POST", self.reset_default_template)), ("/t2i/templates/set_active", ("POST", self.set_active_template)), + ("/t2i/shiki_runtime", ("GET", self.get_shiki_runtime)), # 动态路由应该在静态路由之后注册 ( "/t2i/templates/", @@ -235,3 +239,14 @@ async def reset_default_template(self): response = jsonify(asdict(Response().error(str(e)))) response.status_code = 500 return response + + async def get_shiki_runtime(self): + """获取T2I Shiki运行时""" + try: + runtime = _get_shiki_runtime() + return jsonify(asdict(Response().ok(data={"runtime": runtime}))) + except Exception as e: + logger.error("Error in get_shiki_runtime", exc_info=True) + response = jsonify(asdict(Response().error(str(e)))) + response.status_code = 500 + return response diff --git a/changelogs/v4.23.2.md b/changelogs/v4.23.2.md index d6e91acea4..533fbc2164 100644 --- a/changelogs/v4.23.2.md +++ b/changelogs/v4.23.2.md @@ -5,6 +5,8 @@ ## What's Changed +> 在本次更新后,t2i 模板变量将会变更:渲染变量从 `{{ text | safe }}` 改为 `{{ text_base64 }}`,后端改为 base64 编码传输。您需要同步更新模板语法,否则文转图内容将无法正常渲染。 + ### 新增 - 知识库稀疏检索阶段新增 SQLite FTS5 支持,大幅优化万到十万级别分块时造成的召回时的显著卡顿。([#7648](https://github.com/AstrBotDevs/AstrBot/pull/7648)) @@ -39,6 +41,8 @@ ## What's Changed (EN) +> In this update, the t2i template variable will change: the rendering variable is changed from `{{ text | safe }}` to `{{ text_base64 }}`, and the backend now uses base64 encoding for transmission. Please update your template syntax accordingly, or text-to-image content will not render properly. + ### New Features - Added SQLite FTS5 support to the knowledge-base sparse retrieval stage, greatly reducing recall latency for knowledge bases with tens of thousands to hundreds of thousands of chunks. ([#7648](https://github.com/AstrBotDevs/AstrBot/pull/7648)) diff --git a/dashboard/src/components/shared/T2ITemplateEditor.vue b/dashboard/src/components/shared/T2ITemplateEditor.vue index eac49c7601..603494a703 100644 --- a/dashboard/src/components/shared/T2ITemplateEditor.vue +++ b/dashboard/src/components/shared/T2ITemplateEditor.vue @@ -78,6 +78,18 @@ + +
+ {{ tm('t2iTemplateEditor.syntaxMigrationHint') }} +
+
+ @@ -271,6 +283,9 @@ const applyAndCloseDialog = ref(false) const previewFrame = ref(null) +const syntaxHintDismissed = ref(false) +const showSyntaxMigrationHint = ref(false) + // --- 编辑器配置 --- const editorTheme = computed(() => 'vs-light') const editorOptions = { @@ -296,22 +311,39 @@ const syncPreviewVersion = async () => { } } +const shikiRuntime = ref('') +const syncShikiRuntime = async () => { + try { + const res = await axios.get('/api/t2i/shiki_runtime') + shikiRuntime.value = res?.data?.data?.runtime || res?.data?.runtime + } catch (error) { + console.warn('Failed to fetch shiki runtime:', error) + } +} + const previewData = computed(() => ({ text: tm('t2iTemplateEditor.previewText') || '这是一个示例文本,用于预览模板效果。\n\n这里可以包含多行文本,支持换行和各种格式。', - version: previewVersion.value + version: previewVersion.value, + shikiRuntime: shikiRuntime.value })) const previewContent = computed(() => { try { let content = templateContent.value - content = content.replace(/\{\{\s*text\s*\|\s*safe\s*\}\}/g, previewData.value.text) + content = content.replace(/\{\{\s*text_base64\s*\}\}/g, btoa(String.fromCharCode(...new TextEncoder().encode(previewData.value.text)))) content = content.replace(/\{\{\s*version\s*\}\}/g, previewData.value.version) + content = content.replace(/\{\{\s*shiki_runtime\s*\|\s*safe\s*\}\}/g, previewData.value.shikiRuntime) return content } catch (error) { return `
模板渲染错误: ${error.message}
` } }) +const dismissMigrationHint = () => { + showSyntaxMigrationHint.value = false + syntaxHintDismissed.value = true +} + // --- API 调用方法 --- const loadInitialData = async () => { loading.value = true @@ -458,11 +490,15 @@ const newTemplate = () => { New Template - -
{{ text | safe }}
+
+ + + document.getElementById('content').textContent = new TextDecoder().decode(Uint8Array.from(atob('{{ text_base64 }}'), c => c.charCodeAt(0))); + ` + } const promptDelete = () => { @@ -522,6 +558,12 @@ watch(selectedTemplate, (newName) => { } }) +watch(templateContent, (newContent) => { + if (!syntaxHintDismissed.value) { + showSyntaxMigrationHint.value = /\{\{\s*text\s*\|\s*safe\s*\}\}/.test(newContent) + } +}) + defineExpose({ openDialog: () => { dialog.value = true diff --git a/dashboard/src/i18n/locales/en-US/core/shared.json b/dashboard/src/i18n/locales/en-US/core/shared.json index beb486b303..d487163977 100644 --- a/dashboard/src/i18n/locales/en-US/core/shared.json +++ b/dashboard/src/i18n/locales/en-US/core/shared.json @@ -97,7 +97,8 @@ "livePreview": "Live Preview (may differ)", "refreshPreview": "Refresh Preview", "previewText": "This is a sample text used to preview the template output.\n\nIt can contain multiple lines and various formatting.", - "syntaxHint": "Supports jinja2 syntax. Available variables: text | safe (text to render), version (AstrBot version)", + "syntaxHint": "Supports Jinja2 syntax. Available variables: text_base64 (base64 encoded text to render), shiki_runtime | safe (Shiki runtime environment), version (AstrBot version)", + "syntaxMigrationHint": "Starting from v4.23.2, the rendering variable {{ text | safe }} has been changed to {{ text_base64 }} with base64 encoding. You need to update your template syntax accordingly, or the content will fail to render properly.", "saveAndApply": "Save and Apply Current Template", "confirmReset": "Confirm Reset", "confirmResetMessage": "Are you sure you want to reset the 'base' template to default content? Any unsaved changes in the editor will be lost. This action cannot be undone.", diff --git a/dashboard/src/i18n/locales/ru-RU/core/shared.json b/dashboard/src/i18n/locales/ru-RU/core/shared.json index 3ec2819618..d4865344fa 100644 --- a/dashboard/src/i18n/locales/ru-RU/core/shared.json +++ b/dashboard/src/i18n/locales/ru-RU/core/shared.json @@ -98,7 +98,8 @@ "livePreview": "Предпросмотр (может отличаться)", "refreshPreview": "Обновить", "previewText": "Это пример текста для предпросмотра результата шаблона.\n\nОн может содержать несколько строк и различные форматы.", - "syntaxHint": "Поддерживается синтаксис jinja2. Переменные: text | safe (текст для рендеринга), version (версия AstrBot)", + "syntaxHint": "Поддерживается синтаксис Jinja2. Переменные: text_base64 (base64-кодированный текст для рендеринга), shiki_runtime | safe (среда выполнения Shiki), version (версия AstrBot)", + "syntaxMigrationHint": "Начиная с v4.23.2, переменная рендеринга {{ text | safe }} изменена на {{ text_base64 }} с кодировкой base64. Вам необходимо обновить синтаксис шаблона, иначе содержимое не будет отображаться корректно.", "saveAndApply": "Сохранить и применить текущий шаблон", "confirmReset": "Подтверждение сброса", "confirmResetMessage": "Вы уверены, что хотите сбросить шаблон 'base' до значений по умолчанию? Все несохраненные изменения будут потеряны. Это действие необратимо.", @@ -109,4 +110,4 @@ "confirmAction": "Подтверждение действия", "confirmApplyMessage": "Вы уверены, что хотите сохранить изменения в '{name}' и сделать его активным шаблоном?" } -} \ No newline at end of file +} diff --git a/dashboard/src/i18n/locales/zh-CN/core/shared.json b/dashboard/src/i18n/locales/zh-CN/core/shared.json index fd064e2e41..31ffb580c5 100644 --- a/dashboard/src/i18n/locales/zh-CN/core/shared.json +++ b/dashboard/src/i18n/locales/zh-CN/core/shared.json @@ -97,7 +97,8 @@ "livePreview": "实时预览(可能有差异)", "refreshPreview": "刷新预览", "previewText": "这是一个示例文本,用于预览模板效果。\n\n这里可以包含多行文本,支持换行和各种格式。", - "syntaxHint": "支持 jinja2 语法。可用变量:text | safe(要渲染的文本), version(AstrBot 版本)", + "syntaxHint": "支持 Jinja2 语法。可用变量:text_base64(要渲染文本的 base64 编码)、shiki_runtime | safe(Shiki 运行时环境)、version(AstrBot 版本)", + "syntaxMigrationHint": "从 v4.23.2 开始,渲染变量 {{ text | safe }} 已改为 {{ text_base64 }} 并采用 base64 编码。您需要同步更新模板语法,否则内容将无法正常渲染。", "saveAndApply": "保存应用当前编辑模板", "confirmReset": "确认重置", "confirmResetMessage": "确定要将 'base' 模板恢复为默认内容吗?当前编辑器中的任何未保存更改将丢失。此操作无法撤销。",