#!/usr/bin/env python3 # -*- coding: utf-8 -*- """作业 1 · 修复打开 Agent 配置页 Internal Server Error(精确打到 credential/info)。""" from __future__ import annotations import sys import _bootstrap # noqa: F401 import _config as C from dify_api import Dify REMOTE = "/app/api/services/tools/builtin_tools_manage_service.py" OLD = ''' def get_builtin_tool_provider_credential_info( tenant_id: str, provider: str, session: Session, user: Account | None = None, include_credential_ids: list[str] | None = None, ) -> ToolProviderCredentialInfoApiEntity: """ get builtin tool provider credential info """ provider_controller = ToolManager.get_builtin_provider(provider, tenant_id) ''' NEW = ''' def get_builtin_tool_provider_credential_info( tenant_id: str, provider: str, session: Session, user: Account | None = None, include_credential_ids: list[str] | None = None, ) -> ToolProviderCredentialInfoApiEntity: """ get builtin tool provider credential info """ try: provider_controller = ToolManager.get_builtin_provider(provider, tenant_id) except Exception as exc: err = str(exc).lower() if type(exc).__name__ in ( "PluginNotFoundError", "ToolProviderNotFoundError", ) or "plugin not found" in err: logger.warning( "skip builtin credential/info for non-plugin provider %s: %s", provider, exc, ) return ToolProviderCredentialInfoApiEntity( supported_credential_types=[], is_oauth_custom_client_enabled=False, credentials=[], ) raise ''' def main() -> int: d = Dify(C.DIFY_EMAIL, C.DIFY_PASSWORD) try: d.login() img, _ = d.sh( "docker inspect %s --format '{{.Config.Image}}'" % C.DIFY_API_CTR ) image = img.strip() print("image", image) # 从镜像恢复原文件(上次误改了 list_builtin_tool_provider_tools) d.sh( "docker run --rm --entrypoint cat %s %s > /tmp/builtin_tools_orig.py" % (image, REMOTE) ) orig, _ = d.sh("wc -l /tmp/builtin_tools_orig.py; grep -c get_builtin_tool_provider_credential_info /tmp/builtin_tools_orig.py") print("orig", orig) d.sh("docker cp /tmp/builtin_tools_orig.py %s:%s" % (C.DIFY_API_CTR, REMOTE)) content, _ = d.sh("docker exec %s cat %s" % (C.DIFY_API_CTR, REMOTE)) if OLD not in content: print("恢复后仍找不到精确插入点") print("has func", "get_builtin_tool_provider_credential_info" in content) return 1 if "skip builtin credential/info for non-plugin provider" in content.split("get_builtin_tool_provider_credential_info", 1)[-1][:800]: print("目标函数已有补丁") else: patched = content.replace(OLD, NEW, 1) tmp = "/tmp/builtin_tools_patched.py" with d.sftp.open(tmp, "w") as f: f.write(patched) d.sh("docker cp %s %s:%s" % (tmp, C.DIFY_API_CTR, REMOTE)) print("已精确写入 credential_info 补丁") d.sh("docker restart %s" % C.DIFY_API_CTR) print("等待 api 起来...") d.sh( "for i in 1 2 3 4 5 6 7 8 9 10; do " "curl -sf -o /dev/null -m 3 http://127.0.0.1/console/api/setup || true; sleep 2; done" ) d.login() path = ( "/workspaces/current/tool-provider/builtin/%s/credential/info" % C.SERVER_STATUS_PROVIDER_ID ) r = d.get(path) print("GET", path, "HTTP", r.get("code")) print((r.get("text") or "")[:400]) ok_time = d.get("/workspaces/current/tool-provider/builtin/time/credential/info") print("time still", ok_time.get("code")) if r.get("code") != "200": return 1 print("[PASS] 刷新浏览器打开运维巡检 Agent 配置页,红条应消失。") return 0 finally: d.close() if __name__ == "__main__": sys.exit(main())