agent-Specialization/server/workflow_page.py
JOJO a2cf547400 feat(i18n): 后端用户可见消息国际化(zh/en 双语 + ui_locale 偏好持久化)
- 新增 modules/i18n.py:tr() + 进程级语言缓存 + modules/i18n_messages/ 域文案包自动聚合
- 新增 29 个域文案包,共 1153 条双语 key;90+ 源文件 1146 处用户可见消息 tr 化
- ui_locale 存入 personalization.json(用户级共享),前后端双向同步
- 前端匹配点双语兼容(history/shared/ChatArea/taskPolling/upload 等正则)
- 修复语言判等陷阱:审批等待加稳定 code 字段;conversation.py 不存在判等改双语 helper
- 边界:日志/prompt 注入/子智能体工具回填/容器内嵌脚本不迁移
2026-08-29 07:58:29 +08:00

98 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""工作流页面路由 + REST API。
- `/workflows` 工作流库列表页,返回主 SPA 入口,由前端 bootstrapRoute 识别路径
- `/workflow/<name>` 工作流编辑器页,同上
- `/api/workflows` 系列:工作流 CRUDWORKFLOW.md 落盘,见 modules/workflow_manager.py
"""
from __future__ import annotations
from flask import Blueprint, current_app, jsonify, request
from modules.workflow_manager import (
delete_workflow,
list_workflows,
load_workflow,
save_workflow,
)
from server.auth_helpers import api_login_required, login_required
from server.context import with_terminal
from modules.i18n import tr
workflow_page_bp = Blueprint("workflow_page", __name__)
@workflow_page_bp.route("/workflows")
@login_required
def workflow_library_page():
"""工作流库入口,返回与 /new 相同的 SPA index.html。"""
return current_app.send_static_file("index.html")
@workflow_page_bp.route("/workflow/<path:name>")
@login_required
def workflow_editor_page(name: str):
"""工作流编辑器入口,返回 SPA index.html 让前端路由处理。"""
return current_app.send_static_file("index.html")
# ---------------------------------------------------------------- REST API
@workflow_page_bp.route("/api/workflows", methods=["GET"])
@api_login_required
@with_terminal
def api_list_workflows(terminal, workspace, username):
"""工作流列表(内置 + 用户库双源合并,仅元信息)。"""
try:
return jsonify({"workflows": list_workflows(workspace.data_dir)})
except Exception as exc:
return jsonify({"error": tr("workflow_page.list_failed", error=exc)}), 500
@workflow_page_bp.route("/api/workflows/<path:name>", methods=["GET"])
@api_login_required
@with_terminal
def api_load_workflow(name: str, terminal, workspace, username):
"""加载完整工作流定义(用户库优先,其次内置)。"""
try:
return jsonify({"workflow": load_workflow(name, workspace.data_dir)})
except FileNotFoundError:
return jsonify({"error": tr("workflow_page.workflow_not_found", name=name)}), 404
except ValueError as exc:
return jsonify({"error": str(exc)}), 400
@workflow_page_bp.route("/api/workflows/<path:name>", methods=["PUT"])
@api_login_required
@with_terminal
def api_save_workflow(name: str, terminal, workspace, username):
"""保存工作流到用户库(原子写;结构 error 级校验不过则 400"""
data = request.get_json(silent=True)
if not isinstance(data, dict) or not isinstance(data.get("workflow"), dict):
return jsonify({"error": tr("workflow_page.missing_workflow_object")}), 400
wf = dict(data["workflow"])
wf["name"] = name # 名称以 URL 为准
try:
save_workflow(wf, workspace.data_dir)
return jsonify({"ok": True})
except ValueError as exc:
return jsonify({"error": str(exc)}), 400
except OSError as exc:
return jsonify({"error": tr("workflow_page.write_file_failed", error=exc)}), 500
@workflow_page_bp.route("/api/workflows/<path:name>", methods=["DELETE"])
@api_login_required
@with_terminal
def api_delete_workflow(name: str, terminal, workspace, username):
"""删除用户库中的工作流(内置示例不可删)。"""
try:
delete_workflow(name, workspace.data_dir)
return jsonify({"ok": True})
except FileNotFoundError:
return jsonify({"error": tr("workflow_page.workflow_not_found", name=name)}), 404
except ValueError as exc:
return jsonify({"error": str(exc)}), 400
except OSError as exc:
return jsonify({"error": tr("workflow_page.delete_failed", error=exc)}), 500