From 20b6be987f5029e36bd2db7d074704854bcaa917 Mon Sep 17 00:00:00 2001
From: insistence <3055204202@qq.com>
Date: Sat, 1 Aug 2026 17:40:43 +0800
Subject: [PATCH 1/2] =?UTF-8?q?chore:=20=E5=8D=87=E7=BA=A7=E4=BE=9D?=
=?UTF-8?q?=E8=B5=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ruoyi-fastapi-backend/plugins/ai/plugin.yaml | 30 ++++++++++---------
ruoyi-fastapi-backend/requirements-pg.txt | 24 +++++++--------
ruoyi-fastapi-backend/requirements.txt | 24 +++++++--------
ruoyi-fastapi-frontend/package.json | 10 ++++---
ruoyi-fastapi-frontend/plugins/ai/README.md | 2 ++
.../ai/views/chat/components/AiMessage.vue | 16 ++++++++--
ruoyi-fastapi-frontend/vue.config.js | 10 ++++++-
7 files changed, 71 insertions(+), 45 deletions(-)
diff --git a/ruoyi-fastapi-backend/plugins/ai/plugin.yaml b/ruoyi-fastapi-backend/plugins/ai/plugin.yaml
index 281eb31..4e1da1c 100644
--- a/ruoyi-fastapi-backend/plugins/ai/plugin.yaml
+++ b/ruoyi-fastapi-backend/plugins/ai/plugin.yaml
@@ -74,25 +74,27 @@ permissions:
dependencies:
python:
- - agno==2.4.8
- - anthropic==0.78.0
- - cerebras-cloud-sdk==1.67.0
- - cohere==5.20.4
- - google-genai==1.62.0
- - groq==1.0.0
- - litellm==1.81.8
+ - agno==2.8.6
+ - anthropic==0.120.2
+ - cerebras-cloud-sdk==1.91.0
+ - cohere==7.0.8
+ - google-genai==2.16.0
+ - groq==1.6.0
+ - litellm==1.94.0
- llama-api-client==0.6.0
- - mistralai==1.12.0
- - ollama==0.6.1
- - openai==2.17.0
- - portkey-ai==2.1.0
+ - mistralai==2.8.0
+ - ollama==0.6.2
+ - openai==2.52.0
+ - portkey-ai==2.3.4
npm:
- '@antv/infographic^0.2.13'
+ - '@terrastruct/d2>=0.1.33'
- katex>=0.16.27
- - markstream-vue2^0.0.18
- - mermaid>=11.12.2
+ - markstream-vue2^0.0.50
+ - mermaid>=11.15.0
- shiki^3.21.0
- - stream-markdown>=0.0.14
+ - stream-markdown>=0.0.16
+ - stream-monaco>=0.0.48
npmDev: []
plugins: []
diff --git a/ruoyi-fastapi-backend/requirements-pg.txt b/ruoyi-fastapi-backend/requirements-pg.txt
index 6d17713..e544a3e 100644
--- a/ruoyi-fastapi-backend/requirements-pg.txt
+++ b/ruoyi-fastapi-backend/requirements-pg.txt
@@ -1,24 +1,24 @@
aiofiles==25.1.0
-alembic==1.18.3
-APScheduler==3.11.2
-async-lru==2.1.0
+alembic==1.18.5
+APScheduler==3.11.3
+async-lru==2.3.0
asyncpg==0.31.0
bcrypt==5.0.0
-fastapi[all]==0.128.2
+fastapi[all]==0.141.1
loguru==0.7.3
openpyxl==3.1.5
packaging>=26.0
pandas==2.3.3
-Pillow==12.1.1
+Pillow==12.3.0
psutil==7.2.2
-psycopg2==2.9.11
+psycopg2==2.9.12
pydantic>=2.11.4
pydantic-validation-decorator==0.1.5
-PyJWT[crypto]==2.11.0
-redis==7.1.0
-ruff==0.15.0
-SQLAlchemy[asyncio]==2.0.46
-sqlglot[rs]==28.10.0
-textual==8.2.5
+PyJWT[crypto]==2.13.0
+redis==8.1.0
+ruff==0.16.1
+SQLAlchemy[asyncio]==2.0.51
+sqlglot[rs]==30.14.0
+textual==8.2.8
user-agents==2.2.0
.
diff --git a/ruoyi-fastapi-backend/requirements.txt b/ruoyi-fastapi-backend/requirements.txt
index 7dd6d09..1af954c 100644
--- a/ruoyi-fastapi-backend/requirements.txt
+++ b/ruoyi-fastapi-backend/requirements.txt
@@ -1,24 +1,24 @@
aiofiles==25.1.0
-alembic==1.18.3
-APScheduler==3.11.2
-async-lru==2.1.0
+alembic==1.18.5
+APScheduler==3.11.3
+async-lru==2.3.0
asyncmy==0.2.11
bcrypt==5.0.0
-fastapi[all]==0.128.2
+fastapi[all]==0.141.1
loguru==0.7.3
openpyxl==3.1.5
packaging>=26.0
pandas==2.3.3
-Pillow==12.1.1
+Pillow==12.3.0
psutil==7.2.2
pydantic>=2.11.4
pydantic-validation-decorator==0.1.5
-PyJWT[crypto]==2.11.0
-PyMySQL==1.1.2
-redis==7.1.0
-ruff==0.15.0
-SQLAlchemy[asyncio]==2.0.46
-sqlglot[rs]==28.10.0
-textual==8.2.5
+PyJWT[crypto]==2.13.0
+PyMySQL==1.2.0
+redis==8.1.0
+ruff==0.16.1
+SQLAlchemy[asyncio]==2.0.51
+sqlglot[rs]==30.14.0
+textual==8.2.8
user-agents==2.2.0
.
diff --git a/ruoyi-fastapi-frontend/package.json b/ruoyi-fastapi-frontend/package.json
index 2cb285a..2343678 100644
--- a/ruoyi-fastapi-frontend/package.json
+++ b/ruoyi-fastapi-frontend/package.json
@@ -29,8 +29,9 @@
"@antv/g2plot": "^2.4.31",
"@antv/infographic": "^0.2.13",
"@riophae/vue-treeselect": "0.4.0",
+ "@terrastruct/d2": ">=0.1.33",
"ant-design-vue": "^1.7.8",
- "axios": "0.30.2",
+ "axios": "0.30.3",
"clipboard": "2.0.8",
"core-js": "3.37.1",
"echarts": "5.4.0",
@@ -42,14 +43,15 @@
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"katex": ">=0.16.27",
- "markstream-vue2": "^0.0.18",
- "mermaid": ">=11.12.2",
+ "markstream-vue2": "^0.0.50",
+ "mermaid": ">=11.15.0",
"nprogress": "0.2.0",
"quill": "2.0.2",
"screenfull": "5.0.2",
"shiki": "^3.21.0",
"sortablejs": "1.10.2",
- "stream-markdown": ">=0.0.14",
+ "stream-markdown": ">=0.0.16",
+ "stream-monaco": ">=0.0.48",
"uuid": "^8.3.2",
"viser-vue": "^2.4.8",
"vue": "2.7.16",
diff --git a/ruoyi-fastapi-frontend/plugins/ai/README.md b/ruoyi-fastapi-frontend/plugins/ai/README.md
index 0fd9a57..bc890f5 100644
--- a/ruoyi-fastapi-frontend/plugins/ai/README.md
+++ b/ruoyi-fastapi-frontend/plugins/ai/README.md
@@ -55,10 +55,12 @@ plugins/ai/
- `markstream-vue2`
- `stream-markdown`
+- `stream-monaco`
- `shiki`
- `mermaid`
- `katex`
- `@antv/infographic`
+- `@terrastruct/d2`
## 开发约定
diff --git a/ruoyi-fastapi-frontend/plugins/ai/views/chat/components/AiMessage.vue b/ruoyi-fastapi-frontend/plugins/ai/views/chat/components/AiMessage.vue
index 4a9a724..18372e4 100644
--- a/ruoyi-fastapi-frontend/plugins/ai/views/chat/components/AiMessage.vue
+++ b/ruoyi-fastapi-frontend/plugins/ai/views/chat/components/AiMessage.vue
@@ -14,11 +14,23 @@
>
-
+
-
+
Date: Sat, 1 Aug 2026 18:23:36 +0800
Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=90=8E=E7=AB=AF?=
=?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=BC=82=E5=B8=B8=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../cli/groups/app/controller.py | 25 +++----
.../cli/runtime/app/service.py | 25 +++----
.../tests/cli/runtime/test_app_runtime.py | 70 +++++++++++++++++++
.../plugins/sample_plugins/test_ai_plugin.py | 40 ++++++-----
4 files changed, 118 insertions(+), 42 deletions(-)
diff --git a/ruoyi-fastapi-backend/cli/groups/app/controller.py b/ruoyi-fastapi-backend/cli/groups/app/controller.py
index 2e4a4e8..17f6582 100644
--- a/ruoyi-fastapi-backend/cli/groups/app/controller.py
+++ b/ruoyi-fastapi-backend/cli/groups/app/controller.py
@@ -1,7 +1,7 @@
from collections import defaultdict
from typing import Any
-from fastapi.routing import APIRoute
+from fastapi.routing import APIRoute, iter_route_contexts
from cli.bootstrap import APP_BOOTSTRAP, AppBootstrapService
from cli.core import (
@@ -197,25 +197,26 @@ def _serialize_routes(
"""
normalized_method = method.upper().strip()
routes = []
- for route in app_instance.routes:
- if not isinstance(route, APIRoute):
+ for route_context in iter_route_contexts(app_instance.routes):
+ if not isinstance(route_context.original_route, APIRoute):
continue
- if not include_hidden and not route.include_in_schema:
+ if not include_hidden and not route_context.include_in_schema:
continue
- if path_prefix and not route.path.startswith(path_prefix):
+ route_path = route_context.path or ''
+ if path_prefix and not route_path.startswith(path_prefix):
continue
- route_methods = sorted(item for item in route.methods if item not in {'HEAD', 'OPTIONS'})
+ route_methods = sorted(item for item in (route_context.methods or set()) if item not in {'HEAD', 'OPTIONS'})
if normalized_method and normalized_method not in route_methods:
continue
routes.append(
{
- 'path': route.path,
+ 'path': route_path,
'methods': route_methods,
- 'name': route.name,
- 'summary': route.summary or '',
- 'operationId': route.operation_id or '',
- 'tags': route.tags or [],
- 'includeInSchema': route.include_in_schema,
+ 'name': route_context.name,
+ 'summary': route_context.summary or '',
+ 'operationId': route_context.operation_id or '',
+ 'tags': route_context.tags or [],
+ 'includeInSchema': route_context.include_in_schema,
}
)
return sorted(routes, key=lambda item: (item['path'], ','.join(item['methods'])))
diff --git a/ruoyi-fastapi-backend/cli/runtime/app/service.py b/ruoyi-fastapi-backend/cli/runtime/app/service.py
index 3f6b273..a26a03f 100644
--- a/ruoyi-fastapi-backend/cli/runtime/app/service.py
+++ b/ruoyi-fastapi-backend/cli/runtime/app/service.py
@@ -1,7 +1,7 @@
from collections import defaultdict
from typing import Any
-from fastapi.routing import APIRoute
+from fastapi.routing import APIRoute, iter_route_contexts
from cli.runtime.base import RUNTIME_ENVIRONMENT, RuntimeEnvironmentService
@@ -89,25 +89,26 @@ def get_app_routes_snapshot(
"""
normalized_method = method.upper().strip()
routes: list[dict[str, Any]] = []
- for route in self.build_app_instance().routes:
- if not isinstance(route, APIRoute):
+ for route_context in iter_route_contexts(self.build_app_instance().routes):
+ if not isinstance(route_context.original_route, APIRoute):
continue
- if not include_hidden and not route.include_in_schema:
+ if not include_hidden and not route_context.include_in_schema:
continue
- if path_prefix and not route.path.startswith(path_prefix):
+ route_path = route_context.path or ''
+ if path_prefix and not route_path.startswith(path_prefix):
continue
- route_methods = sorted(item for item in route.methods if item not in {'HEAD', 'OPTIONS'})
+ route_methods = sorted(item for item in (route_context.methods or set()) if item not in {'HEAD', 'OPTIONS'})
if normalized_method and normalized_method not in route_methods:
continue
routes.append(
{
- 'path': route.path,
+ 'path': route_path,
'methods': route_methods,
- 'name': route.name,
- 'summary': route.summary or '',
- 'operationId': route.operation_id or '',
- 'tags': route.tags or [],
- 'includeInSchema': route.include_in_schema,
+ 'name': route_context.name,
+ 'summary': route_context.summary or '',
+ 'operationId': route_context.operation_id or '',
+ 'tags': route_context.tags or [],
+ 'includeInSchema': route_context.include_in_schema,
}
)
routes.sort(key=lambda item: (item['path'], ','.join(item['methods'])))
diff --git a/ruoyi-fastapi-backend/tests/cli/runtime/test_app_runtime.py b/ruoyi-fastapi-backend/tests/cli/runtime/test_app_runtime.py
index 7d6443d..d470776 100644
--- a/ruoyi-fastapi-backend/tests/cli/runtime/test_app_runtime.py
+++ b/ruoyi-fastapi-backend/tests/cli/runtime/test_app_runtime.py
@@ -1,7 +1,9 @@
from types import SimpleNamespace
+from fastapi import APIRouter, FastAPI
from pytest import MonkeyPatch
+from cli.groups.app.controller import AppCommandController
from cli.runtime.app import AppRuntimeService
from cli.runtime.app.gateway import AppInfrastructureGateway
from cli.runtime.app.support import AppSnapshotSupport
@@ -10,6 +12,40 @@
REDIS_PORT = 6379
+def _build_app_with_included_router() -> FastAPI:
+ app = FastAPI()
+ router = APIRouter()
+
+ @router.get(
+ '/visible',
+ name='visible_route',
+ summary='Visible route',
+ operation_id='visibleRoute',
+ tags=['route'],
+ )
+ async def visible_route() -> dict[str, bool]:
+ return {'ok': True}
+
+ @router.get('/hidden', include_in_schema=False)
+ async def hidden_route() -> dict[str, bool]:
+ return {'ok': True}
+
+ app.include_router(router, prefix='/api', tags=['included'])
+ return app
+
+
+def _expected_visible_route() -> dict[str, object]:
+ return {
+ 'path': '/api/visible',
+ 'methods': ['GET'],
+ 'name': 'visible_route',
+ 'summary': 'Visible route',
+ 'operationId': 'visibleRoute',
+ 'tags': ['included', 'route'],
+ 'includeInSchema': True,
+ }
+
+
class FakeRuntimeEnvironment(RuntimeEnvironmentService):
"""
模拟运行时环境服务。
@@ -159,3 +195,37 @@ def _fake_get_server_module() -> FakeServerModule:
payload = service.build_app_instance()
assert payload == {'app': 'ok'}
+
+
+def test_app_runtime_service_expands_included_router_routes() -> None:
+ app = _build_app_with_included_router()
+ gateway = AppInfrastructureGateway()
+ service = AppRuntimeService(
+ runtime_environment=FakeRuntimeEnvironment(),
+ infrastructure_gateway=gateway,
+ )
+ fake_server_module = SimpleNamespace(create_app=lambda: app)
+
+ def _fake_get_server_module() -> SimpleNamespace:
+ return fake_server_module
+
+ object.__setattr__(gateway, 'get_server_module', _fake_get_server_module)
+
+ payload = service.get_app_routes_snapshot('dev')
+ hidden_payload = service.get_app_routes_snapshot('dev', include_hidden=True)
+
+ assert payload['routes'] == [_expected_visible_route()]
+ assert payload['count'] == 1
+ assert [route['path'] for route in hidden_payload['routes']] == ['/api/hidden', '/api/visible']
+ assert [route['includeInSchema'] for route in hidden_payload['routes']] == [False, True]
+
+
+def test_app_command_controller_serializes_included_router_routes() -> None:
+ app = _build_app_with_included_router()
+
+ routes = AppCommandController._serialize_routes(app)
+ hidden_routes = AppCommandController._serialize_routes(app, include_hidden=True)
+
+ assert routes == [_expected_visible_route()]
+ assert [route['path'] for route in hidden_routes] == ['/api/hidden', '/api/visible']
+ assert [route['includeInSchema'] for route in hidden_routes] == [False, True]
diff --git a/ruoyi-fastapi-backend/tests/plugins/sample_plugins/test_ai_plugin.py b/ruoyi-fastapi-backend/tests/plugins/sample_plugins/test_ai_plugin.py
index 35299e3..aa35f96 100644
--- a/ruoyi-fastapi-backend/tests/plugins/sample_plugins/test_ai_plugin.py
+++ b/ruoyi-fastapi-backend/tests/plugins/sample_plugins/test_ai_plugin.py
@@ -28,35 +28,39 @@
'ai:chat:list',
}
EXPECTED_AI_PYTHON_DEPENDENCIES = [
- 'agno==2.4.8',
- 'anthropic==0.78.0',
- 'cerebras-cloud-sdk==1.67.0',
- 'cohere==5.20.4',
- 'google-genai==1.62.0',
- 'groq==1.0.0',
- 'litellm==1.81.8',
+ 'agno==2.8.6',
+ 'anthropic==0.120.2',
+ 'cerebras-cloud-sdk==1.91.0',
+ 'cohere==7.0.8',
+ 'google-genai==2.16.0',
+ 'groq==1.6.0',
+ 'litellm==1.94.0',
'llama-api-client==0.6.0',
- 'mistralai==1.12.0',
- 'ollama==0.6.1',
- 'openai==2.17.0',
- 'portkey-ai==2.1.0',
+ 'mistralai==2.8.0',
+ 'ollama==0.6.2',
+ 'openai==2.52.0',
+ 'portkey-ai==2.3.4',
]
EXPECTED_AI_VUE2_NPM_DEPENDENCIES = [
'@antv/infographic^0.2.13',
+ '@terrastruct/d2>=0.1.33',
'katex>=0.16.27',
- 'markstream-vue2^0.0.18',
- 'mermaid>=11.12.2',
+ 'markstream-vue2^0.0.50',
+ 'mermaid>=11.15.0',
'shiki^3.21.0',
- 'stream-markdown>=0.0.14',
+ 'stream-markdown>=0.0.16',
+ 'stream-monaco>=0.0.48',
]
EXPECTED_AI_VUE3_NPM_DEPENDENCIES = [
'@antv/infographic^0.2.13',
+ '@terrastruct/d2>=0.1.33',
'katex>=0.16.27',
- 'markstream-vue>=0.0.7-beta.6',
- 'mermaid>=11.12.2',
+ 'markstream-vue>=1.0.9-beta.2',
+ 'mermaid>=11.15.0',
'shiki^3.21.0',
- 'stream-markdown>=0.0.14',
- 'stream-monaco>=0.0.17',
+ 'stream-diffs>=0.0.2',
+ 'stream-markdown>=0.0.16',
+ 'stream-monaco>=0.0.48',
]
EXPECTED_AI_VUE3_NPM_DEV_DEPENDENCIES = ['vite-plugin-monaco-editor-esm==2.0.2']
EXPECTED_DEFAULT_NUM_HISTORY_RUNS = 3