Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
21f9822
✨ Abstract Storage SDK
Phinease Nov 12, 2025
8009cdc
Revert "✨[Request] Abstract Storage SDK"
Phinease Nov 13, 2025
bbd7afa
🚚 Revert "✨ Abstract Storage SDK"
Phinease Nov 13, 2025
d053fe1
add codeql.yml
WMC001 Nov 14, 2025
ac56e1d
🐛 Bugfix: generate button in Agent config page returns error: Empty A…
Jasonxia007 Nov 14, 2025
0b10478
♻️ Imporvement: nexent-data-process now takes less memory (down to ~1…
Jasonxia007 Nov 14, 2025
b2419ac
Merge remote-tracking branch 'origin/release/v1.7.5.3' into release/v…
WMC001 Nov 14, 2025
9c165e6
✨ Release/v1.7.5.3
Phinease Nov 14, 2025
c831419
🐛 Bugfix: ray initialize failed
Jasonxia007 Nov 17, 2025
93fcd68
🐛 fix ray initialize failed
Phinease Nov 17, 2025
d666c6c
⭐️ Release/v1.7.5.3-hotfix
Phinease Nov 17, 2025
c5473a6
Merge pull request #1775 from ModelEngine-Group/release/v1.7.6
Phinease Nov 21, 2025
3b2cdeb
🐛 Bugfix: agent tools save or load parameters failed #1780 from Model…
WMC001 Nov 21, 2025
e27d265
Merge pull request #1781 from ModelEngine-Group/release/v1.7.6
Phinease Nov 21, 2025
a6dabbf
📝 Update multimodal tool description from ModelEngine-Group/release/v…
WMC001 Nov 29, 2025
4c1dcff
[release] 🐛 Front-end development and optimization of market interfac…
WMC001 Nov 29, 2025
c09476d
🐛 Bugfix: single added LLM model won't be saved automatically
WMC001 Nov 29, 2025
09da4ba
⭐️ Release/v1.7.7
Phinease Nov 29, 2025
f5bef9a
Merge branch 'main' into release/v1.7.7.1
WMC001 Dec 5, 2025
ffd4b5d
Bugfix: Build frontend arm image failed from ModelEngine-Group/wmc/bu…
WMC001 Dec 5, 2025
0f16d38
Merge pull request #2031 from ModelEngine-Group/wmc/bugfix_1117
WMC001 Dec 5, 2025
7691fbf
Merge pull request #2029 from ModelEngine-Group/wz/develop_fix_datama…
WMC001 Dec 5, 2025
f1f02b6
Release/v1.7.7.1 from ModelEngine-Group/release/v1.7.7.1
WMC001 Dec 5, 2025
60fb82a
✨ Release/v1.7.8
Phinease Dec 12, 2025
1313e88
♻️ Revert package declare from ModelEngine-Group/xyq/unify_dialog&modal
WMC001 Dec 19, 2025
7bcc859
📝 Updates app version from ModelEngine-Group/wmc/bugfix_1117
WMC001 Dec 19, 2025
9da494a
⭐️ Release/v1.7.8.1
Phinease Dec 19, 2025
24c8cbb
feat: Add PathologyAI - 智能病理诊断助手
hud0567 Dec 21, 2025
7ef7750
⭐️ Add PathologyAI - 智能病理诊断助手
Phinease Dec 25, 2025
d29aa16
Merge branch 'main' into release/v1.7.9
WMC001 Dec 27, 2025
d4afa9c
⭐️ Release/v1.7.9
Phinease Dec 27, 2025
fc23afe
✨ Add SDK publish workflow for PyPI with OIDC authentication
Phinease Jan 5, 2026
f1b4f58
🐛 Adjust main page layout
WMC001 Jan 8, 2026
a0efbce
bugfix sync modle engine model icon
xuyaqist Jan 8, 2026
137291b
Revert "bugfix sync modle engine model icon"
xuyaqist Jan 8, 2026
b91149a
[release] 🐛 Remove cache of tenant config
WMC001 Jan 9, 2026
e175c33
🐛 Bugfix in createmode cannot edit tool & cannot change agent model id
WMC001 Jan 9, 2026
eb18e35
Release/v1.7.9.1
WMC001 Jan 9, 2026
38e304b
Release/v1.7.9.2
WMC001 Jan 16, 2026
3d8c13d
Release/v1.7.9.3
WMC001 Jan 23, 2026
c7f4a15
Add CodeQL analysis workflow configuration
WMC001 Jan 26, 2026
1675714
Merge branch 'main' into release/v1.7.10
WMC001 Jan 31, 2026
d7aa26b
Release/v1.7.10
WMC001 Jan 31, 2026
eb3a209
prompt_template
2h0u4n Feb 11, 2026
0feb9da
增加提示词模板功能
2h0u4n Feb 11, 2026
f4cca3c
prompt template
2h0u4n Mar 2, 2026
0acec40
Merge branch 'develop' into za_prompt_template
2h0u4n Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions .github/workflows/codeql_main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '40 13 * * 6'

jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write

# required to fetch internal or private CodeQL packs
packages: read

# only required for workflows in private repositories
actions: read
contents: read

strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
- language: javascript-typescript
build-mode: none
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4

# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- name: Run manual build steps
if: matrix.build-mode == 'manual'
shell: bash
run: |
echo 'If you are using a "manual" build mode for one or more of the' \
'languages you are analyzing, replace this with the commands to build' \
'your code, for example:'
echo ' make bootstrap'
echo ' make release'
exit 1

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
2 changes: 2 additions & 0 deletions backend/apps/config_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from apps.mock_user_management_app import router as mock_user_management_router
from apps.model_managment_app import router as model_manager_router
from apps.prompt_app import router as prompt_router
from apps.prompt_template_app import router as prompt_template_router
from apps.remote_mcp_app import router as remote_mcp_router
from apps.tenant_config_app import router as tenant_config_router
from apps.tool_config_app import router as tool_config_router
Expand Down Expand Up @@ -50,6 +51,7 @@

app.include_router(summary_router)
app.include_router(prompt_router)
app.include_router(prompt_template_router)
app.include_router(tenant_config_router)
app.include_router(remote_mcp_router)
app.include_router(tenant_router)
Expand Down
108 changes: 108 additions & 0 deletions backend/apps/prompt_template_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import logging
from http import HTTPStatus
from typing import Optional

from fastapi import APIRouter, Header, HTTPException, Query
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse

from consts.model import (
PromptTemplateCreateRequest,
PromptTemplateUpdateRequest,
PromptTemplateDeleteRequest,
)
from services.prompt_template_service import (
list_templates,
create_template,
update_template,
delete_template,
)
from utils.auth_utils import get_current_user_id

router = APIRouter(prefix="/prompt_template")
logger = logging.getLogger("prompt_template_app")


@router.get("/list")
async def list_prompt_templates_api(
keyword: Optional[str] = Query(default=None),
authorization: Optional[str] = Header(None)
):
try:
user_id, tenant_id = get_current_user_id(authorization)
templates = list_templates(tenant_id=tenant_id, user_id=user_id, keyword=keyword)
return JSONResponse(
status_code=HTTPStatus.OK,
content={"message": "Templates retrieved successfully", "data": jsonable_encoder(templates)}
)
except Exception as e:
logger.error(f"Failed to list prompt templates: {e}")
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Failed to list prompt templates")


@router.post("/create")
async def create_prompt_template_api(
request: PromptTemplateCreateRequest,
authorization: Optional[str] = Header(None)
):
try:
user_id, tenant_id = get_current_user_id(authorization)
template = create_template(tenant_id=tenant_id, user_id=user_id, payload=request.dict())
return JSONResponse(
status_code=HTTPStatus.CREATED,
content={"message": "Template created successfully", "data": jsonable_encoder(template)}
)
except Exception as e:
logger.error(f"Failed to create prompt template: {e}")
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Failed to create prompt template")


@router.post("/update")
async def update_prompt_template_api(
request: PromptTemplateUpdateRequest,
authorization: Optional[str] = Header(None)
):
try:
user_id, tenant_id = get_current_user_id(authorization)
template = update_template(
tenant_id=tenant_id,
user_id=user_id,
template_id=request.template_id,
payload=request.dict(exclude={"template_id"})
)
return JSONResponse(
status_code=HTTPStatus.OK,
content={"message": "Template updated successfully", "data": jsonable_encoder(template)}
)
except ValueError as e:
logger.warning(f"Prompt template not found: {e}")
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Prompt template not found")
except Exception as e:
logger.error(f"Failed to update prompt template: {e}")
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Failed to update prompt template")


@router.post("/delete")
async def delete_prompt_template_api(
request: PromptTemplateDeleteRequest,
authorization: Optional[str] = Header(None)
):
try:
user_id, tenant_id = get_current_user_id(authorization)
delete_template(tenant_id=tenant_id, user_id=user_id, template_id=request.template_id)
return JSONResponse(
status_code=HTTPStatus.OK,
content={"message": "Template deleted successfully"}
)
except ValueError as e:
logger.warning(f"Prompt template not found: {e}")
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Prompt template not found")
except Exception as e:
logger.error(f"Failed to delete prompt template: {e}")
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail="Failed to delete prompt template")
17 changes: 17 additions & 0 deletions backend/consts/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,23 @@ class GenerateTitleRequest(BaseModel):
question: str


class PromptTemplateCreateRequest(BaseModel):
name: str
description: Optional[str] = None
prompt_text: str


class PromptTemplateUpdateRequest(BaseModel):
template_id: int
name: Optional[str] = None
description: Optional[str] = None
prompt_text: Optional[str] = None


class PromptTemplateDeleteRequest(BaseModel):
template_id: int


# used in agent/search agent/update for save agent info
class AgentInfoRequest(BaseModel):
agent_id: Optional[int] = None
Expand Down
17 changes: 17 additions & 0 deletions backend/database/db_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,23 @@ class TenantConfig(TableBase):
config_value = Column(Text, doc="the value of the config")


class PromptTemplate(TableBase):
"""
Prompt template management table
"""
__tablename__ = "prompt_template_t"
__table_args__ = {"schema": SCHEMA}

template_id = Column(Integer, Sequence(
"prompt_template_t_template_id_seq", schema=SCHEMA), primary_key=True, nullable=False, doc="Template ID")
name = Column(String(200), doc="Template name")
description = Column(String(2000), doc="Template description")
prompt_text = Column(Text, doc="Template prompt text")
is_builtin = Column(Boolean, default=False,
doc="Whether this template is built-in")
tenant_id = Column(String(100), doc="Tenant ID")


class MemoryUserConfig(TableBase):
"""
Tenant configuration information table
Expand Down
100 changes: 100 additions & 0 deletions backend/database/prompt_template_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import logging
from typing import List, Optional

from sqlalchemy import or_

from database.client import get_db_session, as_dict, filter_property
from database.db_models import PromptTemplate

logger = logging.getLogger("prompt_template_db")


def list_prompt_templates(tenant_id: str, keyword: Optional[str] = None) -> List[dict]:
with get_db_session() as session:
query = session.query(PromptTemplate).filter(
PromptTemplate.tenant_id == tenant_id,
PromptTemplate.delete_flag != "Y"
)
if keyword:
like_keyword = f"%{keyword}%"
query = query.filter(
or_(
PromptTemplate.name.ilike(like_keyword),
PromptTemplate.description.ilike(like_keyword),
PromptTemplate.prompt_text.ilike(like_keyword),
)
)
templates = query.order_by(PromptTemplate.update_time.desc()).all()
return [as_dict(t) for t in templates]


def get_prompt_template_by_id(template_id: int, tenant_id: str) -> Optional[dict]:
with get_db_session() as session:
template = session.query(PromptTemplate).filter(
PromptTemplate.template_id == template_id,
PromptTemplate.tenant_id == tenant_id,
PromptTemplate.delete_flag != "Y"
).first()
return as_dict(template) if template else None


def create_prompt_template(
template_info: dict,
tenant_id: str,
user_id: str
) -> dict:
info_with_metadata = dict(template_info)
info_with_metadata.update({
"tenant_id": tenant_id,
"created_by": user_id,
"updated_by": user_id,
})
with get_db_session() as session:
new_template = PromptTemplate(
**filter_property(info_with_metadata, PromptTemplate)
)
new_template.delete_flag = "N"
session.add(new_template)
session.flush()
return as_dict(new_template)


def update_prompt_template(
template_id: int,
template_info: dict,
tenant_id: str,
user_id: str
) -> dict:
with get_db_session() as session:
template = session.query(PromptTemplate).filter(
PromptTemplate.template_id == template_id,
PromptTemplate.tenant_id == tenant_id,
PromptTemplate.delete_flag != "Y"
).first()
if not template:
raise ValueError("prompt template not found")

for key, value in filter_property(template_info, PromptTemplate).items():
if value is None:
continue
setattr(template, key, value)
template.updated_by = user_id
session.flush()
return as_dict(template)


def delete_prompt_template(
template_id: int,
tenant_id: str,
user_id: str
) -> None:
with get_db_session() as session:
template = session.query(PromptTemplate).filter(
PromptTemplate.template_id == template_id,
PromptTemplate.tenant_id == tenant_id,
PromptTemplate.delete_flag != "Y"
).first()
if not template:
raise ValueError("prompt template not found")
template.delete_flag = "Y"
template.updated_by = user_id
Loading